< prev index next >

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

Print this page




  44 import java.awt.image.WritableRaster;
  45 import java.awt.Image;
  46 import java.awt.Composite;
  47 import java.awt.Color;
  48 import java.awt.image.ColorModel;
  49 import java.awt.GraphicsConfiguration;
  50 import java.awt.Paint;
  51 import java.awt.GradientPaint;
  52 import java.awt.LinearGradientPaint;
  53 import java.awt.RadialGradientPaint;
  54 import java.awt.TexturePaint;
  55 import java.awt.geom.Rectangle2D;
  56 import java.awt.geom.PathIterator;
  57 import java.awt.geom.GeneralPath;
  58 import java.awt.Shape;
  59 import java.awt.Stroke;
  60 import java.awt.FontMetrics;
  61 import java.awt.Rectangle;
  62 import java.text.AttributedCharacterIterator;
  63 import java.awt.Font;
  64 import java.awt.Point;
  65 import java.awt.image.ImageObserver;
  66 import java.awt.Transparency;
  67 import java.awt.font.GlyphVector;
  68 import java.awt.font.TextLayout;
  69 
  70 import sun.awt.image.SurfaceManager;
  71 import sun.font.FontDesignMetrics;
  72 import sun.font.FontUtilities;
  73 import sun.java2d.pipe.PixelDrawPipe;
  74 import sun.java2d.pipe.PixelFillPipe;
  75 import sun.java2d.pipe.ShapeDrawPipe;
  76 import sun.java2d.pipe.ValidatePipe;
  77 import sun.java2d.pipe.ShapeSpanIterator;
  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 java.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 {
 118     /*
 119      * Attribute States
 120      */
 121     /* Paint */


3069             return;
3070         }
3071 
3072         try {
3073             textpipe.drawChars(this, chData, 0, length, x, y);
3074         } catch (InvalidPipeException e) {
3075             try {
3076                 revalidateAll();
3077                 textpipe.drawChars(this, chData, 0, length, x, y);
3078             } catch (InvalidPipeException e2) {
3079                 // Still catching the exception; we are not yet ready to
3080                 // validate the surfaceData correctly.  Fail for now and
3081                 // try again next time around.
3082             }
3083         } finally {
3084             surfaceData.markDirty();
3085         }
3086     }
3087 // end of text rendering methods
3088 
3089     private boolean isHiDPIImage(final Image img) {
3090         return (SurfaceManager.getImageScale(img) != 1)
3091                 || img instanceof MultiResolutionImage;
3092     }
3093 
3094     private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2,
3095                                    int dy2, int sx1, int sy1, int sx2, int sy2,
3096                                    Color bgcolor, ImageObserver observer) {
3097 
3098         if (SurfaceManager.getImageScale(img) != 1) {  // Volatile Image
3099             final int scale = SurfaceManager.getImageScale(img);
3100             sx1 = Region.clipScale(sx1, scale);
3101             sx2 = Region.clipScale(sx2, scale);
3102             sy1 = Region.clipScale(sy1, scale);
3103             sy2 = Region.clipScale(sy2, scale);
3104         } else if (img instanceof MultiResolutionImage) {











3105             // get scaled destination image size
3106 
3107             int width = img.getWidth(observer);
3108             int height = img.getHeight(observer);
3109 
3110             Image resolutionVariant = getResolutionVariant(
3111                     (MultiResolutionImage) img, width, height,
3112                     dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);


3113 
3114             if (resolutionVariant != img && resolutionVariant != null) {
3115                 // recalculate source region for the resolution variant
3116 
3117                 ImageObserver rvObserver = MultiResolutionToolkitImage.
3118                         getResolutionVariantObserver(img, observer,
3119                                 width, height, -1, -1);
3120 
3121                 int rvWidth = resolutionVariant.getWidth(rvObserver);
3122                 int rvHeight = resolutionVariant.getHeight(rvObserver);
3123 
3124                 if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3125 
3126                     float widthScale = ((float) rvWidth) / width;
3127                     float heightScale = ((float) rvHeight) / height;
3128 
3129                     sx1 = Region.clipScale(sx1, widthScale);
3130                     sy1 = Region.clipScale(sy1, heightScale);
3131                     sx2 = Region.clipScale(sx2, widthScale);
3132                     sy2 = Region.clipScale(sy2, heightScale);
3133 
3134                     observer = rvObserver;
3135                     img = resolutionVariant;




3136                 }
3137             }












3138         }
3139 
3140         try {
3141             return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
3142                                         sx2, sy2, bgcolor, observer);
3143         } catch (InvalidPipeException e) {
3144             try {
3145                 revalidateAll();
3146                 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1,
3147                                             sy1, sx2, sy2, bgcolor, observer);
3148             } catch (InvalidPipeException e2) {
3149                 // Still catching the exception; we are not yet ready to
3150                 // validate the surfaceData correctly.  Fail for now and
3151                 // try again next time around.
3152                 return false;
3153             }
3154         } finally {
3155             surfaceData.markDirty();
3156         }
3157     }
3158 



















