Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/SurfaceData.java
38829 views
1
/*
2
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.java2d;
27
28
import java.awt.Color;
29
import java.awt.Rectangle;
30
import java.awt.Transparency;
31
import java.awt.GraphicsConfiguration;
32
import java.awt.Image;
33
import java.awt.image.ColorModel;
34
import java.awt.image.IndexColorModel;
35
import java.awt.image.Raster;
36
37
import sun.java2d.loops.RenderCache;
38
import sun.java2d.loops.RenderLoops;
39
import sun.java2d.loops.CompositeType;
40
import sun.java2d.loops.SurfaceType;
41
import sun.java2d.loops.MaskFill;
42
import sun.java2d.loops.DrawLine;
43
import sun.java2d.loops.FillRect;
44
import sun.java2d.loops.DrawRect;
45
import sun.java2d.loops.DrawPolygons;
46
import sun.java2d.loops.DrawPath;
47
import sun.java2d.loops.FillPath;
48
import sun.java2d.loops.FillSpans;
49
import sun.java2d.loops.FillParallelogram;
50
import sun.java2d.loops.DrawParallelogram;
51
import sun.java2d.loops.FontInfo;
52
import sun.java2d.loops.DrawGlyphList;
53
import sun.java2d.loops.DrawGlyphListAA;
54
import sun.java2d.loops.DrawGlyphListLCD;
55
import sun.java2d.pipe.LoopPipe;
56
import sun.java2d.pipe.ShapeDrawPipe;
57
import sun.java2d.pipe.ParallelogramPipe;
58
import sun.java2d.pipe.CompositePipe;
59
import sun.java2d.pipe.GeneralCompositePipe;
60
import sun.java2d.pipe.SpanClipRenderer;
61
import sun.java2d.pipe.SpanShapeRenderer;
62
import sun.java2d.pipe.AAShapePipe;
63
import sun.java2d.pipe.AlphaPaintPipe;
64
import sun.java2d.pipe.AlphaColorPipe;
65
import sun.java2d.pipe.PixelToShapeConverter;
66
import sun.java2d.pipe.PixelToParallelogramConverter;
67
import sun.java2d.pipe.TextPipe;
68
import sun.java2d.pipe.TextRenderer;
69
import sun.java2d.pipe.AATextRenderer;
70
import sun.java2d.pipe.LCDTextRenderer;
71
import sun.java2d.pipe.SolidTextRenderer;
72
import sun.java2d.pipe.OutlineTextRenderer;
73
import sun.java2d.pipe.DrawImagePipe;
74
import sun.java2d.pipe.DrawImage;
75
import sun.awt.SunHints;
76
import sun.awt.image.SurfaceManager;
77
import sun.java2d.pipe.LoopBasedPipe;
78
79
/**
80
* This class provides various pieces of information relevant to a
81
* particular drawing surface. The information obtained from this
82
* object describes the pixels of a particular instance of a drawing
83
* surface and can only be shared among the various graphics objects
84
* that target the same BufferedImage or the same screen Component.
85
* <p>
86
* Each SurfaceData object holds a StateTrackableDelegate object
87
* which tracks both changes to the content of the pixels of this
88
* surface and changes to the overall state of the pixels - such
89
* as becoming invalid or losing the surface. The delegate is
90
* marked "dirty" whenever the setSurfaceLost() or invalidate()
91
* methods are called and should also be marked "dirty" by the
92
* rendering pipelines whenever they modify the pixels of this
93
* SurfaceData.
94
* <p>
95
* If you get a StateTracker from a SurfaceData and it reports
96
* that it is still "current", then you can trust that the pixels
97
* have not changed and that the SurfaceData is still valid and
98
* has not lost its underlying storage (surfaceLost) since you
99
* retrieved the tracker.
100
*/
101
public abstract class SurfaceData
102
implements Transparency, DisposerTarget, StateTrackable, Surface
103
{
104
private long pData;
105
private boolean valid;
106
private boolean surfaceLost; // = false;
107
private SurfaceType surfaceType;
108
private ColorModel colorModel;
109
110
private Object disposerReferent = new Object();
111
112
private static native void initIDs();
113
114
private Object blitProxyKey;
115
private StateTrackableDelegate stateDelegate;
116
117
static {
118
initIDs();
119
}
120
121
protected SurfaceData(SurfaceType surfaceType, ColorModel cm) {
122
this(State.STABLE, surfaceType, cm);
123
}
124
125
protected SurfaceData(State state, SurfaceType surfaceType, ColorModel cm) {
126
this(StateTrackableDelegate.createInstance(state), surfaceType, cm);
127
}
128
129
protected SurfaceData(StateTrackableDelegate trackable,
130
SurfaceType surfaceType, ColorModel cm)
131
{
132
this.stateDelegate = trackable;
133
this.colorModel = cm;
134
this.surfaceType = surfaceType;
135
valid = true;
136
}
137
138
protected SurfaceData(State state) {
139
this.stateDelegate = StateTrackableDelegate.createInstance(state);
140
valid = true;
141
}
142
143
/**
144
* Subclasses can set a "blit proxy key" which will be used
145
* along with the SurfaceManager.getCacheData() mechanism to
146
* store acceleration-compatible cached copies of source images.
147
* This key is a "tag" used to identify which cached copies
148
* are compatible with this destination SurfaceData.
149
* The getSourceSurfaceData() method uses this key to manage
150
* cached copies of a source image as described below.
151
* <p>
152
* The Object used as this key should be as unique as it needs
153
* to be to ensure that multiple acceleratible destinations can
154
* each store their cached copies separately under different keys
155
* without interfering with each other or getting back the wrong
156
* cached copy.
157
* <p>
158
* Many acceleratable SurfaceData objects can use their own
159
* GraphicsConfiguration as their proxy key as the GC object will
160
* typically be unique to a given screen and pixel format, but
161
* other rendering destinations may have more or less stringent
162
* sharing requirements. For instance, X11 pixmaps can be
163
* shared on a given screen by any GraphicsConfiguration that
164
* has the same depth and SurfaceType. Multiple such GCs with
165
* the same depth and SurfaceType can exist per screen so storing
166
* a different cached proxy for each would be a waste. One can
167
* imagine platforms where a single cached copy can be created
168
* and shared across all screens and pixel formats - such
169
* implementations could use a single heavily shared key Object.
170
*/
171
protected void setBlitProxyKey(Object key) {
172
// Caching is effectively disabled if we never have a proxy key
173
// since the getSourceSurfaceData() method only does caching
174
// if the key is not null.
175
if (SurfaceDataProxy.isCachingAllowed()) {
176
this.blitProxyKey = key;
177
}
178
}
179
180
/**
181
* This method is called on a destination SurfaceData to choose
182
* the best SurfaceData from a source Image for an imaging
183
* operation, with help from its SurfaceManager.
184
* The method may determine that the default SurfaceData was
185
* really the best choice in the first place, or it may decide
186
* to use a cached surface. Some general decisions about whether
187
* acceleration is enabled are made by this method, but any
188
* decision based on the type of the source image is made in
189
* the makeProxyFor method below when it comes up with the
190
* appropriate SurfaceDataProxy instance.
191
* The parameters describe the type of imaging operation being performed.
192
* <p>
193
* If a blitProxyKey was supplied by the subclass then it is
194
* used to potentially override the choice of source SurfaceData.
195
* The outline of this process is:
196
* <ol>
197
* <li> Image pipeline asks destSD to find an appropriate
198
* srcSD for a given source Image object.
199
* <li> destSD gets the SurfaceManager of the source Image
200
* and first retrieves the default SD from it using
201
* getPrimarySurfaceData()
202
* <li> destSD uses its "blit proxy key" (if set) to look for
203
* some cached data stored in the source SurfaceManager
204
* <li> If the cached data is null then makeProxyFor() is used
205
* to create some cached data which is stored back in the
206
* source SurfaceManager under the same key for future uses.
207
* <li> The cached data will be a SurfaceDataProxy object.
208
* <li> The SurfaceDataProxy object is then consulted to
209
* return a replacement SurfaceData object (typically
210
* a cached copy if appropriate, or the original if not).
211
* </ol>
212
*/
213
public SurfaceData getSourceSurfaceData(Image img,
214
int txtype,
215
CompositeType comp,
216
Color bgColor)
217
{
218
SurfaceManager srcMgr = SurfaceManager.getManager(img);
219
SurfaceData srcData = srcMgr.getPrimarySurfaceData();
220
if (img.getAccelerationPriority() > 0.0f &&
221
blitProxyKey != null)
222
{
223
SurfaceDataProxy sdp =
224
(SurfaceDataProxy) srcMgr.getCacheData(blitProxyKey);
225
if (sdp == null || !sdp.isValid()) {
226
if (srcData.getState() == State.UNTRACKABLE) {
227
sdp = SurfaceDataProxy.UNCACHED;
228
} else {
229
sdp = makeProxyFor(srcData);
230
}
231
srcMgr.setCacheData(blitProxyKey, sdp);
232
}
233
srcData = sdp.replaceData(srcData, txtype, comp, bgColor);
234
}
235
return srcData;
236
}
237
238
/**
239
* This method is called on a destination SurfaceData to choose
240
* a proper SurfaceDataProxy subclass for a source SurfaceData
241
* to use to control when and with what surface to override a
242
* given image operation. The argument is the default SurfaceData
243
* for the source Image.
244
* <p>
245
* The type of the return object is chosen based on the
246
* acceleration capabilities of this SurfaceData and the
247
* type of the given source SurfaceData object.
248
* <p>
249
* In some cases the original SurfaceData will always be the
250
* best choice to use to blit to this SurfaceData. This can
251
* happen if the source image is a hardware surface of the
252
* same type as this one and so acceleration will happen without
253
* any caching. It may also be the case that the source image
254
* can never be accelerated on this SurfaceData - for example
255
* because it is translucent and there are no accelerated
256
* translucent image ops for this surface.
257
* <p>
258
* In those cases there is a special SurfaceDataProxy.UNCACHED
259
* instance that represents a NOP for caching purposes - it
260
* always returns the original sourceSD object as the replacement
261
* copy so no caching is ever performed.
262
*/
263
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
264
return SurfaceDataProxy.UNCACHED;
265
}
266
267
/**
268
* Extracts the SurfaceManager from the given Image, and then
269
* returns the SurfaceData object that would best be suited as the
270
* destination surface in some rendering operation.
271
*/
272
public static SurfaceData getPrimarySurfaceData(Image img) {
273
SurfaceManager sMgr = SurfaceManager.getManager(img);
274
return sMgr.getPrimarySurfaceData();
275
}
276
277
/**
278
* Restores the contents of the given Image and then returns the new
279
* SurfaceData object in use by the Image's SurfaceManager.
280
*/
281
public static SurfaceData restoreContents(Image img) {
282
SurfaceManager sMgr = SurfaceManager.getManager(img);
283
return sMgr.restoreContents();
284
}
285
286
public State getState() {
287
return stateDelegate.getState();
288
}
289
290
public StateTracker getStateTracker() {
291
return stateDelegate.getStateTracker();
292
}
293
294
/**
295
* Marks this surface as dirty.
296
*/
297
public final void markDirty() {
298
stateDelegate.markDirty();
299
}
300
301
/**
302
* Sets the value of the surfaceLost variable, which indicates whether
303
* something has happened to the rendering surface such that it needs
304
* to be restored and re-rendered.
305
*/
306
public void setSurfaceLost(boolean lost) {
307
surfaceLost = lost;
308
stateDelegate.markDirty();
309
}
310
311
public boolean isSurfaceLost() {
312
return surfaceLost;
313
}
314
315
/**
316
* Returns a boolean indicating whether or not this SurfaceData is valid.
317
*/
318
public final boolean isValid() {
319
return valid;
320
}
321
322
public Object getDisposerReferent() {
323
return disposerReferent;
324
}
325
326
public long getNativeOps() {
327
return pData;
328
}
329
330
/**
331
* Sets this SurfaceData object to the invalid state. All Graphics
332
* objects must get a new SurfaceData object via the refresh method
333
* and revalidate their pipelines before continuing.
334
*/
335
public void invalidate() {
336
valid = false;
337
stateDelegate.markDirty();
338
}
339
340
/**
341
* Certain changes in the configuration of a surface require the
342
* invalidation of existing associated SurfaceData objects and
343
* the creation of brand new ones. These changes include size,
344
* ColorModel, or SurfaceType. Existing Graphics objects
345
* which are directed at such surfaces, however, must continue
346
* to render to them even after the change occurs underneath
347
* the covers. The getReplacement() method is called from
348
* SunGraphics2D.revalidateAll() when the associated SurfaceData
349
* is found to be invalid so that a Graphics object can continue
350
* to render to the surface in its new configuration.
351
*
352
* Such changes only tend to happen to window based surfaces since
353
* most image based surfaces never change size or pixel format.
354
* Even VolatileImage objects never change size and they only
355
* change their pixel format when manually validated against a
356
* new GraphicsConfiguration, at which point old Graphics objects
357
* are no longer expected to render to them after the validation
358
* step. Thus, only window based surfaces really need to deal
359
* with this form of replacement.
360
*/
361
public abstract SurfaceData getReplacement();
362
363
protected static final LoopPipe colorPrimitives;
364
365
public static final TextPipe outlineTextRenderer;
366
public static final TextPipe solidTextRenderer;
367
public static final TextPipe aaTextRenderer;
368
public static final TextPipe lcdTextRenderer;
369
370
protected static final AlphaColorPipe colorPipe;
371
protected static final PixelToShapeConverter colorViaShape;
372
protected static final PixelToParallelogramConverter colorViaPgram;
373
protected static final TextPipe colorText;
374
protected static final CompositePipe clipColorPipe;
375
protected static final TextPipe clipColorText;
376
protected static final AAShapePipe AAColorShape;
377
protected static final PixelToParallelogramConverter AAColorViaShape;
378
protected static final PixelToParallelogramConverter AAColorViaPgram;
379
protected static final AAShapePipe AAClipColorShape;
380
protected static final PixelToParallelogramConverter AAClipColorViaShape;
381
382
protected static final CompositePipe paintPipe;
383
protected static final SpanShapeRenderer paintShape;
384
protected static final PixelToShapeConverter paintViaShape;
385
protected static final TextPipe paintText;
386
protected static final CompositePipe clipPaintPipe;
387
protected static final TextPipe clipPaintText;
388
protected static final AAShapePipe AAPaintShape;
389
protected static final PixelToParallelogramConverter AAPaintViaShape;
390
protected static final AAShapePipe AAClipPaintShape;
391
protected static final PixelToParallelogramConverter AAClipPaintViaShape;
392
393
protected static final CompositePipe compPipe;
394
protected static final SpanShapeRenderer compShape;
395
protected static final PixelToShapeConverter compViaShape;
396
protected static final TextPipe compText;
397
protected static final CompositePipe clipCompPipe;
398
protected static final TextPipe clipCompText;
399
protected static final AAShapePipe AACompShape;
400
protected static final PixelToParallelogramConverter AACompViaShape;
401
protected static final AAShapePipe AAClipCompShape;
402
protected static final PixelToParallelogramConverter AAClipCompViaShape;
403
404
protected static final DrawImagePipe imagepipe;
405
406
// Utility subclass to add the LoopBasedPipe tagging interface
407
static class PixelToShapeLoopConverter
408
extends PixelToShapeConverter
409
implements LoopBasedPipe
410
{
411
public PixelToShapeLoopConverter(ShapeDrawPipe pipe) {
412
super(pipe);
413
}
414
}
415
416
// Utility subclass to add the LoopBasedPipe tagging interface
417
static class PixelToPgramLoopConverter
418
extends PixelToParallelogramConverter
419
implements LoopBasedPipe
420
{
421
public PixelToPgramLoopConverter(ShapeDrawPipe shapepipe,
422
ParallelogramPipe pgrampipe,
423
double minPenSize,
424
double normPosition,
425
boolean adjustfill)
426
{
427
super(shapepipe, pgrampipe, minPenSize, normPosition, adjustfill);
428
}
429
}
430
431
private static PixelToParallelogramConverter
432
makeConverter(AAShapePipe renderer,
433
ParallelogramPipe pgrampipe)
434
{
435
return new PixelToParallelogramConverter(renderer,
436
pgrampipe,
437
1.0/8.0, 0.499,
438
false);
439
}
440
441
private static PixelToParallelogramConverter
442
makeConverter(AAShapePipe renderer)
443
{
444
return makeConverter(renderer, renderer);
445
}
446
447
static {
448
colorPrimitives = new LoopPipe();
449
450
outlineTextRenderer = new OutlineTextRenderer();
451
solidTextRenderer = new SolidTextRenderer();
452
aaTextRenderer = new AATextRenderer();
453
lcdTextRenderer = new LCDTextRenderer();
454
455
colorPipe = new AlphaColorPipe();
456
// colorShape = colorPrimitives;
457
colorViaShape = new PixelToShapeLoopConverter(colorPrimitives);
458
colorViaPgram = new PixelToPgramLoopConverter(colorPrimitives,
459
colorPrimitives,
460
1.0, 0.25, true);
461
colorText = new TextRenderer(colorPipe);
462
clipColorPipe = new SpanClipRenderer(colorPipe);
463
clipColorText = new TextRenderer(clipColorPipe);
464
AAColorShape = new AAShapePipe(colorPipe);
465
AAColorViaShape = makeConverter(AAColorShape);
466
AAColorViaPgram = makeConverter(AAColorShape, colorPipe);
467
AAClipColorShape = new AAShapePipe(clipColorPipe);
468
AAClipColorViaShape = makeConverter(AAClipColorShape);
469
470
paintPipe = new AlphaPaintPipe();
471
paintShape = new SpanShapeRenderer.Composite(paintPipe);
472
paintViaShape = new PixelToShapeConverter(paintShape);
473
paintText = new TextRenderer(paintPipe);
474
clipPaintPipe = new SpanClipRenderer(paintPipe);
475
clipPaintText = new TextRenderer(clipPaintPipe);
476
AAPaintShape = new AAShapePipe(paintPipe);
477
AAPaintViaShape = makeConverter(AAPaintShape);
478
AAClipPaintShape = new AAShapePipe(clipPaintPipe);
479
AAClipPaintViaShape = makeConverter(AAClipPaintShape);
480
481
compPipe = new GeneralCompositePipe();
482
compShape = new SpanShapeRenderer.Composite(compPipe);
483
compViaShape = new PixelToShapeConverter(compShape);
484
compText = new TextRenderer(compPipe);
485
clipCompPipe = new SpanClipRenderer(compPipe);
486
clipCompText = new TextRenderer(clipCompPipe);
487
AACompShape = new AAShapePipe(compPipe);
488
AACompViaShape = makeConverter(AACompShape);
489
AAClipCompShape = new AAShapePipe(clipCompPipe);
490
AAClipCompViaShape = makeConverter(AAClipCompShape);
491
492
imagepipe = new DrawImage();
493
}
494
495
/* Not all surfaces and rendering mode combinations support LCD text. */
496
static final int LOOP_UNKNOWN = 0;
497
static final int LOOP_FOUND = 1;
498
static final int LOOP_NOTFOUND = 2;
499
int haveLCDLoop;
500
int havePgramXORLoop;
501
int havePgramSolidLoop;
502
503
public boolean canRenderLCDText(SunGraphics2D sg2d) {
504
// For now the answer can only be true in the following cases:
505
if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
506
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
507
sg2d.clipState <= SunGraphics2D.CLIP_RECTANGULAR &&
508
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE)
509
{
510
if (haveLCDLoop == LOOP_UNKNOWN) {
511
DrawGlyphListLCD loop =
512
DrawGlyphListLCD.locate(SurfaceType.AnyColor,
513
CompositeType.SrcNoEa,
514
getSurfaceType());
515
haveLCDLoop = (loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
516
}
517
return haveLCDLoop == LOOP_FOUND;
518
}
519
return false; /* for now - in the future we may want to search */
520
}
521
522
public boolean canRenderParallelograms(SunGraphics2D sg2d) {
523
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
524
if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
525
if (havePgramXORLoop == LOOP_UNKNOWN) {
526
FillParallelogram loop =
527
FillParallelogram.locate(SurfaceType.AnyColor,
528
CompositeType.Xor,
529
getSurfaceType());
530
havePgramXORLoop =
531
(loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
532
}
533
return havePgramXORLoop == LOOP_FOUND;
534
} else if (sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
535
sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
536
sg2d.clipState != SunGraphics2D.CLIP_SHAPE)
537
{
538
if (havePgramSolidLoop == LOOP_UNKNOWN) {
539
FillParallelogram loop =
540
FillParallelogram.locate(SurfaceType.AnyColor,
541
CompositeType.SrcNoEa,
542
getSurfaceType());
543
havePgramSolidLoop =
544
(loop != null) ? LOOP_FOUND : LOOP_NOTFOUND;
545
}
546
return havePgramSolidLoop == LOOP_FOUND;
547
}
548
}
549
return false;
550
}
551
552
public void validatePipe(SunGraphics2D sg2d) {
553
sg2d.imagepipe = imagepipe;
554
if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
555
if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
556
sg2d.drawpipe = paintViaShape;
557
sg2d.fillpipe = paintViaShape;
558
sg2d.shapepipe = paintShape;
559
// REMIND: Ideally custom paint mode would use glyph
560
// rendering as opposed to outline rendering but the
561
// glyph paint rendering pipeline uses MaskBlit which
562
// is not defined for XOR. This means that text drawn
563
// in XOR mode with a Color object is different than
564
// text drawn in XOR mode with a Paint object.
565
sg2d.textpipe = outlineTextRenderer;
566
} else {
567
PixelToShapeConverter converter;
568
if (canRenderParallelograms(sg2d)) {
569
converter = colorViaPgram;
570
// Note that we use the transforming pipe here because it
571
// will examine the shape and possibly perform an optimized
572
// operation if it can be simplified. The simplifications
573
// will be valid for all STROKE and TRANSFORM types.
574
sg2d.shapepipe = colorViaPgram;
575
} else {
576
converter = colorViaShape;
577
sg2d.shapepipe = colorPrimitives;
578
}
579
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
580
sg2d.drawpipe = converter;
581
sg2d.fillpipe = converter;
582
// REMIND: We should not be changing text strategies
583
// between outline and glyph rendering based upon the
584
// presence of a complex clip as that could cause a
585
// mismatch when drawing the same text both clipped
586
// and unclipped on two separate rendering passes.
587
// Unfortunately, all of the clipped glyph rendering
588
// pipelines rely on the use of the MaskBlit operation
589
// which is not defined for XOR.
590
sg2d.textpipe = outlineTextRenderer;
591
} else {
592
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
593
sg2d.drawpipe = converter;
594
sg2d.fillpipe = converter;
595
} else {
596
if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
597
sg2d.drawpipe = converter;
598
} else {
599
sg2d.drawpipe = colorPrimitives;
600
}
601
sg2d.fillpipe = colorPrimitives;
602
}
603
sg2d.textpipe = solidTextRenderer;
604
}
605
// assert(sg2d.surfaceData == this);
606
}
607
} else if (sg2d.compositeState == SunGraphics2D.COMP_CUSTOM) {
608
if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) {
609
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
610
sg2d.drawpipe = AAClipCompViaShape;
611
sg2d.fillpipe = AAClipCompViaShape;
612
sg2d.shapepipe = AAClipCompViaShape;
613
sg2d.textpipe = clipCompText;
614
} else {
615
sg2d.drawpipe = AACompViaShape;
616
sg2d.fillpipe = AACompViaShape;
617
sg2d.shapepipe = AACompViaShape;
618
sg2d.textpipe = compText;
619
}
620
} else {
621
sg2d.drawpipe = compViaShape;
622
sg2d.fillpipe = compViaShape;
623
sg2d.shapepipe = compShape;
624
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
625
sg2d.textpipe = clipCompText;
626
} else {
627
sg2d.textpipe = compText;
628
}
629
}
630
} else if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) {
631
sg2d.alphafill = getMaskFill(sg2d);
632
// assert(sg2d.surfaceData == this);
633
if (sg2d.alphafill != null) {
634
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
635
sg2d.drawpipe = AAClipColorViaShape;
636
sg2d.fillpipe = AAClipColorViaShape;
637
sg2d.shapepipe = AAClipColorViaShape;
638
sg2d.textpipe = clipColorText;
639
} else {
640
PixelToParallelogramConverter converter =
641
(sg2d.alphafill.canDoParallelograms()
642
? AAColorViaPgram
643
: AAColorViaShape);
644
sg2d.drawpipe = converter;
645
sg2d.fillpipe = converter;
646
sg2d.shapepipe = converter;
647
if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR ||
648
sg2d.compositeState > SunGraphics2D.COMP_ISCOPY)
649
{
650
sg2d.textpipe = colorText;
651
} else {
652
sg2d.textpipe = getTextPipe(sg2d, true /* AA==ON */);
653
}
654
}
655
} else {
656
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
657
sg2d.drawpipe = AAClipPaintViaShape;
658
sg2d.fillpipe = AAClipPaintViaShape;
659
sg2d.shapepipe = AAClipPaintViaShape;
660
sg2d.textpipe = clipPaintText;
661
} else {
662
sg2d.drawpipe = AAPaintViaShape;
663
sg2d.fillpipe = AAPaintViaShape;
664
sg2d.shapepipe = AAPaintViaShape;
665
sg2d.textpipe = paintText;
666
}
667
}
668
} else if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR ||
669
sg2d.compositeState > SunGraphics2D.COMP_ISCOPY ||
670
sg2d.clipState == SunGraphics2D.CLIP_SHAPE)
671
{
672
sg2d.drawpipe = paintViaShape;
673
sg2d.fillpipe = paintViaShape;
674
sg2d.shapepipe = paintShape;
675
sg2d.alphafill = getMaskFill(sg2d);
676
// assert(sg2d.surfaceData == this);
677
if (sg2d.alphafill != null) {
678
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
679
sg2d.textpipe = clipColorText;
680
} else {
681
sg2d.textpipe = colorText;
682
}
683
} else {
684
if (sg2d.clipState == SunGraphics2D.CLIP_SHAPE) {
685
sg2d.textpipe = clipPaintText;
686
} else {
687
sg2d.textpipe = paintText;
688
}
689
}
690
} else {
691
PixelToShapeConverter converter;
692
if (canRenderParallelograms(sg2d)) {
693
converter = colorViaPgram;
694
// Note that we use the transforming pipe here because it
695
// will examine the shape and possibly perform an optimized
696
// operation if it can be simplified. The simplifications
697
// will be valid for all STROKE and TRANSFORM types.
698
sg2d.shapepipe = colorViaPgram;
699
} else {
700
converter = colorViaShape;
701
sg2d.shapepipe = colorPrimitives;
702
}
703
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
704
sg2d.drawpipe = converter;
705
sg2d.fillpipe = converter;
706
} else {
707
if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
708
sg2d.drawpipe = converter;
709
} else {
710
sg2d.drawpipe = colorPrimitives;
711
}
712
sg2d.fillpipe = colorPrimitives;
713
}
714
715
sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */);
716
// assert(sg2d.surfaceData == this);
717
}
718
719
// check for loops
720
if (sg2d.textpipe instanceof LoopBasedPipe ||
721
sg2d.shapepipe instanceof LoopBasedPipe ||
722
sg2d.fillpipe instanceof LoopBasedPipe ||
723
sg2d.drawpipe instanceof LoopBasedPipe ||
724
sg2d.imagepipe instanceof LoopBasedPipe)
725
{
726
sg2d.loops = getRenderLoops(sg2d);
727
}
728
}
729
730
/* Return the text pipe to be used based on the graphics AA hint setting,
731
* and the rest of the graphics state is compatible with these loops.
732
* If the text AA hint is "DEFAULT", then the AA graphics hint requests
733
* the AA text renderer, else it requests the B&W text renderer.
734
*/
735
private TextPipe getTextPipe(SunGraphics2D sg2d, boolean aaHintIsOn) {
736
737
/* Try to avoid calling getFontInfo() unless its needed to
738
* resolve one of the new AA types.
739
*/
740
switch (sg2d.textAntialiasHint) {
741
case SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT:
742
if (aaHintIsOn) {
743
return aaTextRenderer;
744
} else {
745
return solidTextRenderer;
746
}
747
case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
748
return solidTextRenderer;
749
750
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
751
return aaTextRenderer;
752
753
default:
754
switch (sg2d.getFontInfo().aaHint) {
755
756
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_HRGB:
757
case SunHints.INTVAL_TEXT_ANTIALIAS_LCD_VRGB:
758
return lcdTextRenderer;
759
760
case SunHints.INTVAL_TEXT_ANTIALIAS_ON:
761
return aaTextRenderer;
762
763
case SunHints.INTVAL_TEXT_ANTIALIAS_OFF:
764
return solidTextRenderer;
765
766
/* This should not be reached as the FontInfo will
767
* always explicitly set its hint value. So whilst
768
* this could be collapsed to returning say just
769
* solidTextRenderer, or even removed, its left
770
* here in case DEFAULT is ever passed in.
771
*/
772
default:
773
if (aaHintIsOn) {
774
return aaTextRenderer;
775
} else {
776
return solidTextRenderer;
777
}
778
}
779
}
780
}
781
782
private static SurfaceType getPaintSurfaceType(SunGraphics2D sg2d) {
783
switch (sg2d.paintState) {
784
case SunGraphics2D.PAINT_OPAQUECOLOR:
785
return SurfaceType.OpaqueColor;
786
case SunGraphics2D.PAINT_ALPHACOLOR:
787
return SurfaceType.AnyColor;
788
case SunGraphics2D.PAINT_GRADIENT:
789
if (sg2d.paint.getTransparency() == OPAQUE) {
790
return SurfaceType.OpaqueGradientPaint;
791
} else {
792
return SurfaceType.GradientPaint;
793
}
794
case SunGraphics2D.PAINT_LIN_GRADIENT:
795
if (sg2d.paint.getTransparency() == OPAQUE) {
796
return SurfaceType.OpaqueLinearGradientPaint;
797
} else {
798
return SurfaceType.LinearGradientPaint;
799
}
800
case SunGraphics2D.PAINT_RAD_GRADIENT:
801
if (sg2d.paint.getTransparency() == OPAQUE) {
802
return SurfaceType.OpaqueRadialGradientPaint;
803
} else {
804
return SurfaceType.RadialGradientPaint;
805
}
806
case SunGraphics2D.PAINT_TEXTURE:
807
if (sg2d.paint.getTransparency() == OPAQUE) {
808
return SurfaceType.OpaqueTexturePaint;
809
} else {
810
return SurfaceType.TexturePaint;
811
}
812
default:
813
case SunGraphics2D.PAINT_CUSTOM:
814
return SurfaceType.AnyPaint;
815
}
816
}
817
818
private static CompositeType getFillCompositeType(SunGraphics2D sg2d) {
819
CompositeType compType = sg2d.imageComp;
820
if (sg2d.compositeState == SunGraphics2D.COMP_ISCOPY) {
821
if (compType == CompositeType.SrcOverNoEa) {
822
compType = CompositeType.OpaqueSrcOverNoEa;
823
} else {
824
compType = CompositeType.SrcNoEa;
825
}
826
}
827
return compType;
828
}
829
830
/**
831
* Returns a MaskFill object that can be used on this destination
832
* with the source (paint) and composite types determined by the given
833
* SunGraphics2D, or null if no such MaskFill object can be located.
834
* Subclasses can override this method if they wish to filter other
835
* attributes (such as the hardware capabilities of the destination
836
* surface) before returning a specific MaskFill object.
837
*/
838
protected MaskFill getMaskFill(SunGraphics2D sg2d) {
839
SurfaceType src = getPaintSurfaceType(sg2d);
840
CompositeType comp = getFillCompositeType(sg2d);
841
SurfaceType dst = getSurfaceType();
842
return MaskFill.getFromCache(src, comp, dst);
843
}
844
845
private static RenderCache loopcache = new RenderCache(30);
846
847
/**
848
* Return a RenderLoops object containing all of the basic
849
* GraphicsPrimitive objects for rendering to the destination
850
* surface with the current attributes of the given SunGraphics2D.
851
*/
852
public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
853
SurfaceType src = getPaintSurfaceType(sg2d);
854
CompositeType comp = getFillCompositeType(sg2d);
855
SurfaceType dst = sg2d.getSurfaceData().getSurfaceType();
856
857
Object o = loopcache.get(src, comp, dst);
858
if (o != null) {
859
return (RenderLoops) o;
860
}
861
862
RenderLoops loops = makeRenderLoops(src, comp, dst);
863
loopcache.put(src, comp, dst, loops);
864
return loops;
865
}
866
867
/**
868
* Construct and return a RenderLoops object containing all of
869
* the basic GraphicsPrimitive objects for rendering to the
870
* destination surface with the given source, destination, and
871
* composite types.
872
*/
873
public static RenderLoops makeRenderLoops(SurfaceType src,
874
CompositeType comp,
875
SurfaceType dst)
876
{
877
RenderLoops loops = new RenderLoops();
878
loops.drawLineLoop = DrawLine.locate(src, comp, dst);
879
loops.fillRectLoop = FillRect.locate(src, comp, dst);
880
loops.drawRectLoop = DrawRect.locate(src, comp, dst);
881
loops.drawPolygonsLoop = DrawPolygons.locate(src, comp, dst);
882
loops.drawPathLoop = DrawPath.locate(src, comp, dst);
883
loops.fillPathLoop = FillPath.locate(src, comp, dst);
884
loops.fillSpansLoop = FillSpans.locate(src, comp, dst);
885
loops.fillParallelogramLoop = FillParallelogram.locate(src, comp, dst);
886
loops.drawParallelogramLoop = DrawParallelogram.locate(src, comp, dst);
887
loops.drawGlyphListLoop = DrawGlyphList.locate(src, comp, dst);
888
loops.drawGlyphListAALoop = DrawGlyphListAA.locate(src, comp, dst);
889
loops.drawGlyphListLCDLoop = DrawGlyphListLCD.locate(src, comp, dst);
890
/*
891
System.out.println("drawLine: "+loops.drawLineLoop);
892
System.out.println("fillRect: "+loops.fillRectLoop);
893
System.out.println("drawRect: "+loops.drawRectLoop);
894
System.out.println("drawPolygons: "+loops.drawPolygonsLoop);
895
System.out.println("fillSpans: "+loops.fillSpansLoop);
896
System.out.println("drawGlyphList: "+loops.drawGlyphListLoop);
897
System.out.println("drawGlyphListAA: "+loops.drawGlyphListAALoop);
898
System.out.println("drawGlyphListLCD: "+loops.drawGlyphListLCDLoop);
899
*/
900
return loops;
901
}
902
903
/**
904
* Return the GraphicsConfiguration object that describes this
905
* destination surface.
906
*/
907
public abstract GraphicsConfiguration getDeviceConfiguration();
908
909
/**
910
* Return the SurfaceType object that describes the destination
911
* surface.
912
*/
913
public final SurfaceType getSurfaceType() {
914
return surfaceType;
915
}
916
917
/**
918
* Return the ColorModel for the destination surface.
919
*/
920
public final ColorModel getColorModel() {
921
return colorModel;
922
}
923
924
/**
925
* Returns the type of this <code>Transparency</code>.
926
* @return the field type of this <code>Transparency</code>, which is
927
* either OPAQUE, BITMASK or TRANSLUCENT.
928
*/
929
public int getTransparency() {
930
return getColorModel().getTransparency();
931
}
932
933
/**
934
* Return a readable Raster which contains the pixels for the
935
* specified rectangular region of the destination surface.
936
* The coordinate origin of the returned Raster is the same as
937
* the device space origin of the destination surface.
938
* In some cases the returned Raster might also be writeable.
939
* In most cases, the returned Raster might contain more pixels
940
* than requested.
941
*
942
* @see useTightBBoxes
943
*/
944
public abstract Raster getRaster(int x, int y, int w, int h);
945
946
/**
947
* Does the pixel accessibility of the destination surface
948
* suggest that rendering algorithms might want to take
949
* extra time to calculate a more accurate bounding box for
950
* the operation being performed?
951
* The typical case when this will be true is when a copy of
952
* the pixels has to be made when doing a getRaster. The
953
* fewer pixels copied, the faster the operation will go.
954
*
955
* @see getRaster
956
*/
957
public boolean useTightBBoxes() {
958
// Note: The native equivalent would trigger on VISIBLE_TO_NATIVE
959
// REMIND: This is not used - should be obsoleted maybe
960
return true;
961
}
962
963
/**
964
* Returns the pixel data for the specified Argb value packed
965
* into an integer for easy storage and conveyance.
966
*/
967
public int pixelFor(int rgb) {
968
return surfaceType.pixelFor(rgb, colorModel);
969
}
970
971
/**
972
* Returns the pixel data for the specified color packed into an
973
* integer for easy storage and conveyance.
974
*
975
* This method will use the getRGB() method of the Color object
976
* and defer to the pixelFor(int rgb) method if not overridden.
977
*
978
* For now this is a convenience function, but for cases where
979
* the highest quality color conversion is requested, this method
980
* should be overridden in those cases so that a more direct
981
* conversion of the color to the destination color space
982
* can be done using the additional information in the Color
983
* object.
984
*/
985
public int pixelFor(Color c) {
986
return pixelFor(c.getRGB());
987
}
988
989
/**
990
* Returns the Argb representation for the specified integer value
991
* which is packed in the format of the associated ColorModel.
992
*/
993
public int rgbFor(int pixel) {
994
return surfaceType.rgbFor(pixel, colorModel);
995
}
996
997
/**
998
* Returns the bounds of the destination surface.
999
*/
1000
public abstract Rectangle getBounds();
1001
1002
static java.security.Permission compPermission;
1003
1004
/**
1005
* Performs Security Permissions checks to see if a Custom
1006
* Composite object should be allowed access to the pixels
1007
* of this surface.
1008
*/
1009
protected void checkCustomComposite() {
1010
SecurityManager sm = System.getSecurityManager();
1011
if (sm != null) {
1012
if (compPermission == null) {
1013
compPermission =
1014
new java.awt.AWTPermission("readDisplayPixels");
1015
}
1016
sm.checkPermission(compPermission);
1017
}
1018
}
1019
1020
/**
1021
* Fetches private field IndexColorModel.allgrayopaque
1022
* which is true when all palette entries in the color
1023
* model are gray and opaque.
1024
*/
1025
protected static native boolean isOpaqueGray(IndexColorModel icm);
1026
1027
/**
1028
* For our purposes null and NullSurfaceData are the same as
1029
* they represent a disposed surface.
1030
*/
1031
public static boolean isNull(SurfaceData sd) {
1032
if (sd == null || sd == NullSurfaceData.theInstance) {
1033
return true;
1034
}
1035
return false;
1036
}
1037
1038
/**
1039
* Performs a copyarea within this surface. Returns
1040
* false if there is no algorithm to perform the copyarea
1041
* given the current settings of the SunGraphics2D.
1042
*/
1043
public boolean copyArea(SunGraphics2D sg2d,
1044
int x, int y, int w, int h, int dx, int dy)
1045
{
1046
return false;
1047
}
1048
1049
/**
1050
* Synchronously releases resources associated with this surface.
1051
*/
1052
public void flush() {}
1053
1054
/**
1055
* Returns destination associated with this SurfaceData. This could be
1056
* either an Image or a Component; subclasses of SurfaceData are
1057
* responsible for returning the appropriate object.
1058
*/
1059
public abstract Object getDestination();
1060
1061
/**
1062
* Returns default scale factor of the destination surface. Scale factor
1063
* describes the mapping between virtual and physical coordinates of the
1064
* SurfaceData. If the scale is 2 then virtual pixel coordinates need to be
1065
* doubled for physical pixels.
1066
*/
1067
public int getDefaultScale() {
1068
return 1;
1069
}
1070
}
1071
1072