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
26package sun.java2d;
27
28import java.awt.Color;
29import java.awt.Rectangle;
30import java.awt.Transparency;
31import java.awt.GraphicsConfiguration;
32import java.awt.Image;
33import java.awt.image.ColorModel;
34import java.awt.image.IndexColorModel;
35import java.awt.image.Raster;
36
37import sun.java2d.loops.RenderCache;
38import sun.java2d.loops.RenderLoops;
39import sun.java2d.loops.CompositeType;
40import sun.java2d.loops.SurfaceType;
41import sun.java2d.loops.MaskFill;
42import sun.java2d.loops.DrawLine;
43import sun.java2d.loops.FillRect;
44import sun.java2d.loops.DrawRect;
45import sun.java2d.loops.DrawPolygons;
46import sun.java2d.loops.DrawPath;
47import sun.java2d.loops.FillPath;
48import sun.java2d.loops.FillSpans;
49import sun.java2d.loops.FillParallelogram;
50import sun.java2d.loops.DrawParallelogram;
51import sun.java2d.loops.FontInfo;
52import sun.java2d.loops.DrawGlyphList;
53import sun.java2d.loops.DrawGlyphListAA;
54import sun.java2d.loops.DrawGlyphListLCD;
55import sun.java2d.pipe.LoopPipe;
56import sun.java2d.pipe.ShapeDrawPipe;
57import sun.java2d.pipe.ParallelogramPipe;
58import sun.java2d.pipe.CompositePipe;
59import sun.java2d.pipe.GeneralCompositePipe;
60import sun.java2d.pipe.SpanClipRenderer;
61import sun.java2d.pipe.SpanShapeRenderer;
62import sun.java2d.pipe.AAShapePipe;
63import sun.java2d.pipe.AlphaPaintPipe;
64import sun.java2d.pipe.AlphaColorPipe;
65import sun.java2d.pipe.PixelToShapeConverter;
66import sun.java2d.pipe.PixelToParallelogramConverter;
67import sun.java2d.pipe.TextPipe;
68import sun.java2d.pipe.TextRenderer;
69import sun.java2d.pipe.AATextRenderer;
70import sun.java2d.pipe.LCDTextRenderer;
71import sun.java2d.pipe.SolidTextRenderer;
72import sun.java2d.pipe.OutlineTextRenderer;
73import sun.java2d.pipe.DrawImagePipe;
74import sun.java2d.pipe.DrawImage;
75import sun.awt.SunHints;
76import sun.awt.image.SurfaceManager;
77import 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 */
101public 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}