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,
|