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

Print this page




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

  96 
  97 /**
  98  * This is a the master Graphics2D superclass for all of the Sun
  99  * Graphics implementations.  This class relies on subclasses to
 100  * manage the various device information, but provides an overall
 101  * general framework for performing all of the requests in the
 102  * Graphics and Graphics2D APIs.
 103  *
 104  * @author Jim Graham
 105  */
 106 public final class SunGraphics2D
 107     extends Graphics2D
 108     implements ConstrainableGraphics, Cloneable, DestSurfaceProvider
 109 {
 110     /*
 111      * Attribute States
 112      */
 113     /* Paint */
 114     @Native
 115     public static final int PAINT_CUSTOM       = 6; /* Any other Paint object */


2071                 revalidateAll();
2072                 doCopyArea(x, y, w, h, dx, dy);
2073             } catch (InvalidPipeException e2) {
2074                 // Still catching the exception; we are not yet ready to
2075                 // validate the surfaceData correctly.  Fail for now and
2076                 // try again next time around.
2077             }
2078         } finally {
2079             surfaceData.markDirty();
2080         }
2081     }
2082 
2083     private void doCopyArea(int x, int y, int w, int h, int dx, int dy) {
2084         if (w <= 0 || h <= 0) {
2085             return;
2086         }
2087         SurfaceData theData = surfaceData;
2088         if (theData.copyArea(this, x, y, w, h, dx, dy)) {
2089             return;
2090         }
2091         if (transformState >= TRANSFORM_TRANSLATESCALE) {
2092             throw new InternalError("transformed copyArea not implemented yet");
2093         }
2094         // REMIND: This method does not deal with missing data from the
2095         // source object (i.e. it does not send exposure events...)
2096 
2097         Region clip = getCompClip();
2098 
2099         Composite comp = composite;
2100         if (lastCAcomp != comp) {
2101             SurfaceType dsttype = theData.getSurfaceType();
2102             CompositeType comptype = imageComp;
2103             if (CompositeType.SrcOverNoEa.equals(comptype) &&
2104                 theData.getTransparency() == Transparency.OPAQUE)
2105             {
2106                 comptype = CompositeType.SrcNoEa;
2107             }
2108             lastCAblit = Blit.locate(dsttype, comptype, dsttype);
2109             lastCAcomp = comp;
2110         }
2111 
2112         x += transX;
2113         y += transY;







2114 
2115         Blit ob = lastCAblit;
2116         if (dy == 0 && dx > 0 && dx < w) {
2117             while (w > 0) {
2118                 int partW = Math.min(w, dx);
2119                 w -= partW;
2120                 int sx = x + w;
2121                 ob.Blit(theData, theData, comp, clip,
2122                         sx, y, sx+dx, y+dy, partW, h);
2123             }
2124             return;
2125         }
2126         if (dy > 0 && dy < h && dx > -w && dx < w) {
2127             while (h > 0) {
2128                 int partH = Math.min(h, dy);
2129                 h -= partH;
2130                 int sy = y + h;
2131                 ob.Blit(theData, theData, comp, clip,
2132                         x, sy, x+dx, sy+dy, w, partH);
2133             }


3034         }
3035 
3036         try {
3037             textpipe.drawChars(this, chData, 0, length, x, y);
3038         } catch (InvalidPipeException e) {
3039             try {
3040                 revalidateAll();
3041                 textpipe.drawChars(this, chData, 0, length, x, y);
3042             } catch (InvalidPipeException e2) {
3043                 // Still catching the exception; we are not yet ready to
3044                 // validate the surfaceData correctly.  Fail for now and
3045                 // try again next time around.
3046             }
3047         } finally {
3048             surfaceData.markDirty();
3049         }
3050     }
3051 // end of text rendering methods
3052 
3053     private static boolean isHiDPIImage(final Image img) {





3054         return SurfaceManager.getImageScale(img) != 1;
3055     }
3056 
3057     private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
3058                                    int dy2, int sx1, int sy1, int sx2, int sy2,
3059                                    Color bgcolor, ImageObserver observer) {
3060         final int scale = SurfaceManager.getImageScale(img);
3061         sx1 = Region.clipScale(sx1, scale);
3062         sx2 = Region.clipScale(sx2, scale);
3063         sy1 = Region.clipScale(sy1, scale);
3064         sy2 = Region.clipScale(sy2, scale);
3065         try {
3066             return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
3067                                         sx2, sy2, bgcolor, observer);
3068         } catch (InvalidPipeException e) {
3069             try {
3070                 revalidateAll();
3071                 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1,
3072                                             sy1, sx2, sy2, bgcolor, observer);
3073             } catch (InvalidPipeException e2) {
3074                 // Still catching the exception; we are not yet ready to
3075                 // validate the surfaceData correctly.  Fail for now and
3076                 // try again next time around.
3077                 return false;
3078             }
3079         } finally {
3080             surfaceData.markDirty();
3081         }
3082     }
3083 





























