src/share/classes/sun/java2d/SunGraphics2D.java

Print this page




  78 import sun.java2d.pipe.Region;
  79 import sun.java2d.pipe.TextPipe;
  80 import sun.java2d.pipe.DrawImagePipe;
  81 import sun.java2d.pipe.LoopPipe;
  82 import sun.java2d.loops.FontInfo;
  83 import sun.java2d.loops.RenderLoops;
  84 import sun.java2d.loops.CompositeType;
  85 import sun.java2d.loops.SurfaceType;
  86 import sun.java2d.loops.Blit;
  87 import sun.java2d.loops.MaskFill;
  88 import java.awt.font.FontRenderContext;
  89 import sun.java2d.loops.XORComposite;
  90 import sun.awt.ConstrainableGraphics;
  91 import sun.awt.SunHints;
  92 import java.util.Map;
  93 import java.util.Iterator;
  94 import sun.misc.PerformanceLogger;
  95 
  96 import java.lang.annotation.Native;
  97 import sun.awt.image.MultiResolutionImage;

  98 
  99 import static java.awt.geom.AffineTransform.TYPE_FLIP;
 100 import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
 101 import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
 102 import sun.awt.image.MultiResolutionToolkitImage;
 103 import sun.awt.image.ToolkitImage;
 104 
 105 /**
 106  * This is a the master Graphics2D superclass for all of the Sun
 107  * Graphics implementations.  This class relies on subclasses to
 108  * manage the various device information, but provides an overall
 109  * general framework for performing all of the requests in the
 110  * Graphics and Graphics2D APIs.
 111  *
 112  * @author Jim Graham
 113  */
 114 public final class SunGraphics2D
 115     extends Graphics2D
 116     implements ConstrainableGraphics, Cloneable, DestSurfaceProvider
 117 {


2091                 revalidateAll();
2092                 doCopyArea(x, y, w, h, dx, dy);
2093             } catch (InvalidPipeException e2) {
2094                 // Still catching the exception; we are not yet ready to
2095                 // validate the surfaceData correctly.  Fail for now and
2096                 // try again next time around.
2097             }
2098         } finally {
2099             surfaceData.markDirty();
2100         }
2101     }
2102 
2103     private void doCopyArea(int x, int y, int w, int h, int dx, int dy) {
2104         if (w <= 0 || h <= 0) {
2105             return;
2106         }
2107         SurfaceData theData = surfaceData;
2108         if (theData.copyArea(this, x, y, w, h, dx, dy)) {
2109             return;
2110         }
2111         if (transformState >= TRANSFORM_TRANSLATESCALE) {
2112             throw new InternalError("transformed copyArea not implemented yet");
2113         }
2114         // REMIND: This method does not deal with missing data from the
2115         // source object (i.e. it does not send exposure events...)
2116 
2117         Region clip = getCompClip();
2118 
2119         Composite comp = composite;
2120         if (lastCAcomp != comp) {
2121             SurfaceType dsttype = theData.getSurfaceType();
2122             CompositeType comptype = imageComp;
2123             if (CompositeType.SrcOverNoEa.equals(comptype) &&
2124                 theData.getTransparency() == Transparency.OPAQUE)
2125             {
2126                 comptype = CompositeType.SrcNoEa;
2127             }
2128             lastCAblit = Blit.locate(dsttype, comptype, dsttype);
2129             lastCAcomp = comp;
2130         }
2131 
2132         x += transX;
2133         y += transY;

















2134 
2135         Blit ob = lastCAblit;
2136         if (dy == 0 && dx > 0 && dx < w) {
2137             while (w > 0) {
2138                 int partW = Math.min(w, dx);
2139                 w -= partW;
2140                 int sx = x + w;
2141                 ob.Blit(theData, theData, comp, clip,
2142                         sx, y, sx+dx, y+dy, partW, h);
2143             }
2144             return;
2145         }
2146         if (dy > 0 && dy < h && dx > -w && dx < w) {
2147             while (h > 0) {
2148                 int partH = Math.min(h, dy);
2149                 h -= partH;
2150                 int sy = y + h;
2151                 ob.Blit(theData, theData, comp, clip,
2152                         x, sy, x+dx, sy+dy, w, partH);
2153             }


3056         }
3057 
3058         try {
3059             textpipe.drawChars(this, chData, 0, length, x, y);
3060         } catch (InvalidPipeException e) {
3061             try {
3062                 revalidateAll();
3063                 textpipe.drawChars(this, chData, 0, length, x, y);
3064             } catch (InvalidPipeException e2) {
3065                 // Still catching the exception; we are not yet ready to
3066                 // validate the surfaceData correctly.  Fail for now and
3067                 // try again next time around.
3068             }
3069         } finally {
3070             surfaceData.markDirty();
3071         }
3072     }
3073 // end of text rendering methods
3074 
3075     private boolean isHiDPIImage(final Image img) {





3076         return (SurfaceManager.getImageScale(img) != 1) ||
3077                (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_OFF
3078                     && img instanceof MultiResolutionImage);
3079     }
3080 
3081     private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
3082                                    int dy2, int sx1, int sy1, int sx2, int sy2,
3083                                    Color bgcolor, ImageObserver observer) {
3084 
3085         if (SurfaceManager.getImageScale(img) != 1) {  // Volatile Image
3086             final int scale = SurfaceManager.getImageScale(img);
3087             sx1 = Region.clipScale(sx1, scale);
3088             sx2 = Region.clipScale(sx2, scale);
3089             sy1 = Region.clipScale(sy1, scale);
3090             sy2 = Region.clipScale(sy2, scale);
3091         } else if (img instanceof MultiResolutionImage) {
3092             // get scaled destination image size
3093 
3094             int width = img.getWidth(observer);
3095             int height = img.getHeight(observer);


3174             destRegionWidth = dw * Math.hypot(
3175                     transform.getScaleX(), transform.getShearY());
3176             destRegionHeight = dh * Math.hypot(
3177                     transform.getShearX(), transform.getScaleY());
3178         }
3179 
3180         int destImageWidth = (int) Math.abs(srcWidth * destRegionWidth / sw);
3181         int destImageHeight = (int) Math.abs(srcHeight * destRegionHeight / sh);
3182 
3183         Image resolutionVariant
3184                 = img.getResolutionVariant(destImageWidth, destImageHeight);
3185 
3186         if (resolutionVariant instanceof ToolkitImage
3187                 && ((ToolkitImage) resolutionVariant).hasError()) {
3188             return null;
3189         }
3190 
3191         return resolutionVariant;
3192     }
3193 





























