Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit 8da6c8d

Browse files
committedSep 10, 2020
7183828: Invalid Image Variant when using anything other than BufferedImage
Reviewed-by: prr
1 parent ff21696 commit 8da6c8d

File tree

3 files changed

+313
-145
lines changed

3 files changed

+313
-145
lines changed
 

‎src/java.desktop/share/classes/sun/awt/image/SurfaceManager.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,18 @@
2525

2626
package sun.awt.image;
2727

28-
import java.awt.Color;
29-
import java.awt.GraphicsEnvironment;
3028
import java.awt.GraphicsConfiguration;
29+
import java.awt.GraphicsEnvironment;
3130
import java.awt.Image;
3231
import java.awt.ImageCapabilities;
3332
import java.awt.image.BufferedImage;
3433
import java.awt.image.VolatileImage;
35-
import java.util.concurrent.ConcurrentHashMap;
3634
import java.util.Iterator;
35+
import java.util.concurrent.ConcurrentHashMap;
36+
37+
import sun.java2d.InvalidPipeException;
3738
import sun.java2d.SurfaceData;
3839
import sun.java2d.SurfaceDataProxy;
39-
import sun.java2d.loops.CompositeType;
4040

4141
/**
4242
* The abstract base class that manages the various SurfaceData objects that
@@ -79,7 +79,7 @@ public static SurfaceManager getManager(Image img) {
7979
sMgr = new BufImgSurfaceManager(bi);
8080
setManager(bi, sMgr);
8181
} catch (ClassCastException e) {
82-
throw new IllegalArgumentException("Invalid Image variant");
82+
throw new InvalidPipeException("Invalid Image variant");
8383
}
8484
}
8585
return sMgr;

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

+141-139
Original file line numberDiff line numberDiff line change
@@ -25,82 +25,81 @@
2525

2626
package sun.java2d;
2727

28-
import java.awt.Graphics;
29-
import java.awt.Graphics2D;
30-
import java.awt.RenderingHints;
31-
import java.awt.RenderingHints.Key;
32-
import java.awt.geom.Area;
33-
import java.awt.geom.AffineTransform;
34-
import java.awt.geom.NoninvertibleTransformException;
3528
import java.awt.AlphaComposite;
3629
import java.awt.BasicStroke;
37-
import java.awt.image.BufferedImage;
38-
import java.awt.image.BufferedImageOp;
39-
import java.awt.image.RenderedImage;
40-
import java.awt.image.renderable.RenderableImage;
41-
import java.awt.image.renderable.RenderContext;
42-
import java.awt.image.AffineTransformOp;
43-
import java.awt.image.Raster;
44-
import java.awt.image.WritableRaster;
45-
import java.awt.Image;
46-
import java.awt.Composite;
4730
import java.awt.Color;
48-
import java.awt.image.ColorModel;
49-
import java.awt.GraphicsConfiguration;
50-
import java.awt.Paint;
31+
import java.awt.Composite;
32+
import java.awt.Font;
33+
import java.awt.FontMetrics;
5134
import java.awt.GradientPaint;
35+
import java.awt.Graphics;
36+
import java.awt.Graphics2D;
37+
import java.awt.GraphicsConfiguration;
38+
import java.awt.Image;
5239
import java.awt.LinearGradientPaint;
40+
import java.awt.Paint;
5341
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;
42+
import java.awt.Rectangle;
43+
import java.awt.RenderingHints;
44+
import java.awt.RenderingHints.Key;
5845
import java.awt.Shape;
5946
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;
47+
import java.awt.TexturePaint;
6548
import java.awt.Transparency;
49+
import java.awt.font.FontRenderContext;
6650
import java.awt.font.GlyphVector;
6751
import java.awt.font.TextLayout;
52+
import java.awt.geom.AffineTransform;
53+
import java.awt.geom.Area;
54+
import java.awt.geom.GeneralPath;
55+
import java.awt.geom.NoninvertibleTransformException;
56+
import java.awt.geom.PathIterator;
57+
import java.awt.geom.Rectangle2D;
58+
import java.awt.image.AffineTransformOp;
59+
import java.awt.image.BufferedImage;
60+
import java.awt.image.BufferedImageOp;
61+
import java.awt.image.ColorModel;
62+
import java.awt.image.ImageObserver;
63+
import java.awt.image.MultiResolutionImage;
64+
import java.awt.image.Raster;
65+
import java.awt.image.RenderedImage;
66+
import java.awt.image.VolatileImage;
67+
import java.awt.image.WritableRaster;
68+
import java.awt.image.renderable.RenderContext;
69+
import java.awt.image.renderable.RenderableImage;
70+
import java.lang.annotation.Native;
71+
import java.text.AttributedCharacterIterator;
72+
import java.util.Iterator;
73+
import java.util.Map;
6874

75+
import sun.awt.ConstrainableGraphics;
76+
import sun.awt.SunHints;
77+
import sun.awt.image.MultiResolutionToolkitImage;
6978
import sun.awt.image.SurfaceManager;
79+
import sun.awt.image.ToolkitImage;
80+
import sun.awt.util.PerformanceLogger;
7081
import sun.font.FontDesignMetrics;
7182
import sun.font.FontUtilities;
83+
import sun.java2d.loops.Blit;
84+
import sun.java2d.loops.CompositeType;
85+
import sun.java2d.loops.FontInfo;
86+
import sun.java2d.loops.MaskFill;
87+
import sun.java2d.loops.RenderLoops;
88+
import sun.java2d.loops.SurfaceType;
89+
import sun.java2d.loops.XORComposite;
90+
import sun.java2d.pipe.DrawImagePipe;
91+
import sun.java2d.pipe.LoopPipe;
7292
import sun.java2d.pipe.PixelDrawPipe;
7393
import sun.java2d.pipe.PixelFillPipe;
94+
import sun.java2d.pipe.Region;
7495
import sun.java2d.pipe.ShapeDrawPipe;
75-
import sun.java2d.pipe.ValidatePipe;
7696
import sun.java2d.pipe.ShapeSpanIterator;
77-
import sun.java2d.pipe.Region;
7897
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 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;
98+
import sun.java2d.pipe.ValidatePipe;
9799

98100
import static java.awt.geom.AffineTransform.TYPE_FLIP;
99101
import static java.awt.geom.AffineTransform.TYPE_MASK_SCALE;
100102
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;
104103

105104
/**
106105
* This is a the master Graphics2D superclass for all of the Sun
@@ -3102,99 +3101,102 @@ private Boolean drawHiDPIImage(Image img,
31023101
int sx1, int sy1, int sx2, int sy2,
31033102
Color bgcolor, ImageObserver observer,
31043103
AffineTransform xform) {
3105-
3106-
if (img instanceof VolatileImage) {
3107-
final SurfaceData sd = SurfaceManager.getManager(img)
3108-
.getPrimarySurfaceData();
3109-
final double scaleX = sd.getDefaultScaleX();
3110-
final double scaleY = sd.getDefaultScaleY();
3111-
if (scaleX == 1 && scaleY == 1) {
3112-
return null;
3113-
}
3114-
sx1 = Region.clipRound(sx1 * scaleX);
3115-
sx2 = Region.clipRound(sx2 * scaleX);
3116-
sy1 = Region.clipRound(sy1 * scaleY);
3117-
sy2 = Region.clipRound(sy2 * scaleY);
3118-
3119-
AffineTransform tx = null;
3120-
if (xform != null) {
3121-
tx = new AffineTransform(transform);
3122-
transform(xform);
3123-
}
3124-
boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
3125-
sx1, sy1, sx2, sy2,
3126-
bgcolor, observer);
3127-
if (tx != null) {
3128-
transform.setTransform(tx);
3129-
invalidateTransform();
3130-
}
3131-
return result;
3132-
} else if (img instanceof MultiResolutionImage) {
3133-
// get scaled destination image size
3134-
3135-
int width = img.getWidth(observer);
3136-
int height = img.getHeight(observer);
3137-
3138-
MultiResolutionImage mrImage = (MultiResolutionImage) img;
3139-
Image resolutionVariant = getResolutionVariant(mrImage, width, height,
3140-
dx1, dy1, dx2, dy2,
3141-
sx1, sy1, sx2, sy2,
3142-
xform);
3143-
3144-
if (resolutionVariant != img && resolutionVariant != null) {
3145-
// recalculate source region for the resolution variant
3146-
3147-
ImageObserver rvObserver = MultiResolutionToolkitImage.
3148-
getResolutionVariantObserver(img, observer,
3149-
width, height, -1, -1);
3150-
3151-
int rvWidth = resolutionVariant.getWidth(rvObserver);
3152-
int rvHeight = resolutionVariant.getHeight(rvObserver);
3153-
3154-
if (rvWidth < 0 || rvHeight < 0) {
3155-
// The resolution variant is not loaded yet, try to use default resolution
3156-
resolutionVariant = mrImage.getResolutionVariant(width, height);
3157-
rvWidth = resolutionVariant.getWidth(rvObserver);
3158-
rvHeight = resolutionVariant.getHeight(rvObserver);
3104+
try {
3105+
if (img instanceof VolatileImage) {
3106+
final SurfaceData sd = SurfaceManager.getManager(img)
3107+
.getPrimarySurfaceData();
3108+
final double scaleX = sd.getDefaultScaleX();
3109+
final double scaleY = sd.getDefaultScaleY();
3110+
if (scaleX == 1 && scaleY == 1) {
3111+
return null;
31593112
}
3160-
3161-
if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3162-
3163-
double widthScale = ((double) rvWidth) / width;
3164-
double heightScale = ((double) rvHeight) / height;
3165-
3166-
if (resolutionVariant instanceof VolatileImage) {
3167-
SurfaceData sd = SurfaceManager
3168-
.getManager(resolutionVariant)
3169-
.getPrimarySurfaceData();
3170-
widthScale *= sd.getDefaultScaleX();
3171-
heightScale *= sd.getDefaultScaleY();
3113+
sx1 = Region.clipRound(sx1 * scaleX);
3114+
sx2 = Region.clipRound(sx2 * scaleX);
3115+
sy1 = Region.clipRound(sy1 * scaleY);
3116+
sy2 = Region.clipRound(sy2 * scaleY);
3117+
3118+
AffineTransform tx = null;
3119+
if (xform != null) {
3120+
tx = new AffineTransform(transform);
3121+
transform(xform);
3122+
}
3123+
boolean result = scaleImage(img, dx1, dy1, dx2, dy2,
3124+
sx1, sy1, sx2, sy2,
3125+
bgcolor, observer);
3126+
if (tx != null) {
3127+
transform.setTransform(tx);
3128+
invalidateTransform();
3129+
}
3130+
return result;
3131+
} else if (img instanceof MultiResolutionImage) {
3132+
// get scaled destination image size
3133+
3134+
int width = img.getWidth(observer);
3135+
int height = img.getHeight(observer);
3136+
3137+
MultiResolutionImage mrImage = (MultiResolutionImage) img;
3138+
Image resolutionVariant = getResolutionVariant(mrImage, width, height,
3139+
dx1, dy1, dx2, dy2,
3140+
sx1, sy1, sx2, sy2,
3141+
xform);
3142+
3143+
if (resolutionVariant != img && resolutionVariant != null) {
3144+
// recalculate source region for the resolution variant
3145+
3146+
ImageObserver rvObserver = MultiResolutionToolkitImage.
3147+
getResolutionVariantObserver(img, observer,
3148+
width, height, -1, -1);
3149+
3150+
int rvWidth = resolutionVariant.getWidth(rvObserver);
3151+
int rvHeight = resolutionVariant.getHeight(rvObserver);
3152+
3153+
if (rvWidth < 0 || rvHeight < 0) {
3154+
// The resolution variant is not loaded yet, try to use default resolution
3155+
resolutionVariant = mrImage.getResolutionVariant(width, height);
3156+
rvWidth = resolutionVariant.getWidth(rvObserver);
3157+
rvHeight = resolutionVariant.getHeight(rvObserver);
31723158
}
31733159

3174-
sx1 = Region.clipScale(sx1, widthScale);
3175-
sy1 = Region.clipScale(sy1, heightScale);
3176-
sx2 = Region.clipScale(sx2, widthScale);
3177-
sy2 = Region.clipScale(sy2, heightScale);
3178-
3179-
observer = rvObserver;
3180-
img = resolutionVariant;
3181-
3182-
if (xform != null) {
3183-
assert dx1 == 0 && dy1 == 0;
3184-
assert dx2 == img.getWidth(observer);
3185-
assert dy2 == img.getHeight(observer);
3186-
AffineTransform renderTX = new AffineTransform(xform);
3187-
renderTX.scale(1 / widthScale, 1 / heightScale);
3188-
return transformImage(img, renderTX, observer);
3160+
if (0 < width && 0 < height && 0 < rvWidth && 0 < rvHeight) {
3161+
3162+
double widthScale = ((double) rvWidth) / width;
3163+
double heightScale = ((double) rvHeight) / height;
3164+
3165+
if (resolutionVariant instanceof VolatileImage) {
3166+
SurfaceData sd = SurfaceManager
3167+
.getManager(resolutionVariant)
3168+
.getPrimarySurfaceData();
3169+
widthScale *= sd.getDefaultScaleX();
3170+
heightScale *= sd.getDefaultScaleY();
3171+
}
3172+
3173+
sx1 = Region.clipScale(sx1, widthScale);
3174+
sy1 = Region.clipScale(sy1, heightScale);
3175+
sx2 = Region.clipScale(sx2, widthScale);
3176+
sy2 = Region.clipScale(sy2, heightScale);
3177+
3178+
observer = rvObserver;
3179+
img = resolutionVariant;
3180+
3181+
if (xform != null) {
3182+
assert dx1 == 0 && dy1 == 0;
3183+
assert dx2 == img.getWidth(observer);
3184+
assert dy2 == img.getHeight(observer);
3185+
AffineTransform renderTX = new AffineTransform(xform);
3186+
renderTX.scale(1 / widthScale, 1 / heightScale);
3187+
return transformImage(img, renderTX, observer);
3188+
}
3189+
3190+
return scaleImage(img, dx1, dy1, dx2, dy2,
3191+
sx1, sy1, sx2, sy2,
3192+
bgcolor, observer);
3193+
} else {
3194+
return false; // Image variant is not initialized yet
31893195
}
3190-
3191-
return scaleImage(img, dx1, dy1, dx2, dy2,
3192-
sx1, sy1, sx2, sy2,
3193-
bgcolor, observer);
3194-
} else {
3195-
return false; // Image variant is not initialized yet
31963196
}
31973197
}
3198+
} catch (InvalidPipeException e) {
3199+
return false;
31983200
}
31993201
return null;
32003202
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.Color;
25+
import java.awt.Graphics;
26+
import java.awt.Graphics2D;
27+
import java.awt.GraphicsConfiguration;
28+
import java.awt.Image;
29+
import java.awt.ImageCapabilities;
30+
import java.awt.geom.AffineTransform;
31+
import java.awt.image.BufferedImage;
32+
import java.awt.image.ImageObserver;
33+
import java.awt.image.ImageProducer;
34+
import java.awt.image.VolatileImage;
35+
36+
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
37+
38+
/**
39+
* @test
40+
* @bug 7183828
41+
* @summary Tests that no exceptions are thrown when we draw the custom image
42+
*/
43+
public final class CustomImage extends Image {
44+
45+
public static void main(String[] args) {
46+
Image ci = new CustomImage();
47+
VolatileImage cvi = new CustomVolatileImage();
48+
49+
BufferedImage bi = generateImage();
50+
Graphics2D g2d = bi.createGraphics();
51+
// Custom Image
52+
test(g2d.drawImage(ci, 0, 0, null), bi);
53+
test(g2d.drawImage(ci, 0, 0, 5, 5, 0, 0, 5, 5, Color.BLUE, null), bi);
54+
test(g2d.drawImage(ci, 0, 0, 9, 9, Color.BLUE, null), bi);
55+
test(g2d.drawImage(ci, 0, 0, 5, 5, 0, 0, 9, 9, Color.BLUE, null), bi);
56+
test(g2d.drawImage(ci, AffineTransform.getRotateInstance(30), null), bi);
57+
// Custom VolatileImage
58+
test(g2d.drawImage(cvi, 0, 0, null), bi);
59+
test(g2d.drawImage(cvi, 0, 0, 5, 5, 0, 0, 5, 5, Color.BLUE, null), bi);
60+
test(g2d.drawImage(cvi, 0, 0, 9, 9, Color.BLUE, null), bi);
61+
test(g2d.drawImage(cvi, 0, 0, 5, 5, 0, 0, 9, 9, Color.BLUE, null), bi);
62+
test(g2d.drawImage(cvi, AffineTransform.getRotateInstance(30), null), bi);
63+
64+
g2d.dispose();
65+
}
66+
67+
private static BufferedImage generateImage() {
68+
BufferedImage bi = new BufferedImage(100, 100, TYPE_INT_ARGB_PRE);
69+
Graphics g = bi.createGraphics();
70+
g.setColor(Color.GREEN);
71+
g.fillRect(0, 0, 100, 100);
72+
g.dispose();
73+
return bi;
74+
}
75+
76+
private static void test(boolean complete, BufferedImage bi) {
77+
if (complete) {
78+
throw new RuntimeException("Custom image successfully drawn");
79+
}
80+
for (int y = 0; y < bi.getHeight(); ++y) {
81+
for (int x = 0; x < bi.getWidth(); ++x) {
82+
if (bi.getRGB(x, y) != Color.GREEN.getRGB()) {
83+
throw new RuntimeException("The image was changed");
84+
}
85+
}
86+
}
87+
}
88+
89+
@Override
90+
public int getWidth(ImageObserver observer) {
91+
return 100;
92+
}
93+
94+
@Override
95+
public int getHeight(ImageObserver observer) {
96+
return 100;
97+
}
98+
99+
@Override
100+
public ImageProducer getSource() {
101+
return null;
102+
}
103+
104+
@Override
105+
public Graphics getGraphics() {
106+
return null;
107+
}
108+
109+
@Override
110+
public Object getProperty(String name, ImageObserver observer) {
111+
return null;
112+
}
113+
114+
private static final class CustomVolatileImage extends VolatileImage {
115+
116+
@Override
117+
public BufferedImage getSnapshot() {
118+
return null;
119+
}
120+
121+
@Override
122+
public int getWidth() {
123+
return 100;
124+
}
125+
126+
@Override
127+
public int getHeight() {
128+
return 100;
129+
}
130+
131+
@Override
132+
public Graphics2D createGraphics() {
133+
return null;
134+
}
135+
136+
@Override
137+
public int validate(GraphicsConfiguration gc) {
138+
return 0;
139+
}
140+
141+
@Override
142+
public boolean contentsLost() {
143+
return false;
144+
}
145+
146+
@Override
147+
public ImageCapabilities getCapabilities() {
148+
return null;
149+
}
150+
151+
@Override
152+
public int getWidth(ImageObserver observer) {
153+
return 100;
154+
}
155+
156+
@Override
157+
public int getHeight(ImageObserver observer) {
158+
return 100;
159+
}
160+
161+
@Override
162+
public Object getProperty(String name, ImageObserver observer) {
163+
return null;
164+
}
165+
}
166+
}

0 commit comments

Comments
 (0)
This repository has been archived.