3084     /**
3085      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3086      * callback object.
3087      */
3088     public boolean drawImage(Image img, int x, int y, int width, int height,
3089                              ImageObserver observer) {
3090         return drawImage(img, x, y, width, height, null, observer);
3091     }
3092 
3093     /**
3094      * Not part of the advertised API but a useful utility method
3095      * to call internally.  This is for the case where we are
3096      * drawing to/from given coordinates using a given width/height,
3097      * but we guarantee that the surfaceData's width/height of the src and dest
3098      * areas are equal (no scale needed). Note that this method intentionally
3099      * ignore scale factor of the source image, and copy it as is.
3100      */
3101     public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
3102                              int width, int height, Color bgcolor,
3103                              ImageObserver observer) {


3341                 return imagepipe.transformImage(this, img, xform, observer);
3342             } catch (InvalidPipeException e2) {
3343                 // Still catching the exception; we are not yet ready to
3344                 // validate the surfaceData correctly.  Fail for now and
3345                 // try again next time around.
3346                 return false;
3347             }
3348         } finally {
3349             surfaceData.markDirty();
3350         }
3351     }
3352 
3353     public void drawImage(BufferedImage bImg,
3354                           BufferedImageOp op,
3355                           int x,
3356                           int y)  {
3357 
3358         if (bImg == null) {
3359             return;
3360         }
3361 



3362         try {
3363             imagepipe.transformImage(this, bImg, op, x, y);
3364         } catch (InvalidPipeException e) {
3365             try {
3366                 revalidateAll();
3367                 imagepipe.transformImage(this, bImg, op, x, y);
3368             } catch (InvalidPipeException e2) {
3369                 // Still catching the exception; we are not yet ready to
3370                 // validate the surfaceData correctly.  Fail for now and
3371                 // try again next time around.
3372             }
3373         } finally {
3374             surfaceData.markDirty();
3375         }
3376     }
3377 
3378     /**
3379     * Get the rendering context of the font
3380     * within this Graphics2D context.
3381     */




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