3159     private Image getResolutionVariant(MultiResolutionImage img,
3160             int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2,
3161             int sx1, int sy1, int sx2, int sy2) {
3162 
3163         if (srcWidth <= 0 || srcHeight <= 0) {
3164             return null;
3165         }
3166 
3167         int sw = sx2 - sx1;
3168         int sh = sy2 - sy1;
3169 
3170         if (sw == 0 || sh == 0) {
3171             return null;
3172         }
3173 
3174         int type = transform.getType();









3175         int dw = dx2 - dx1;
3176         int dh = dy2 - dy1;
3177 
3178         double destImageWidth;
3179         double destImageHeight;
3180 
3181         if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_BASE) {
3182             destImageWidth = srcWidth;
3183             destImageHeight = srcHeight;
3184         } else if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_DPI_FIT) {
3185             AffineTransform configTransform = getDefaultTransform();
3186             if (configTransform.isIdentity()) {
3187                 destImageWidth = srcWidth;
3188                 destImageHeight = srcHeight;
3189             } else {
3190                 destImageWidth = srcWidth * configTransform.getScaleX();
3191                 destImageHeight = srcHeight * configTransform.getScaleY();
3192             }
3193         } else {
3194             double destRegionWidth;
3195             double destRegionHeight;
3196 
3197             if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
3198                 destRegionWidth = dw;
3199                 destRegionHeight = dh;
3200             } else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
3201                 destRegionWidth = dw * transform.getScaleX();
3202                 destRegionHeight = dh * transform.getScaleY();
3203             } else {
3204                 destRegionWidth = dw * Math.hypot(
3205                         transform.getScaleX(), transform.getShearY());
3206                 destRegionHeight = dh * Math.hypot(
3207                         transform.getShearX(), transform.getScaleY());
3208             }
3209             destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
3210             destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
3211         }
3212 
3213         Image resolutionVariant
3214                 = img.getResolutionVariant(destImageWidth, destImageHeight);
3215 
3216         if (resolutionVariant instanceof ToolkitImage
3217                 && ((ToolkitImage) resolutionVariant).hasError()) {
3218             return null;
3219         }
3220 
3221         return resolutionVariant;
3222     }
3223 
3224     /**
3225      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3226      * callback object.
3227      */


