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 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 */ 220 public int lcdTextContrast; 221 private static int lcdTextContrastDefaultValue = 140; 222 223 private int interpolationHint; // raw value of rendering Hint 224 public int strokeHint; 225 226 public int interpolationType; // algorithm choice based on 227 // interpolation and render Hints 228 229 public RenderingHints hints; 230 231 public Region constrainClip; // lightweight bounds in pixels 232 public int constrainX; 233 public int constrainY; 234 235 public Region clipRegion; 236 public Shape usrClip; 237 protected Region devClip; // Actual physical drawable in pixels 238 239 private final int devScale; // Actual physical scale factor 240 241 // cached state for text rendering 242 private boolean validFontInfo; 243 private FontInfo fontInfo; 244 private FontInfo glyphVectorFontInfo; 245 private FontRenderContext glyphVectorFRC; 246 247 private final static int slowTextTransformMask = 248 AffineTransform.TYPE_GENERAL_TRANSFORM 249 | AffineTransform.TYPE_MASK_ROTATION 250 | AffineTransform.TYPE_FLIP; 251 252 static { 253 if (PerformanceLogger.loggingEnabled()) { 254 PerformanceLogger.setTime("SunGraphics2D static initialization"); 255 } 256 } 257 258 public SunGraphics2D(SurfaceData sd, Color fg, Color bg, Font f) { 259 surfaceData = sd; 260 foregroundColor = fg; 261 backgroundColor = bg; 262 263 transform = new AffineTransform(); 264 stroke = defaultStroke; 265 composite = defaultComposite; 266 paint = foregroundColor; 267 268 imageComp = CompositeType.SrcOverNoEa; 269 270 renderHint = SunHints.INTVAL_RENDER_DEFAULT; 271 antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; 272 textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; 273 fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; 274 lcdTextContrast = lcdTextContrastDefaultValue; 275 interpolationHint = -1; 276 strokeHint = SunHints.INTVAL_STROKE_DEFAULT; 277 278 interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 279 280 validateColor(); 281 282 devScale = sd.getDefaultScale(); 283 if (devScale != 1) { 284 transform.setToScale(devScale, devScale); 285 invalidateTransform(); 286 } 287 288 font = f; 289 if (font == null) { 290 font = defaultFont; 291 } 292 293 setDevClip(sd.getBounds()); 294 invalidatePipe(); 295 } 296 1232 interpolationHint = newHint; 1233 switch (newHint) { 1234 case SunHints.INTVAL_INTERPOLATION_BICUBIC: 1235 newHint = AffineTransformOp.TYPE_BICUBIC; 1236 break; 1237 case SunHints.INTVAL_INTERPOLATION_BILINEAR: 1238 newHint = AffineTransformOp.TYPE_BILINEAR; 1239 break; 1240 default: 1241 case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: 1242 newHint = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 1243 break; 1244 } 1245 stateChanged = (interpolationType != newHint); 1246 interpolationType = newHint; 1247 break; 1248 case SunHints.INTKEY_STROKE_CONTROL: 1249 stateChanged = (strokeHint != newHint); 1250 strokeHint = newHint; 1251 break; 1252 default: 1253 recognized = false; 1254 stateChanged = false; 1255 break; 1256 } 1257 if (recognized) { 1258 if (stateChanged) { 1259 invalidatePipe(); 1260 if (textStateChanged) { 1261 fontMetrics = null; 1262 this.cachedFRC = null; 1263 validFontInfo = false; 1264 this.glyphVectorFontInfo = null; 1265 } 1266 } 1267 if (hints != null) { 1268 hints.put(hintKey, hintValue); 1269 } 1270 return; 1271 } 1305 return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, 1306 textAntialiasHint); 1307 case SunHints.INTKEY_FRACTIONALMETRICS: 1308 return SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, 1309 fractionalMetricsHint); 1310 case SunHints.INTKEY_AATEXT_LCD_CONTRAST: 1311 return new Integer(lcdTextContrast); 1312 case SunHints.INTKEY_INTERPOLATION: 1313 switch (interpolationHint) { 1314 case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: 1315 return SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; 1316 case SunHints.INTVAL_INTERPOLATION_BILINEAR: 1317 return SunHints.VALUE_INTERPOLATION_BILINEAR; 1318 case SunHints.INTVAL_INTERPOLATION_BICUBIC: 1319 return SunHints.VALUE_INTERPOLATION_BICUBIC; 1320 } 1321 return null; 1322 case SunHints.INTKEY_STROKE_CONTROL: 1323 return SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, 1324 strokeHint); 1325 } 1326 return null; 1327 } 1328 1329 /** 1330 * Sets the preferences for the rendering algorithms. 1331 * Hint categories include controls for rendering quality and 1332 * overall time/quality trade-off in the rendering process. 1333 * @param hints The rendering hints to be set 1334 * @see RenderingHints 1335 */ 1336 public void setRenderingHints(Map<?,?> hints) { 1337 this.hints = null; 1338 renderHint = SunHints.INTVAL_RENDER_DEFAULT; 1339 antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; 1340 textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; 1341 fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; 1342 lcdTextContrast = lcdTextContrastDefaultValue; 1343 interpolationHint = -1; 1344 interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 3033 return; 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) { | 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 sun.awt.image.MultiResolutionImage; 98 99 import static java.awt.geom.AffineTransform.TYPE_FLIP; 100 import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE; 101 import static java.awt.geom.AffineTransform.TYPE_TRANSLATION; 102 import sun.awt.image.MultiResolutionToolkitImage; 103 import sun.awt.image.ToolkitImage; 104 105 /** 106 * This is a the master Graphics2D superclass for all of the Sun 107 * Graphics implementations. This class relies on subclasses to 108 * manage the various device information, but provides an overall 109 * general framework for performing all of the requests in the 110 * Graphics and Graphics2D APIs. 111 * 112 * @author Jim Graham 113 */ 114 public final class SunGraphics2D 115 extends Graphics2D 116 implements ConstrainableGraphics, Cloneable, DestSurfaceProvider 117 { 118 /* 119 * Attribute States 120 */ 121 /* Paint */ 122 @Native 123 public static final int PAINT_CUSTOM = 6; /* Any other Paint object */ 228 public int lcdTextContrast; 229 private static int lcdTextContrastDefaultValue = 140; 230 231 private int interpolationHint; // raw value of rendering Hint 232 public int strokeHint; 233 234 public int interpolationType; // algorithm choice based on 235 // interpolation and render Hints 236 237 public RenderingHints hints; 238 239 public Region constrainClip; // lightweight bounds in pixels 240 public int constrainX; 241 public int constrainY; 242 243 public Region clipRegion; 244 public Shape usrClip; 245 protected Region devClip; // Actual physical drawable in pixels 246 247 private final int devScale; // Actual physical scale factor 248 private int resolutionVariantHint; 249 250 // cached state for text rendering 251 private boolean validFontInfo; 252 private FontInfo fontInfo; 253 private FontInfo glyphVectorFontInfo; 254 private FontRenderContext glyphVectorFRC; 255 256 private final static int slowTextTransformMask = 257 AffineTransform.TYPE_GENERAL_TRANSFORM 258 | AffineTransform.TYPE_MASK_ROTATION 259 | AffineTransform.TYPE_FLIP; 260 261 static { 262 if (PerformanceLogger.loggingEnabled()) { 263 PerformanceLogger.setTime("SunGraphics2D static initialization"); 264 } 265 } 266 267 public SunGraphics2D(SurfaceData sd, Color fg, Color bg, Font f) { 268 surfaceData = sd; 269 foregroundColor = fg; 270 backgroundColor = bg; 271 272 transform = new AffineTransform(); 273 stroke = defaultStroke; 274 composite = defaultComposite; 275 paint = foregroundColor; 276 277 imageComp = CompositeType.SrcOverNoEa; 278 279 renderHint = SunHints.INTVAL_RENDER_DEFAULT; 280 antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; 281 textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; 282 fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; 283 lcdTextContrast = lcdTextContrastDefaultValue; 284 interpolationHint = -1; 285 strokeHint = SunHints.INTVAL_STROKE_DEFAULT; 286 resolutionVariantHint = SunHints.INTVAL_RESOLUTION_VARIANT_DEFAULT; 287 288 interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 289 290 validateColor(); 291 292 devScale = sd.getDefaultScale(); 293 if (devScale != 1) { 294 transform.setToScale(devScale, devScale); 295 invalidateTransform(); 296 } 297 298 font = f; 299 if (font == null) { 300 font = defaultFont; 301 } 302 303 setDevClip(sd.getBounds()); 304 invalidatePipe(); 305 } 306 1242 interpolationHint = newHint; 1243 switch (newHint) { 1244 case SunHints.INTVAL_INTERPOLATION_BICUBIC: 1245 newHint = AffineTransformOp.TYPE_BICUBIC; 1246 break; 1247 case SunHints.INTVAL_INTERPOLATION_BILINEAR: 1248 newHint = AffineTransformOp.TYPE_BILINEAR; 1249 break; 1250 default: 1251 case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: 1252 newHint = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 1253 break; 1254 } 1255 stateChanged = (interpolationType != newHint); 1256 interpolationType = newHint; 1257 break; 1258 case SunHints.INTKEY_STROKE_CONTROL: 1259 stateChanged = (strokeHint != newHint); 1260 strokeHint = newHint; 1261 break; 1262 case SunHints.INTKEY_RESOLUTION_VARIANT: 1263 stateChanged = (resolutionVariantHint != newHint); 1264 resolutionVariantHint = newHint; 1265 break; 1266 default: 1267 recognized = false; 1268 stateChanged = false; 1269 break; 1270 } 1271 if (recognized) { 1272 if (stateChanged) { 1273 invalidatePipe(); 1274 if (textStateChanged) { 1275 fontMetrics = null; 1276 this.cachedFRC = null; 1277 validFontInfo = false; 1278 this.glyphVectorFontInfo = null; 1279 } 1280 } 1281 if (hints != null) { 1282 hints.put(hintKey, hintValue); 1283 } 1284 return; 1285 } 1319 return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, 1320 textAntialiasHint); 1321 case SunHints.INTKEY_FRACTIONALMETRICS: 1322 return SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, 1323 fractionalMetricsHint); 1324 case SunHints.INTKEY_AATEXT_LCD_CONTRAST: 1325 return new Integer(lcdTextContrast); 1326 case SunHints.INTKEY_INTERPOLATION: 1327 switch (interpolationHint) { 1328 case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: 1329 return SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; 1330 case SunHints.INTVAL_INTERPOLATION_BILINEAR: 1331 return SunHints.VALUE_INTERPOLATION_BILINEAR; 1332 case SunHints.INTVAL_INTERPOLATION_BICUBIC: 1333 return SunHints.VALUE_INTERPOLATION_BICUBIC; 1334 } 1335 return null; 1336 case SunHints.INTKEY_STROKE_CONTROL: 1337 return SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, 1338 strokeHint); 1339 case SunHints.INTKEY_RESOLUTION_VARIANT: 1340 return SunHints.Value.get(SunHints.INTKEY_RESOLUTION_VARIANT, 1341 resolutionVariantHint); 1342 } 1343 return null; 1344 } 1345 1346 /** 1347 * Sets the preferences for the rendering algorithms. 1348 * Hint categories include controls for rendering quality and 1349 * overall time/quality trade-off in the rendering process. 1350 * @param hints The rendering hints to be set 1351 * @see RenderingHints 1352 */ 1353 public void setRenderingHints(Map<?,?> hints) { 1354 this.hints = null; 1355 renderHint = SunHints.INTVAL_RENDER_DEFAULT; 1356 antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; 1357 textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; 1358 fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; 1359 lcdTextContrast = lcdTextContrastDefaultValue; 1360 interpolationHint = -1; 1361 interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; 3050 return; 3051 } 3052 3053 try { 3054 textpipe.drawChars(this, chData, 0, length, x, y); 3055 } catch (InvalidPipeException e) { 3056 try { 3057 revalidateAll(); 3058 textpipe.drawChars(this, chData, 0, length, x, y); 3059 } catch (InvalidPipeException e2) { 3060 // Still catching the exception; we are not yet ready to 3061 // validate the surfaceData correctly. Fail for now and 3062 // try again next time around. 3063 } 3064 } finally { 3065 surfaceData.markDirty(); 3066 } 3067 } 3068 // end of text rendering methods 3069 3070 private boolean isHiDPIImage(final Image img) { 3071 return (SurfaceManager.getImageScale(img) != 1) || 3072 (resolutionVariantHint != SunHints.INTVAL_RESOLUTION_VARIANT_OFF 3073 && img instanceof MultiResolutionImage); 3074 } 3075 3076 private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2, 3077 int dy2, int sx1, int sy1, int sx2, int sy2, 3078 Color bgcolor, ImageObserver observer) { 3079 3080 if (SurfaceManager.getImageScale(img) != 1) { // Volatile Image 3081 final int scale = SurfaceManager.getImageScale(img); 3082 sx1 = Region.clipScale(sx1, scale); 3083 sx2 = Region.clipScale(sx2, scale); 3084 sy1 = Region.clipScale(sy1, scale); 3085 sy2 = Region.clipScale(sy2, scale); 3086 } else if (img instanceof MultiResolutionImage) { 3087 // get scaled destination image size 3088 3089 int width = img.getWidth(observer); 3090 int height = img.getHeight(observer); 3091 3092 Image resolutionVariant = getResolutionVariant( 3093 (MultiResolutionImage) img, width, height, 3094 dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2); 3095 3096 if (resolutionVariant != img && resolutionVariant != null) { 3097 // recalculate source region for the resolution variant 3098 3099 ImageObserver rvObserver = MultiResolutionToolkitImage. 3100 getResolutionVariantObserver(img, observer, 3101 width, height, -1, -1); 3102 3103 int rvWidth = resolutionVariant.getWidth(rvObserver); 3104 int rvHeight = resolutionVariant.getHeight(rvObserver); 3105 3106 if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) { 3107 3108 float widthScale = ((float) rvWidth) / width; 3109 float heightScale = ((float) rvHeight) / height; 3110 3111 sx1 = Region.clipScale(sx1, widthScale); 3112 sy1 = Region.clipScale(sy1, heightScale); 3113 sx2 = Region.clipScale(sx2, widthScale); 3114 sy2 = Region.clipScale(sy2, heightScale); 3115 3116 observer = rvObserver; 3117 img = resolutionVariant; 3118 } 3119 } 3120 } 3121 3122 try { 3123 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1, 3124 sx2, sy2, bgcolor, observer); 3125 } catch (InvalidPipeException e) { 3126 try { 3127 revalidateAll(); 3128 return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, 3129 sy1, sx2, sy2, bgcolor, observer); 3130 } catch (InvalidPipeException e2) { 3131 // Still catching the exception; we are not yet ready to 3132 // validate the surfaceData correctly. Fail for now and 3133 // try again next time around. 3134 return false; 3135 } 3136 } finally { 3137 surfaceData.markDirty(); 3138 } 3139 } 3140 3141 private Image getResolutionVariant(MultiResolutionImage img, 3142 int srcWidth, int srcHeight, int dx1, int dy1, int dx2, int dy2, 3143 int sx1, int sy1, int sx2, int sy2) { 3144 3145 if (srcWidth <= 0 || srcHeight <= 0) { 3146 return null; 3147 } 3148 3149 int sw = sx2 - sx1; 3150 int sh = sy2 - sy1; 3151 3152 if (sw == 0 || sh == 0) { 3153 return null; 3154 } 3155 3156 int type = transform.getType(); 3157 int dw = dx2 - dx1; 3158 int dh = dy2 - dy1; 3159 double destRegionWidth; 3160 double destRegionHeight; 3161 3162 if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP)) == 0) { 3163 destRegionWidth = dw; 3164 destRegionHeight = dh; 3165 } else if ((type & ~(TYPE_TRANSLATION | TYPE_FLIP | TYPE_MASK_SCALE)) == 0) { 3166 destRegionWidth = dw * transform.getScaleX(); 3167 destRegionHeight = dh * transform.getScaleY(); 3168 } else { 3169 destRegionWidth = dw * Math.hypot( 3170 transform.getScaleX(), transform.getShearY()); 3171 destRegionHeight = dh * Math.hypot( 3172 transform.getShearX(), transform.getScaleY()); 3173 } 3174 3175 int destImageWidth = (int) Math.abs(srcWidth * destRegionWidth / sw); 3176 int destImageHeight = (int) Math.abs(srcHeight * destRegionHeight / sh); 3177 3178 Image resolutionVariant 3179 = img.getResolutionVariant(destImageWidth, destImageHeight); 3180 3181 if (resolutionVariant instanceof ToolkitImage 3182 && ((ToolkitImage) resolutionVariant).hasError()) { 3183 return null; 3184 } 3185 3186 return resolutionVariant; 3187 } 3188 3189 /** 3190 * Draws an image scaled to x,y,w,h in nonblocking mode with a 3191 * callback object. 3192 */ 3193 public boolean drawImage(Image img, int x, int y, int width, int height, 3194 ImageObserver observer) { 3195 return drawImage(img, x, y, width, height, null, observer); 3196 } 3197 3198 /** 3199 * Not part of the advertised API but a useful utility method 3200 * to call internally. This is for the case where we are 3201 * drawing to/from given coordinates using a given width/height, 3202 * but we guarantee that the surfaceData's width/height of the src and dest 3203 * areas are equal (no scale needed). Note that this method intentionally 3204 * ignore scale factor of the source image, and copy it as is. 3205 */ 3206 public boolean copyImage(Image img, int dx, int dy, int sx, int sy, 3207 int width, int height, Color bgcolor, 3208 ImageObserver observer) { |