2072                 revalidateAll();
2073                 doCopyArea(x, y, w, h, dx, dy);
2074             } catch (InvalidPipeException e2) {
2075                 // Still catching the exception; we are not yet ready to
2076                 // validate the surfaceData correctly.  Fail for now and
2077                 // try again next time around.
2078             }
2079         } finally {
2080             surfaceData.markDirty();
2081         }
2082     }
2083 
2084     private void doCopyArea(int x, int y, int w, int h, int dx, int dy) {
2085         if (w <= 0 || h <= 0) {
2086             return;
2087         }
2088         SurfaceData theData = surfaceData;
2089         if (theData.copyArea(this, x, y, w, h, dx, dy)) {
2090             return;
2091         }
2092         if (transformState > TRANSFORM_TRANSLATESCALE) {
2093             throw new InternalError("transformed copyArea not implemented yet");
2094         }
2095         // REMIND: This method does not deal with missing data from the
2096         // source object (i.e. it does not send exposure events...)
2097         
2098         Region clip = getCompClip();
2099 
2100         Composite comp = composite;
2101         if (lastCAcomp != comp) {
2102             SurfaceType dsttype = theData.getSurfaceType();
2103             CompositeType comptype = imageComp;
2104             if (CompositeType.SrcOverNoEa.equals(comptype) &&
2105                 theData.getTransparency() == Transparency.OPAQUE)
2106             {
2107                 comptype = CompositeType.SrcNoEa;
2108             }
2109             lastCAblit = Blit.locate(dsttype, comptype, dsttype);
2110             lastCAcomp = comp;
2111         }
2112 
2113         double[] coords = {x, y, x + w, y + h, x + dx, y + dy};
2114         transform.transform(coords, 0, coords, 0, 3);
2115 
2116         x = (int)Math.ceil(coords[0] - 0.5);
2117         y = (int)Math.ceil(coords[1] - 0.5);
2118         w = ((int)Math.ceil(coords[2] - 0.5)) - x;
2119         h = ((int)Math.ceil(coords[3] - 0.5)) - y;
2120         dx = ((int)Math.ceil(coords[4] - 0.5)) - x;
2121         dy = ((int)Math.ceil(coords[5] - 0.5)) - y;
2122         
2123         Blit ob = lastCAblit;
2124         if (dy == 0 && dx > 0 && dx < w) {
2125             while (w > 0) {
2126                 int partW = Math.min(w, dx);
2127                 w -= partW;
2128                 int sx = x + w;
2129                 ob.Blit(theData, theData, comp, clip,
2130                         sx, y, sx+dx, y+dy, partW, h);
2131             }
2132             return;
2133         }
2134         if (dy > 0 && dy < h && dx > -w && dx < w) {
2135             while (h > 0) {
2136                 int partH = Math.min(h, dy);
2137                 h -= partH;
2138                 int sy = y + h;
2139                 ob.Blit(theData, theData, comp, clip,
2140                         x, sy, x+dx, sy+dy, w, partH);
2141             }


3042         }
3043 
3044         try {
3045             textpipe.drawChars(this, chData, 0, length, x, y);
3046         } catch (InvalidPipeException e) {
3047             try {
3048                 revalidateAll();
3049                 textpipe.drawChars(this, chData, 0, length, x, y);
3050             } catch (InvalidPipeException e2) {
3051                 // Still catching the exception; we are not yet ready to
3052                 // validate the surfaceData correctly.  Fail for now and
3053                 // try again next time around.
3054             }
3055         } finally {
3056             surfaceData.markDirty();
3057         }
3058     }
3059 // end of text rendering methods
3060     
3061     private static boolean isHiDPIImage(final Image img) {
3062         if (img instanceof OffScreenImage &&
3063             !((OffScreenImage)img).isReturnLayoutSize())
3064         {
3065             return false;
3066         }
3067         return SurfaceManager.getImageScale(img) != 1;
3068     }
3069 
3070     private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
3071                                    int dy2, int sx1, int sy1, int sx2, int sy2,
3072                                    Color bgcolor, ImageObserver observer) {        
3073         final int scale = SurfaceManager.getImageScale(img);
3074         sx1 = Region.clipScale(sx1, scale);
3075         sx2 = Region.clipScale(sx2, scale);
3076         sy1 = Region.clipScale(sy1, scale);
3077         sy2 = Region.clipScale(sy2, scale);
3078         try {
3079             return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
3080                                         sx2, sy2, bgcolor, observer);
3081         } catch (InvalidPipeException e) {
3082             try {
3083                 revalidateAll();
3084                 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1,
3085                                             sy1, sx2, sy2, bgcolor, observer);
3086             } catch (InvalidPipeException e2) {
3087                 // Still catching the exception; we are not yet ready to
3088                 // validate the surfaceData correctly.  Fail for now and
3089                 // try again next time around.
3090                 return false;
3091             }
3092         } finally {
3093             surfaceData.markDirty();
3094         }
3095     }
3096 
3097     private boolean drawHiDPIImage(BufferedImage img, BufferedImageOp op,
3098                                    int x, int y)
3099     {
3100         final int scale = SurfaceManager.getImageScale(img);
3101         if (op != null) {
3102             if (op instanceof AffineTransformOp) {
3103                 AffineTransformOp atop = (AffineTransformOp)op;
3104                 AffineTransform at = atop.getTransform();
3105                 try {
3106                     // The "atop" transform may move the bounding rect of the image,
3107                     // so the scale transform should be applied before.
3108                     at.concatenate(AffineTransform.getScaleInstance(scale, scale).createInverse());
3109                 } catch (Exception e) {
3110                     // the inverse is always possible
3111                 }
3112                 atop = new AffineTransformOp(at, atop.getInterpolationType());
3113                 imagepipe.transformImage(this, img, atop, x, y);
3114                 return true;
3115             }
3116             img = op.filter(img, null);
3117         }
3118         int w = img.getWidth();
3119         int h = img.getHeight();
3120         return drawHiDPIImage(img,
3121                               x, y, x + w, y + h,
3122                               0, 0, w, h,
3123                               backgroundColor, null);
3124     }
3125 
3126     /**
3127      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3128      * callback object.
3129      */
3130     public boolean drawImage(Image img, int x, int y, int width, int height,
3131                              ImageObserver observer) {
3132         return drawImage(img, x, y, width, height, null, observer);
3133     }
3134 
3135     /**
3136      * Not part of the advertised API but a useful utility method
3137      * to call internally.  This is for the case where we are
3138      * drawing to/from given coordinates using a given width/height,
3139      * but we guarantee that the surfaceData's width/height of the src and dest
3140      * areas are equal (no scale needed). Note that this method intentionally
3141      * ignore scale factor of the source image, and copy it as is.
3142      */
3143     public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
3144                              int width, int height, Color bgcolor,
3145                              ImageObserver observer) {


3383                 return imagepipe.transformImage(this, img, xform, observer);
3384             } catch (InvalidPipeException e2) {
3385                 // Still catching the exception; we are not yet ready to
3386                 // validate the surfaceData correctly.  Fail for now and
3387                 // try again next time around.
3388                 return false;
3389             }
3390         } finally {
3391             surfaceData.markDirty();
3392         }
3393     }
3394 
3395     public void drawImage(BufferedImage bImg,
3396                           BufferedImageOp op,
3397                           int x,
3398                           int y)  {
3399 
3400         if (bImg == null) {
3401             return;
3402         }
3403         if (isHiDPIImage(bImg)) {
3404             drawHiDPIImage(bImg, op, x, y);
3405             return;
3406         }
3407         try {
3408             imagepipe.transformImage(this, bImg, op, x, y);
3409         } catch (InvalidPipeException e) {
3410             try {
3411                 revalidateAll();
3412                 imagepipe.transformImage(this, bImg, op, x, y);
3413             } catch (InvalidPipeException e2) {
3414                 // Still catching the exception; we are not yet ready to
3415                 // validate the surfaceData correctly.  Fail for now and
3416                 // try again next time around.
3417             }
3418         } finally {
3419             surfaceData.markDirty();
3420         }
3421     }
3422 
3423     /**
3424     * Get the rendering context of the font
3425     * within this Graphics2D context.
3426     */