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 sun.awt.util.PerformanceLogger;
92 import java.util.Map;
93 import java.util.Iterator;
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 */
3114 AffineTransform tx = null;
3115 if (xform != null) {
3116 tx = new AffineTransform(transform);
3117 transform(xform);
3118 }
3119 boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
3120 sx1, sy1, sx2, sy2,
3121 bgcolor, observer);
3122 if (tx != null) {
3123 transform.setTransform(tx);
3124 invalidateTransform();
3125 }
3126 return result;
3127 } else if (img instanceof MultiResolutionImage) {
3128 // get scaled destination image size
3129
3130 int width = img.getWidth(observer);
3131 int height = img.getHeight(observer);
3132
3133 MultiResolutionImage mrImage = (MultiResolutionImage) img;
3134 Image resolutionVariant = getResolutionVariant(mrImage, width, height,
3135 dx1, dy1, dx2, dy2,
3136 sx1, sy1, sx2, sy2,
3137 xform);
3138
3139 if (resolutionVariant != img && resolutionVariant != null) {
3140 // recalculate source region for the resolution variant
3141
3142 ImageObserver rvObserver = MultiResolutionToolkitImage.
3143 getResolutionVariantObserver(img, observer,
3144 width, height, -1, -1);
3145
3146 int rvWidth = resolutionVariant.getWidth(rvObserver);
3147 int rvHeight = resolutionVariant.getHeight(rvObserver);
3148
3149 if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3150
3151 double widthScale = ((double) rvWidth) / width;
3152 double heightScale = ((double) rvHeight) / height;
3153
3154 sx1 = Region.clipScale(sx1, widthScale);
3155 sy1 = Region.clipScale(sy1, heightScale);
3156 sx2 = Region.clipScale(sx2, widthScale);
3157 sy2 = Region.clipScale(sy2, heightScale);
3158
3159 observer = rvObserver;
3160 img = resolutionVariant;
3161
3162 if (xform != null) {
3163 assert dx1 == 0 && dy1 == 0;
3164 assert dx2 == img.getWidth(observer);
3204 AffineTransform xform,
3205 ImageObserver observer)
3206 {
3207 try {
3208 return imagepipe.transformImage(this, img, xform, observer);
3209 } catch (InvalidPipeException e) {
3210 try {
3211 revalidateAll();
3212 return imagepipe.transformImage(this, img, xform, observer);
3213 } catch (InvalidPipeException e2) {
3214 // Still catching the exception; we are not yet ready to
3215 // validate the surfaceData correctly. Fail for now and
3216 // try again next time around.
3217 return false;
3218 }
3219 } finally {
3220 surfaceData.markDirty();
3221 }
3222 }
3223
3224 private Image getResolutionVariant(MultiResolutionImage img,
3225 int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2,
3226 int sx1, int sy1, int sx2, int sy2, AffineTransform xform) {
3227
3228 if (srcWidth <= 0 || srcHeight <= 0) {
3229 return null;
3230 }
3231
3232 int sw = sx2 - sx1;
3233 int sh = sy2 - sy1;
3234
3235 if (sw == 0 || sh == 0) {
3236 return null;
3237 }
3238
3239 AffineTransform tx;
3240
3241 if (xform == null) {
3242 tx = transform;
3243 } else {
3244 tx = new AffineTransform(transform);
3245 tx.concatenate(xform);
3246 }
3267 } else {
3268 double destRegionWidth;
3269 double destRegionHeight;
3270
3271 if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
3272 destRegionWidth = dw;
3273 destRegionHeight = dh;
3274 } else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
3275 destRegionWidth = dw * tx.getScaleX();
3276 destRegionHeight = dh * tx.getScaleY();
3277 } else {
3278 destRegionWidth = dw * Math.hypot(
3279 tx.getScaleX(), tx.getShearY());
3280 destRegionHeight = dh * Math.hypot(
3281 tx.getShearX(), tx.getScaleY());
3282 }
3283 destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
3284 destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
3285 }
3286
3287 Image resolutionVariant
3288 = img.getResolutionVariant(destImageWidth, destImageHeight);
3289
3290 if (resolutionVariant instanceof ToolkitImage
3291 && ((ToolkitImage) resolutionVariant).hasError()) {
3292 return null;
3293 }
3294
3295 return resolutionVariant;
3296 }
3297
3298 /**
3299 * Draws an image scaled to x,y,w,h in nonblocking mode with a
3300 * callback object.
3301 */
3302 public boolean drawImage(Image img, int x, int y, int width, int height,
3303 ImageObserver observer) {
3304 return drawImage(img, x, y, width, height, null, observer);
3305 }
3306
3307 /**
3308 * Not part of the advertised API but a useful utility method
3309 * to call internally. This is for the case where we are
3310 * drawing to/from given coordinates using a given width/height,
3311 * but we guarantee that the surfaceData's width/height of the src and dest
3312 * areas are equal (no scale needed). Note that this method intentionally
3313 * ignore scale factor of the source image, and copy it as is.
3314 */
3315 public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
|
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 sun.awt.util.PerformanceLogger;
92 import java.util.Map;
93 import java.util.Iterator;
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.ResolutionVariantItem;
102 import java.awt.image.VolatileImage;
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 {
119 /*
120 * Attribute States
121 */
3115 AffineTransform tx = null;
3116 if (xform != null) {
3117 tx = new AffineTransform(transform);
3118 transform(xform);
3119 }
3120 boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
3121 sx1, sy1, sx2, sy2,
3122 bgcolor, observer);
3123 if (tx != null) {
3124 transform.setTransform(tx);
3125 invalidateTransform();
3126 }
3127 return result;
3128 } else if (img instanceof MultiResolutionImage) {
3129 // get scaled destination image size
3130
3131 int width = img.getWidth(observer);
3132 int height = img.getHeight(observer);
3133
3134 MultiResolutionImage mrImage = (MultiResolutionImage) img;
3135 ResolutionVariantItem<Image> rvItem =
3136 getResolutionVariant(mrImage, width, height,
3137 dx1, dy1, dx2, dy2,
3138 sx1, sy1, sx2, sy2,
3139 xform);
3140
3141
3142 if (rvItem != null) {
3143 // recalculate source region for the resolution variant
3144 Image resolutionVariant = rvItem.getValue();
3145
3146 ImageObserver rvObserver = MultiResolutionToolkitImage.
3147 getResolutionVariantObserver(img, observer,
3148 rvItem.getScaleX(),
3149 rvItem.getScaleY(),
3150 false);
3151
3152 int rvWidth = resolutionVariant.getWidth(rvObserver);
3153 int rvHeight = resolutionVariant.getHeight(rvObserver);
3154
3155 if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3156
3157 double widthScale = ((double) rvWidth) / width;
3158 double heightScale = ((double) rvHeight) / height;
3159
3160 sx1 = Region.clipScale(sx1, widthScale);
3161 sy1 = Region.clipScale(sy1, heightScale);
3162 sx2 = Region.clipScale(sx2, widthScale);
3163 sy2 = Region.clipScale(sy2, heightScale);
3164
3165 observer = rvObserver;
3166 img = resolutionVariant;
3167
3168 if (xform != null) {
3169 assert dx1 == 0 && dy1 == 0;
3170 assert dx2 == img.getWidth(observer);
3210 AffineTransform xform,
3211 ImageObserver observer)
3212 {
3213 try {
3214 return imagepipe.transformImage(this, img, xform, observer);
3215 } catch (InvalidPipeException e) {
3216 try {
3217 revalidateAll();
3218 return imagepipe.transformImage(this, img, xform, observer);
3219 } catch (InvalidPipeException e2) {
3220 // Still catching the exception; we are not yet ready to
3221 // validate the surfaceData correctly. Fail for now and
3222 // try again next time around.
3223 return false;
3224 }
3225 } finally {
3226 surfaceData.markDirty();
3227 }
3228 }
3229
3230 private ResolutionVariantItem<Image> getResolutionVariant(
3231 MultiResolutionImage img, int srcWidth, int srcHeight,
3232 int dx1, int dy1, int dx2, int dy2,
3233 int sx1, int sy1, int sx2, int sy2,
3234 AffineTransform xform) {
3235
3236 if (srcWidth <= 0 || srcHeight <= 0) {
3237 return null;
3238 }
3239
3240 int sw = sx2 - sx1;
3241 int sh = sy2 - sy1;
3242
3243 if (sw == 0 || sh == 0) {
3244 return null;
3245 }
3246
3247 AffineTransform tx;
3248
3249 if (xform == null) {
3250 tx = transform;
3251 } else {
3252 tx = new AffineTransform(transform);
3253 tx.concatenate(xform);
3254 }
3275 } else {
3276 double destRegionWidth;
3277 double destRegionHeight;
3278
3279 if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) {
3280 destRegionWidth = dw;
3281 destRegionHeight = dh;
3282 } else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) {
3283 destRegionWidth = dw * tx.getScaleX();
3284 destRegionHeight = dh * tx.getScaleY();
3285 } else {
3286 destRegionWidth = dw * Math.hypot(
3287 tx.getScaleX(), tx.getShearY());
3288 destRegionHeight = dh * Math.hypot(
3289 tx.getShearX(), tx.getScaleY());
3290 }
3291 destImageWidth = Math.abs(srcWidth * destRegionWidth / sw);
3292 destImageHeight = Math.abs(srcHeight * destRegionHeight / sh);
3293 }
3294
3295 ResolutionVariantItem<Image> rvItem = getResolutionVariantItem(
3296 img, srcWidth, srcHeight, destImageWidth, destImageHeight);
3297
3298 Image resolutionVariant = rvItem.getValue();
3299 if (resolutionVariant == img) {
3300 return null;
3301 }
3302
3303 if (resolutionVariant instanceof ToolkitImage
3304 && ((ToolkitImage) resolutionVariant).hasError()) {
3305 return null;
3306 }
3307
3308 return rvItem;
3309 }
3310
3311 private static ResolutionVariantItem<Image> getResolutionVariantItem(
3312 MultiResolutionImage img,
3313 double srcWidth, double srcHeight,
3314 double dstWidth, double dstHeight) {
3315
3316 if (img instanceof MultiResolutionToolkitImage) {
3317 return ((MultiResolutionToolkitImage) img)
3318 .getResolutionVariantItem(dstWidth, dstHeight);
3319 }
3320
3321 Image resolutionVariant
3322 = img.getResolutionVariant(dstWidth, dstHeight);
3323 double sx = resolutionVariant.getWidth(null) / srcWidth;
3324 double sy = resolutionVariant.getWidth(null) / srcHeight;
3325 return new ResolutionVariantItem<>(resolutionVariant, sx, sy);
3326 }
3327
3328 /**
3329 * Draws an image scaled to x,y,w,h in nonblocking mode with a
3330 * callback object.
3331 */
3332 public boolean drawImage(Image img, int x, int y, int width, int height,
3333 ImageObserver observer) {
3334 return drawImage(img, x, y, width, height, null, observer);
3335 }
3336
3337 /**
3338 * Not part of the advertised API but a useful utility method
3339 * to call internally. This is for the case where we are
3340 * drawing to/from given coordinates using a given width/height,
3341 * but we guarantee that the surfaceData's width/height of the src and dest
3342 * areas are equal (no scale needed). Note that this method intentionally
3343 * ignore scale factor of the source image, and copy it as is.
3344 */
3345 public boolean copyImage(Image img, int dx, int dy, int sx, int sy,
|