3194     /**
3195      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3196      * callback object.
3197      */
3198     public boolean drawImage(Image img, int x, int y, int width, int height,
3199                              ImageObserver observer) {
3200         return drawImage(img, x, y, width, height, null, observer);
3201     }
3202 
3203     /**
3204      * Not part of the advertised API but a useful utility method
3205      * to call internally.  This is for the case where we are
3206      * drawing to/from given coordinates using a given width/height,
3207      * but we guarantee that the surfaceData's width/height of the src and dest
3208      * areas are equal (no scale needed). Note that this method intentionally
3209      * ignore scale factor of the source image, and copy it as is.
3210      */
3211     public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
3212                              int width, int height, Color bgcolor,
3213                              ImageObserver observer) {


3451                 return imagepipe.transformImage(this, img, xform, observer);
3452             } catch (InvalidPipeException e2) {
3453                 // Still catching the exception; we are not yet ready to
3454                 // validate the surfaceData correctly.  Fail for now and
3455                 // try again next time around.
3456                 return false;
3457             }
3458         } finally {
3459             surfaceData.markDirty();
3460         }
3461     }
3462 
3463     public void drawImage(BufferedImage bImg,
3464                           BufferedImageOp op,
3465                           int x,
3466                           int y)  {
3467 
3468         if (bImg == null) {
3469             return;
3470         }
3471 



3472         try {
3473             imagepipe.transformImage(this, bImg, op, x, y);
3474         } catch (InvalidPipeException e) {
3475             try {
3476                 revalidateAll();
3477                 imagepipe.transformImage(this, bImg, op, x, y);
3478             } catch (InvalidPipeException e2) {
3479                 // Still catching the exception; we are not yet ready to
3480                 // validate the surfaceData correctly.  Fail for now and
3481                 // try again next time around.
3482             }
3483         } finally {
3484             surfaceData.markDirty();
3485         }
3486     }
3487 
3488     /**
3489     * Get the rendering context of the font
3490     * within this Graphics2D context.
3491     */




  78 import sun.java2d.pipe.Region;
  79 import sun.java2d.pipe.TextPipe;
  80 import sun.java2d.pipe.DrawImagePipe;
  81 import sun.java2d.pipe.LoopPipe;
  82 import sun.java2d.loops.FontInfo;
  83 import sun.java2d.loops.RenderLoops;
  84 import sun.java2d.loops.CompositeType;
  85 import sun.java2d.loops.SurfaceType;
  86 import sun.java2d.loops.Blit;
  87 import sun.java2d.loops.MaskFill;
  88 import java.awt.font.FontRenderContext;
  89 import sun.java2d.loops.XORComposite;
  90 import sun.awt.ConstrainableGraphics;
  91 import sun.awt.SunHints;
  92 import java.util.Map;
  93 import java.util.Iterator;
  94 import sun.misc.PerformanceLogger;
  95 
  96 import java.lang.annotation.Native;
  97 import sun.awt.image.MultiResolutionImage;
  98 import sun.awt.image.OffScreenImage;
  99 
 100 import static java.awt.geom.AffineTransform.TYPE_FLIP;
 101 import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
 102 import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
 103 import sun.awt.image.MultiResolutionToolkitImage;
 104 import sun.awt.image.ToolkitImage;
 105 
 106 /**
 107  * This is a the master Graphics2D superclass for all of the Sun
 108  * Graphics implementations.  This class relies on subclasses to
 109  * manage the various device information, but provides an overall
 110  * general framework for performing all of the requests in the
 111  * Graphics and Graphics2D APIs.
 112  *
 113  * @author Jim Graham
 114  */
 115 public final class SunGraphics2D
 116     extends Graphics2D
 117     implements ConstrainableGraphics, Cloneable, DestSurfaceProvider
 118 {


2092                 revalidateAll();
2093                 doCopyArea(x, y, w, h, dx, dy);
2094             } catch (InvalidPipeException e2) {
2095                 // Still catching the exception; we are not yet ready to
2096                 // validate the surfaceData correctly.  Fail for now and
2097                 // try again next time around.
2098             }
2099         } finally {
2100             surfaceData.markDirty();
2101         }
2102     }
2103 
2104     private void doCopyArea(int x, int y, int w, int h, int dx, int dy) {
2105         if (w <= 0 || h <= 0) {
2106             return;
2107         }
2108         SurfaceData theData = surfaceData;
2109         if (theData.copyArea(this, x, y, w, h, dx, dy)) {
2110             return;
2111         }
2112         if (transformState > TRANSFORM_TRANSLATESCALE) {
2113             throw new InternalError("transformed copyArea not implemented yet");
2114         }
2115         // REMIND: This method does not deal with missing data from the
2116         // source object (i.e. it does not send exposure events...)
2117         
2118         Region clip = getCompClip();
2119 
2120         Composite comp = composite;
2121         if (lastCAcomp != comp) {
2122             SurfaceType dsttype = theData.getSurfaceType();
2123             CompositeType comptype = imageComp;
2124             if (CompositeType.SrcOverNoEa.equals(comptype) &&
2125                 theData.getTransparency() == Transparency.OPAQUE)
2126             {
2127                 comptype = CompositeType.SrcNoEa;
2128             }
2129             lastCAblit = Blit.locate(dsttype, comptype, dsttype);
2130             lastCAcomp = comp;
2131         }
2132 
2133         double[] coords = {x, y, x + w, y + h, x + dx, y + dy};
2134         transform.transform(coords, 0, coords, 0, 3);
2135 
2136         x = (int)Math.ceil(coords[0] - 0.5);
2137         y = (int)Math.ceil(coords[1] - 0.5);
2138         w = ((int)Math.ceil(coords[2] - 0.5)) - x;
2139         h = ((int)Math.ceil(coords[3] - 0.5)) - y;
2140         dx = ((int)Math.ceil(coords[4] - 0.5)) - x;
2141         dy = ((int)Math.ceil(coords[5] - 0.5)) - y;
2142         
2143         // In case of negative scale transform, reflect the rect coords.
2144         if (w < 0) {
2145             w *= -1;
2146             x -= w;
2147         }
2148         if (h < 0) {
2149             h *= -1;
2150             y -= h;
2151         }
2152         
2153         Blit ob = lastCAblit;
2154         if (dy == 0 && dx > 0 && dx < w) {
2155             while (w > 0) {
2156                 int partW = Math.min(w, dx);
2157                 w -= partW;
2158                 int sx = x + w;
2159                 ob.Blit(theData, theData, comp, clip,
2160                         sx, y, sx+dx, y+dy, partW, h);
2161             }
2162             return;
2163         }
2164         if (dy > 0 && dy < h && dx > -w && dx < w) {
2165             while (h > 0) {
2166                 int partH = Math.min(h, dy);
2167                 h -= partH;
2168                 int sy = y + h;
2169                 ob.Blit(theData, theData, comp, clip,
2170                         x, sy, x+dx, sy+dy, w, partH);
2171             }


3074         }
3075 
3076         try {
3077             textpipe.drawChars(this, chData, 0, length, x, y);
3078         } catch (InvalidPipeException e) {
3079             try {
3080                 revalidateAll();
3081                 textpipe.drawChars(this, chData, 0, length, x, y);
3082             } catch (InvalidPipeException e2) {
3083                 // Still catching the exception; we are not yet ready to
3084                 // validate the surfaceData correctly.  Fail for now and
3085                 // try again next time around.
3086             }
3087         } finally {
3088             surfaceData.markDirty();
3089         }
3090     }
3091 // end of text rendering methods
3092 
3093     private boolean isHiDPIImage(final Image img) {
3094         if (img instanceof OffScreenImage &&
3095             !((OffScreenImage)img).isReturnLayoutSize())
3096         {
3097             return false;
3098         }
3099         return (SurfaceManager.getImageScale(img) != 1) ||
3100                (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_OFF
3101                     && img instanceof MultiResolutionImage);
3102     }
3103 
3104     private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
3105                                    int dy2, int sx1, int sy1, int sx2, int sy2,
3106                                    Color bgcolor, ImageObserver observer) {
3107 
3108         if (SurfaceManager.getImageScale(img) != 1) {  // Volatile Image
3109             final int scale = SurfaceManager.getImageScale(img);
3110             sx1 = Region.clipScale(sx1, scale);
3111             sx2 = Region.clipScale(sx2, scale);
3112             sy1 = Region.clipScale(sy1, scale);
3113             sy2 = Region.clipScale(sy2, scale);
3114         } else if (img instanceof MultiResolutionImage) {
3115             // get scaled destination image size
3116 
3117             int width = img.getWidth(observer);
3118             int height = img.getHeight(observer);


3197             destRegionWidth = dw * Math.hypot(
3198                     transform.getScaleX(), transform.getShearY());
3199             destRegionHeight = dh * Math.hypot(
3200                     transform.getShearX(), transform.getScaleY());
3201         }
3202 
3203         int destImageWidth = (int) Math.abs(srcWidth * destRegionWidth / sw);
3204         int destImageHeight = (int) Math.abs(srcHeight * destRegionHeight / sh);
3205 
3206         Image resolutionVariant
3207                 = img.getResolutionVariant(destImageWidth, destImageHeight);
3208 
3209         if (resolutionVariant instanceof ToolkitImage
3210                 && ((ToolkitImage) resolutionVariant).hasError()) {
3211             return null;
3212         }
3213 
3214         return resolutionVariant;
3215     }
3216 
3217     private boolean drawHiDPIImage(BufferedImage img, BufferedImageOp op,
3218                                    int x, int y)
3219     {
3220         final int scale = SurfaceManager.getImageScale(img);
3221         if (op != null) {
3222             if (op instanceof AffineTransformOp) {
3223                 AffineTransformOp atop = (AffineTransformOp)op;
3224                 AffineTransform at = atop.getTransform();
3225                 try {
3226                     // The "atop" transform may move the bounding rect of the image,
3227                     // so the scale transform should be applied before.
3228                     at.concatenate(AffineTransform.getScaleInstance(scale, scale).createInverse());
3229                 } catch (Exception e) {
3230                     // the inverse is always possible
3231                 }
3232                 atop = new AffineTransformOp(at, atop.getInterpolationType());
3233                 imagepipe.transformImage(this, img, atop, x, y);
3234                 return true;
3235             }
3236             img = op.filter(img, null);
3237         }
3238         int w = img.getWidth();
3239         int h = img.getHeight();
3240         return drawHiDPIImage(img,
3241                               x, y, x + w, y + h,
3242                               0, 0, w, h,
3243                               backgroundColor, null);
3244     }
3245 
3246     /**
3247      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3248      * callback object.
3249      */
3250     public boolean drawImage(Image img, int x, int y, int width, int height,
3251                              ImageObserver observer) {
3252         return drawImage(img, x, y, width, height, null, observer);
3253     }
3254 
3255     /**
3256      * Not part of the advertised API but a useful utility method
3257      * to call internally.  This is for the case where we are
3258      * drawing to/from given coordinates using a given width/height,
3259      * but we guarantee that the surfaceData's width/height of the src and dest
3260      * areas are equal (no scale needed). Note that this method intentionally
3261      * ignore scale factor of the source image, and copy it as is.
3262      */
3263     public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
3264                              int width, int height, Color bgcolor,
3265                              ImageObserver observer) {


3503                 return imagepipe.transformImage(this, img, xform, observer);
3504             } catch (InvalidPipeException e2) {
3505                 // Still catching the exception; we are not yet ready to
3506                 // validate the surfaceData correctly.  Fail for now and
3507                 // try again next time around.
3508                 return false;
3509             }
3510         } finally {
3511             surfaceData.markDirty();
3512         }
3513     }
3514 
3515     public void drawImage(BufferedImage bImg,
3516                           BufferedImageOp op,
3517                           int x,
3518                           int y)  {
3519 
3520         if (bImg == null) {
3521             return;
3522         }
3523         if (isHiDPIImage(bImg)) {
3524             drawHiDPIImage(bImg, op, x, y);
3525             return;
3526         }
3527         try {
3528             imagepipe.transformImage(this, bImg, op, x, y);
3529         } catch (InvalidPipeException e) {
3530             try {
3531                 revalidateAll();
3532                 imagepipe.transformImage(this, bImg, op, x, y);
3533             } catch (InvalidPipeException e2) {
3534                 // Still catching the exception; we are not yet ready to
3535                 // validate the surfaceData correctly.  Fail for now and
3536                 // try again next time around.
3537             }
3538         } finally {
3539             surfaceData.markDirty();
3540         }
3541     }
3542 
3543     /**
3544     * Get the rendering context of the font
3545     * within this Graphics2D context.
3546     */