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