Showing the changes to java/pkg/sun/java2d/SurfaceData.java (1 of 18352 files). Show all
Unified · Split
| @@ -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 | } | ||