3260         }
3261     }
3262 
3263     /**
3264      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3265      * solid background color and a callback object.
3266      */
3267     public boolean drawImage(Image img, int x, int y, int width, int height,
3268                              Color bg, ImageObserver observer) {
3269 
3270         if (img == null) {
3271             return true;
3272         }
3273 
3274         if ((width == 0) || (height == 0)) {
3275             return true;
3276         }
3277 
3278         final int imgW = img.getWidth(null);
3279         final int imgH = img.getHeight(null);
3280         if (isHiDPIImage(img)) {
3281             return drawHiDPIImage(img, x, y, x + width, y + height, 0, 0, imgW,
3282                                   imgH, bg, observer);


3283         }
3284 
3285         if (width == imgW && height == imgH) {
3286             return copyImage(img, x, y, 0, 0, width, height, bg, observer);
3287         }
3288 
3289         try {
3290             return imagepipe.scaleImage(this, img, x, y, width, height,
3291                                         bg, observer);
3292         } catch (InvalidPipeException e) {
3293             try {
3294                 revalidateAll();
3295                 return imagepipe.scaleImage(this, img, x, y, width, height,
3296                                             bg, observer);
3297             } catch (InvalidPipeException e2) {
3298                 // Still catching the exception; we are not yet ready to
3299                 // validate the surfaceData correctly.  Fail for now and
3300                 // try again next time around.
3301                 return false;
3302             }


3306     }
3307 
3308     /**
3309      * Draws an image at x,y in nonblocking mode.
3310      */
3311     public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
3312         return drawImage(img, x, y, null, observer);
3313     }
3314 
3315     /**
3316      * Draws an image at x,y in nonblocking mode with a solid background
3317      * color and a callback object.
3318      */
3319     public boolean drawImage(Image img, int x, int y, Color bg,
3320                              ImageObserver observer) {
3321 
3322         if (img == null) {
3323             return true;
3324         }
3325 
3326         if (isHiDPIImage(img)) {
3327             final int imgW = img.getWidth(null);
3328             final int imgH = img.getHeight(null);
3329             return drawHiDPIImage(img, x, y, x + imgW, y + imgH, 0, 0, imgW,
3330                                   imgH, bg, observer);



3331         }
3332 
3333         try {
3334             return imagepipe.copyImage(this, img, x, y, bg, observer);
3335         } catch (InvalidPipeException e) {
3336             try {
3337                 revalidateAll();
3338                 return imagepipe.copyImage(this, img, x, y, bg, observer);
3339             } catch (InvalidPipeException e2) {
3340                 // Still catching the exception; we are not yet ready to
3341                 // validate the surfaceData correctly.  Fail for now and
3342                 // try again next time around.
3343                 return false;
3344             }
3345         } finally {
3346             surfaceData.markDirty();
3347         }
3348     }
3349 
3350     /**


3361 
3362     /**
3363      * Draws a subrectangle of an image scaled to a destination rectangle in
3364      * nonblocking mode with a solid background color and a callback object.
3365      */
3366     public boolean drawImage(Image img,
3367                              int dx1, int dy1, int dx2, int dy2,
3368                              int sx1, int sy1, int sx2, int sy2,
3369                              Color bgcolor, ImageObserver observer) {
3370 
3371         if (img == null) {
3372             return true;
3373         }
3374 
3375         if (dx1 == dx2 || dy1 == dy2 ||
3376             sx1 == sx2 || sy1 == sy2)
3377         {
3378             return true;
3379         }
3380 
3381         if (isHiDPIImage(img)) {
3382             return drawHiDPIImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
3383                                   bgcolor, observer);



3384         }
3385 
3386         if (((sx2 - sx1) == (dx2 - dx1)) &&
3387             ((sy2 - sy1) == (dy2 - dy1)))
3388         {
3389             // Not a scale - forward it to a copy routine
3390             int srcX, srcY, dstX, dstY, width, height;
3391             if (sx2 > sx1) {
3392                 width = sx2 - sx1;
3393                 srcX = sx1;
3394                 dstX = dx1;
3395             } else {
3396                 width = sx1 - sx2;
3397                 srcX = sx2;
3398                 dstX = dx2;
3399             }
3400             if (sy2 > sy1) {
3401                 height = sy2-sy1;
3402                 srcY = sy1;
3403                 dstY = dy1;


3444      * @param img The image to be drawn.
3445      * @param xform The transformation from image space into user space.
3446      * @param observer The image observer to be notified on the image producing
3447      * progress.
3448      * @see #transform
3449      * @see #setComposite
3450      * @see #setClip
3451      */
3452     public boolean drawImage(Image img,
3453                              AffineTransform xform,
3454                              ImageObserver observer) {
3455 
3456         if (img == null) {
3457             return true;
3458         }
3459 
3460         if (xform == null || xform.isIdentity()) {
3461             return drawImage(img, 0, 0, null, observer);
3462         }
3463 
3464         if (isHiDPIImage(img)) {
3465             final int w = img.getWidth(null);
3466             final int h = img.getHeight(null);
3467             final AffineTransform tx = new AffineTransform(transform);
3468             transform(xform);
3469             boolean result = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h, null,
3470                                             observer);
3471             transform.setTransform(tx);
3472             invalidateTransform();
3473             return result;
3474         }
3475 
3476         try {
3477             return imagepipe.transformImage(this, img, xform, observer);
3478         } catch (InvalidPipeException e) {
3479             try {
3480                 revalidateAll();
3481                 return imagepipe.transformImage(this, img, xform, observer);
3482             } catch (InvalidPipeException e2) {
3483                 // Still catching the exception; we are not yet ready to
3484                 // validate the surfaceData correctly.  Fail for now and
3485                 // try again next time around.
3486                 return false;
3487             }
3488         } finally {
3489             surfaceData.markDirty();
3490         }
3491     }
3492 
3493     public void drawImage(BufferedImage bImg,




  44 import java.awt.image.WritableRaster;
  45 import java.awt.Image;
  46 import java.awt.Composite;
  47 import java.awt.Color;
  48 import java.awt.image.ColorModel;
  49 import java.awt.GraphicsConfiguration;
  50 import java.awt.Paint;
  51 import java.awt.GradientPaint;
  52 import java.awt.LinearGradientPaint;
  53 import java.awt.RadialGradientPaint;
  54 import java.awt.TexturePaint;
  55 import java.awt.geom.Rectangle2D;
  56 import java.awt.geom.PathIterator;
  57 import java.awt.geom.GeneralPath;
  58 import java.awt.Shape;
  59 import java.awt.Stroke;
  60 import java.awt.FontMetrics;
  61 import java.awt.Rectangle;
  62 import java.text.AttributedCharacterIterator;
  63 import java.awt.Font;

  64 import java.awt.image.ImageObserver;
  65 import java.awt.Transparency;
  66 import java.awt.font.GlyphVector;
  67 import java.awt.font.TextLayout;
  68 
  69 import sun.awt.image.SurfaceManager;
  70 import sun.font.FontDesignMetrics;
  71 import sun.font.FontUtilities;
  72 import sun.java2d.pipe.PixelDrawPipe;
  73 import sun.java2d.pipe.PixelFillPipe;
  74 import sun.java2d.pipe.ShapeDrawPipe;
  75 import sun.java2d.pipe.ValidatePipe;
  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 java.awt.image.MultiResolutionImage;
  97 
  98 import static java.awt.geom.AffineTransform.TYPE_FLIP;
  99 import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
 100 import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
 101 import java.awt.image.VolatileImage;
 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 {
 118     /*
 119      * Attribute States
 120      */
 121     /* Paint */


3069             return;
3070         }
3071 
3072         try {
3073             textpipe.drawChars(this, chData, 0, length, x, y);
3074         } catch (InvalidPipeException e) {
3075             try {
3076                 revalidateAll();
3077                 textpipe.drawChars(this, chData, 0, length, x, y);
3078             } catch (InvalidPipeException e2) {
3079                 // Still catching the exception; we are not yet ready to
3080                 // validate the surfaceData correctly.  Fail for now and
3081                 // try again next time around.
3082             }
3083         } finally {
3084             surfaceData.markDirty();
3085         }
3086     }
3087 // end of text rendering methods
3088 
3089     private Boolean drawHiDPIImage(Image img,
3090                                    int dx1, int dy1, int dx2, int dy2,
3091                                    int sx1, int sy1, int sx2, int sy2,
3092                                    Color bgcolor, ImageObserver observer,
3093                                    AffineTransform xform) {



3094 
3095         if (img instanceof VolatileImage) {
3096             final SurfaceData sd = SurfaceManager.getManager(img)
3097                     .getPrimarySurfaceData();
3098             final double scaleX = sd.getDefaultScaleX();
3099             final double scaleY = sd.getDefaultScaleY();
3100             if (scaleX == 1 && scaleY == 1) {
3101                 return null;
3102             }
3103             sx1 = Region.clipScale(sx1, scaleX);
3104             sx2 = Region.clipScale(sx2, scaleX);
3105             sy1 = Region.clipScale(sy1, scaleY);
3106             sy2 = Region.clipScale(sy2, scaleY);
3107 
3108             return scaleImage(img, dx1, dy1, dx2, dy2,
3109                               sx1, sy1, sx2, sy2,
3110                               bgcolor, xform, observer);
3111         } else if (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_BASE
3112                    && (img instanceof MultiResolutionImage)) {
3113             // get scaled destination image size
3114 
3115             int width = img.getWidth(observer);
3116             int height = img.getHeight(observer);
3117 
3118             MultiResolutionImage mrImage = (MultiResolutionImage) img;
3119             Image resolutionVariant = getResolutionVariant(mrImage, width, height,
3120                                                            dx1, dy1, dx2, dy2,
3121                                                            sx1, sy1, sx2, sy2,
3122                                                            xform);
3123 
3124             if (resolutionVariant != img && resolutionVariant != null) {
3125                 // recalculate source region for the resolution variant
3126 
3127                 ImageObserver rvObserver = MultiResolutionToolkitImage.
3128                         getResolutionVariantObserver(img, observer,
3129                                 width, height, -1, -1);
3130 
3131                 int rvWidth = resolutionVariant.getWidth(rvObserver);
3132                 int rvHeight = resolutionVariant.getHeight(rvObserver);
3133 
3134                 if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3135 
3136                     float widthScale = ((float) rvWidth) / width;
3137                     float heightScale = ((float) rvHeight) / height;
3138 
3139                     sx1 = Region.clipScale(sx1, widthScale);
3140                     sy1 = Region.clipScale(sy1, heightScale);
3141                     sx2 = Region.clipScale(sx2, widthScale);
3142                     sy2 = Region.clipScale(sy2, heightScale);
3143 
3144                     observer = rvObserver;
3145                     img = resolutionVariant;
3146                     return scaleImage(img, dx1, dy1, dx2, dy2,
3147                                       sx1, sy1, sx2, sy2,
3148                                       bgcolor, xform, observer);
3149                 }
3150             }
3151         }
3152         return null;
3153     }
3154 
3155     private boolean scaleImage(Image img, int dx1, int dy1, int dx2, int dy2,
3156                                int sx1, int sy1, int sx2, int sy2,
3157                                Color bgcolor, AffineTransform xform,
3158                                ImageObserver observer) {
3159 
3160         if (xform != null) {
3161             assert dx1 == 0 && dy1 == 0;
3162             assert dx2 == img.getWidth(observer) && dy2 == img.getHeight(observer);
3163             return transformImage(img, xform, observer);
3164         }
3165 
3166         try {
3167             return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1,
3168                                         sx2, sy2, bgcolor, observer);
3169         } catch (InvalidPipeException e) {
3170             try {
3171                 revalidateAll();
3172                 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1,
3173                                             sy1, sx2, sy2, bgcolor, observer);
3174             } catch (InvalidPipeException e2) {
3175                 // Still catching the exception; we are not yet ready to
3176                 // validate the surfaceData correctly.  Fail for now and
3177                 // try again next time around.
3178                 return false;
3179             }
3180         } finally {
3181             surfaceData.markDirty();
3182         }
3183     }
3184 
3185     private boolean transformImage(Image img, AffineTransform xform,
3186                                    ImageObserver observer) {
3187         try {
3188             return imagepipe.transformImage(this, img, xform, observer);
3189         } catch (InvalidPipeException e) {
3190             try {
3191                 revalidateAll();
3192                 return imagepipe.transformImage(this, img, xform, observer);
3193             } catch (InvalidPipeException e2) {
3194                 // Still catching the exception; we are not yet ready to
3195                 // validate the surfaceData correctly.  Fail for now and
3196                 // try again next time around.
3197                 return false;
3198             }
3199         } finally {
3200             surfaceData.markDirty();
3201         }
3202     }
3203 
3204     private Image getResolutionVariant(MultiResolutionImage img,
3205             int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2,
3206             int sx1, int sy1, int sx2, int sy2, AffineTransform xform) {
3207 
3208         if (srcWidth <= 0 || srcHeight <= 0) {
3209             return null;
3210         }
3211 
3212         int sw = sx2 - sx1;
3213         int sh = sy2 - sy1;
3214 
3215         if (sw == 0 || sh == 0) {
3216             return null;
3217         }
3218 
3219         AffineTransform tx;
3220 
3221         if (xform == null) {
3222             tx = transform;
3223         } else {
3224             tx = new AffineTransform(transform);
3225             tx.concatenate(xform);
3226         }
3227 
3228         int type = tx.getType();
3229         int dw = dx2 - dx1;
3230         int dh = dy2 - dy1;
3231 
3232         double destImageWidth;
3233         double destImageHeight;
3234 
3235         if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_BASE) {
3236             destImageWidth = srcWidth;
3237             destImageHeight = srcHeight;
3238         } else if (resolutionVariantHint == SunHints.INTVAL_RESOLUTION_VARIANT_DPI_FIT) {
3239             AffineTransform configTransform = getDefaultTransform();
3240             if (configTransform.isIdentity()) {
3241                 destImageWidth = srcWidth;
3242                 destImageHeight = srcHeight;
3243             } else {
3244                 destImageWidth = srcWidth * configTransform.getScaleX();
3245                 destImageHeight = srcHeight * configTransform.getScaleY();
3246             }
3247         } else {
3248             double destRegionWidth;
3249             double destRegionHeight;
3250 
3251             if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
3252                 destRegionWidth = dw;
3253                 destRegionHeight = dh;
3254             } else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
3255                 destRegionWidth = dw * tx.getScaleX();
3256                 destRegionHeight = dh * tx.getScaleY();
3257             } else {
3258                 destRegionWidth = dw * Math.hypot(
3259                         tx.getScaleX(), tx.getShearY());
3260                 destRegionHeight = dh * Math.hypot(
3261                         tx.getShearX(), tx.getScaleY());
3262             }
3263             destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
3264             destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
3265         }
3266 
3267         Image resolutionVariant
3268                 = img.getResolutionVariant(destImageWidth, destImageHeight);
3269 
3270         if (resolutionVariant instanceof ToolkitImage
3271                 && ((ToolkitImage) resolutionVariant).hasError()) {
3272             return null;
3273         }
3274 
3275         return resolutionVariant;
3276     }
3277 
3278     /**
3279      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3280      * callback object.
3281      */


