History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/java2d/SurfaceData.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/java2d/SurfaceData.java+1060−0
@@ -0,0 +1,1060 @@
1+/*
2+ * Copyright (c) 1999, 2010, 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 <= sg2d.PAINT_ALPHACOLOR) {
524+ if (sg2d.compositeState == sg2d.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 <= sg2d.COMP_ISCOPY &&
535+ sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON &&
536+ sg2d.clipState != sg2d.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 == sg2d.COMP_XOR) {
555+ if (sg2d.paintState > sg2d.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 == sg2d.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 >= sg2d.TRANSFORM_TRANSLATESCALE) {
593+ sg2d.drawpipe = converter;
594+ sg2d.fillpipe = converter;
595+ } else {
596+ if (sg2d.strokeState != sg2d.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 == sg2d.COMP_CUSTOM) {
608+ if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON) {
609+ if (sg2d.clipState == sg2d.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 == sg2d.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 == sg2d.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 > sg2d.PAINT_ALPHACOLOR ||
648+ sg2d.compositeState > sg2d.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 == sg2d.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 > sg2d.PAINT_ALPHACOLOR ||
669+ sg2d.compositeState > sg2d.COMP_ISCOPY ||
670+ sg2d.clipState == sg2d.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 == sg2d.CLIP_SHAPE) {
679+ sg2d.textpipe = clipColorText;
680+ } else {
681+ sg2d.textpipe = colorText;
682+ }
683+ } else {
684+ if (sg2d.clipState == sg2d.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 >= sg2d.TRANSFORM_TRANSLATESCALE) {
704+ sg2d.drawpipe = converter;
705+ sg2d.fillpipe = converter;
706+ } else {
707+ if (sg2d.strokeState != sg2d.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 == sg2d.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+}