3314         }
3315     }
3316 
3317     /**
3318      * Draws an image scaled to x,y,w,h in nonblocking mode with a
3319      * solid background color and a callback object.
3320      */
3321     public boolean drawImage(Image img, int x, int y, int width, int height,
3322                              Color bg, ImageObserver observer) {
3323 
3324         if (img == null) {
3325             return true;
3326         }
3327 
3328         if ((width == 0) || (height == 0)) {
3329             return true;
3330         }
3331 
3332         final int imgW = img.getWidth(null);
3333         final int imgH = img.getHeight(null);
3334         Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + width, y + height,
3335                                                  0, 0, imgW, imgH, bg, observer,
3336                                                  null);
3337         if (hidpiImageDrawn != null) {
3338             return hidpiImageDrawn;
3339         }
3340 
3341         if (width == imgW && height == imgH) {
3342             return copyImage(img, x, y, 0, 0, width, height, bg, observer);
3343         }
3344 
3345         try {
3346             return imagepipe.scaleImage(this, img, x, y, width, height,
3347                                         bg, observer);
3348         } catch (InvalidPipeException e) {
3349             try {
3350                 revalidateAll();
3351                 return imagepipe.scaleImage(this, img, x, y, width, height,
3352                                             bg, observer);
3353             } catch (InvalidPipeException e2) {
3354                 // Still catching the exception; we are not yet ready to
3355                 // validate the surfaceData correctly.  Fail for now and
3356                 // try again next time around.
3357                 return false;
3358             }


3362     }
3363 
3364     /**
3365      * Draws an image at x,y in nonblocking mode.
3366      */
3367     public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
3368         return drawImage(img, x, y, null, observer);
3369     }
3370 
3371     /**
3372      * Draws an image at x,y in nonblocking mode with a solid background
3373      * color and a callback object.
3374      */
3375     public boolean drawImage(Image img, int x, int y, Color bg,
3376                              ImageObserver observer) {
3377 
3378         if (img == null) {
3379             return true;
3380         }
3381 

3382         final int imgW = img.getWidth(null);
3383         final int imgH = img.getHeight(null);
3384         Boolean hidpiImageDrawn = drawHiDPIImage(img, x, y, x + imgW, y + imgH,
3385                                                  0, 0, imgW, imgH, bg, observer,
3386                                                  null);
3387         if (hidpiImageDrawn != null) {
3388             return hidpiImageDrawn;
3389         }
3390 
3391         try {
3392             return imagepipe.copyImage(this, img, x, y, bg, observer);
3393         } catch (InvalidPipeException e) {
3394             try {
3395                 revalidateAll();
3396                 return imagepipe.copyImage(this, img, x, y, bg, observer);
3397             } catch (InvalidPipeException e2) {
3398                 // Still catching the exception; we are not yet ready to
3399                 // validate the surfaceData correctly.  Fail for now and
3400                 // try again next time around.
3401                 return false;
3402             }
3403         } finally {
3404             surfaceData.markDirty();
3405         }
3406     }
3407 
3408     /**


3419 
3420     /**
3421      * Draws a subrectangle of an image scaled to a destination rectangle in
3422      * nonblocking mode with a solid background color and a callback object.
3423      */
3424     public boolean drawImage(Image img,
3425                              int dx1, int dy1, int dx2, int dy2,
3426                              int sx1, int sy1, int sx2, int sy2,
3427                              Color bgcolor, ImageObserver observer) {
3428 
3429         if (img == null) {
3430             return true;
3431         }
3432 
3433         if (dx1 == dx2 || dy1 == dy2 ||
3434             sx1 == sx2 || sy1 == sy2)
3435         {
3436             return true;
3437         }
3438 
3439         Boolean hidpiImageDrawn = drawHiDPIImage(img, dx1, dy1, dx2, dy2,
3440                                                  sx1, sy1, sx2, sy2,
3441                                                  bgcolor, observer, null);
3442 
3443         if (hidpiImageDrawn != null) {
3444             return hidpiImageDrawn;
3445         }
3446 
3447         if (((sx2 - sx1) == (dx2 - dx1)) &&
3448             ((sy2 - sy1) == (dy2 - dy1)))
3449         {
3450             // Not a scale - forward it to a copy routine
3451             int srcX, srcY, dstX, dstY, width, height;
3452             if (sx2 > sx1) {
3453                 width = sx2 - sx1;
3454                 srcX = sx1;
3455                 dstX = dx1;
3456             } else {
3457                 width = sx1 - sx2;
3458                 srcX = sx2;
3459                 dstX = dx2;
3460             }
3461             if (sy2 > sy1) {
3462                 height = sy2-sy1;
3463                 srcY = sy1;
3464                 dstY = dy1;


3505      * @param img The image to be drawn.
3506      * @param xform The transformation from image space into user space.
3507      * @param observer The image observer to be notified on the image producing
3508      * progress.
3509      * @see #transform
3510      * @see #setComposite
3511      * @see #setClip
3512      */
3513     public boolean drawImage(Image img,
3514                              AffineTransform xform,
3515                              ImageObserver observer) {
3516 
3517         if (img == null) {
3518             return true;
3519         }
3520 
3521         if (xform == null || xform.isIdentity()) {
3522             return drawImage(img, 0, 0, null, observer);
3523         }
3524 

3525         final int w = img.getWidth(null);
3526         final int h = img.getHeight(null);
3527         Boolean hidpiImageDrawn = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h,
3528                                                  null, observer, xform);
3529 
3530         if (hidpiImageDrawn != null) {
3531             return hidpiImageDrawn;


3532         }
3533 
3534         try {
3535             return imagepipe.transformImage(this, img, xform, observer);
3536         } catch (InvalidPipeException e) {
3537             try {
3538                 revalidateAll();
3539                 return imagepipe.transformImage(this, img, xform, observer);
3540             } catch (InvalidPipeException e2) {
3541                 // Still catching the exception; we are not yet ready to
3542                 // validate the surfaceData correctly.  Fail for now and
3543                 // try again next time around.
3544                 return false;
3545             }
3546         } finally {
3547             surfaceData.markDirty();
3548         }
3549     }
3550 
3551     public void drawImage(BufferedImage bImg,


< prev index next >