Revision: 7428
Author: [email protected]
Date: Tue Jan 19 07:13:03 2010
Log: Merge tr...@7424.
Prevent InlineResourceContext from creating too-long data: URLs.
Disables composition of lossy source images.
$ svn merge -c 7424 --ignore-ancestry
https://google-web-toolkit.googlecode.com/svn/trunk
http://code.google.com/p/google-web-toolkit/source/detail?r=7428
Added:
/releases/2.0/user/test/com/google/gwt/resources/client/complexLossy.jpg
Modified:
/releases/2.0/branch-info.txt
/releases/2.0/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
/releases/2.0/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java
/releases/2.0/user/test/com/google/gwt/resources/client/ImageResourceTest.java
/releases/2.0/user/test/com/google/gwt/resources/client/largeLossy.jpg
=======================================
--- /dev/null
+++
/releases/2.0/user/test/com/google/gwt/resources/client/complexLossy.jpg
Tue Jan 19 07:13:03 2010
Binary file, no diff available.
=======================================
--- /releases/2.0/branch-info.txt Tue Jan 19 06:59:10 2010
+++ /releases/2.0/branch-info.txt Tue Jan 19 07:13:03 2010
@@ -1262,3 +1262,8 @@
Allow CssResource to parse identifiers containing underscores or that
have a leading hyphen.
svn merge -c 7413 --ignore-ancestry
https://google-web-toolkit.googlecode.com/svn/trunk
+tr...@7424 was merged into this branch
+ Prevent InlineResourceContext from creating too-long data: URLs.
+ Disables composition of lossy source images.
+ svn merge -c 7424 --ignore-ancestry
https://google-web-toolkit.googlecode.com/svn/trunk
+
=======================================
---
/releases/2.0/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
Thu Jul 30 11:19:40 2009
+++
/releases/2.0/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
Tue Jan 19 07:13:03 2010
@@ -24,6 +24,7 @@
public class ImageResourcePrototype implements ImageResource {
private final boolean animated;
+ private final boolean lossy;
private final String name;
private final String url;
private final int left;
@@ -35,7 +36,7 @@
* Only called by generated code.
*/
public ImageResourcePrototype(String name, String url, int left, int top,
- int width, int height, boolean animated) {
+ int width, int height, boolean animated, boolean lossy) {
this.name = name;
this.left = left;
this.top = top;
@@ -43,6 +44,7 @@
this.width = width;
this.url = url;
this.animated = animated;
+ this.lossy = lossy;
}
/**
@@ -87,4 +89,8 @@
public boolean isAnimated() {
return animated;
}
-}
+
+ public boolean isLossy() {
+ return lossy;
+ }
+}
=======================================
---
/releases/2.0/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
Wed May 27 06:48:54 2009
+++
/releases/2.0/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
Tue Jan 19 07:13:03 2010
@@ -21,6 +21,11 @@
import com.google.gwt.core.ext.typeinfo.JClassType;
class InlineResourceContext extends StaticResourceContext {
+ /**
+ * String constants in Java have a maximum limit that we must obey.
+ */
+ public static final int MAX_ENCODED_SIZE = (2 << 15) - 1;
+
InlineResourceContext(TreeLogger logger, GeneratorContext context,
JClassType resourceBundleType) {
super(logger, context, resourceBundleType);
@@ -37,10 +42,19 @@
String base64Contents = toBase64(data);
- return "\"data:" + mimeType + ";base64," + base64Contents + "\"";
- } else {
- return super.deploy(suggestedFileName, mimeType, data, true);
- }
+ String encoded = "\"data:" + mimeType + ";base64," + base64Contents
+ + "\"";
+
+ /*
+ * We know that the encoded format will be one byte per character,
since
+ * we're using only ASCII characters.
+ */
+ if (encoded.length() < MAX_ENCODED_SIZE) {
+ return encoded;
+ }
+ }
+
+ return super.deploy(suggestedFileName, mimeType, data, true);
}
@Override
=======================================
---
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java
Wed Oct 28 07:24:14 2009
+++
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java
Tue Jan 19 07:13:03 2010
@@ -20,6 +20,8 @@
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import org.w3c.dom.Node;
+
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
@@ -42,6 +44,8 @@
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.stream.MemoryCacheImageInputStream;
/**
@@ -294,7 +298,7 @@
*/
static class ImageRect implements HasRect {
- private boolean hasBeenPositioned;
+ private boolean hasBeenPositioned, lossy;
private final int height, width;
private final BufferedImage[] images;
private int left, top;
@@ -367,6 +371,14 @@
public boolean isAnimated() {
return images.length > 1;
}
+
+ public boolean isLossy() {
+ return lossy;
+ }
+
+ public void setLossy(boolean lossy) {
+ this.lossy = lossy;
+ }
public void setPosition(int left, int top) {
hasBeenPositioned = true;
@@ -669,6 +681,8 @@
"Adding image '" + imageName + "'", null);
BufferedImage image = null;
+ // Be safe by default and assume that the incoming image is lossy
+ boolean lossy = true;
// Load the image
try {
/*
@@ -689,6 +703,30 @@
} else if (numImages == 1) {
try {
image = reader.read(0);
+ IIOMetadata metadata = reader.getImageMetadata(0);
+ if (metadata != null
+ && metadata.isStandardMetadataFormatSupported()) {
+ //
http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/metadata/doc-files/standard_metadata.html
+ Node data =
metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
+ metadata : for (int i = 0, j =
data.getChildNodes().getLength(); i < j; i++) {
+ Node child = data.getChildNodes().item(i);
+ if (child.getLocalName().equalsIgnoreCase("compression")) {
+ for (int k = 0, l = child.getChildNodes().getLength(); k
< l; k++) {
+ Node child2 = child.getChildNodes().item(k);
+ if
(child2.getLocalName().equalsIgnoreCase("lossless")) {
+ Node value =
child2.getAttributes().getNamedItem("value");
+ if (value == null) {
+ // The default is true, according to the DTD
+ lossy = false;
+ } else {
+ lossy
= !Boolean.parseBoolean(value.getNodeValue());
+ }
+ break metadata;
+ }
+ }
+ }
+ }
+ }
} catch (Exception e) {
// Hope we have another reader that can handle the image
continue readers;
@@ -739,8 +777,11 @@
}
ImageRect toReturn = new ImageRect(imageName, image);
-
- if (toReturn.height > IMAGE_MAX_SIZE || toReturn.width >
IMAGE_MAX_SIZE) {
+ toReturn.setLossy(lossy);
+
+ // Don't composite the image if it's lossy or if it is too big
+ if (lossy || toReturn.height > IMAGE_MAX_SIZE
+ || toReturn.width > IMAGE_MAX_SIZE) {
throw new UnsuitableForStripException(toReturn);
}
=======================================
---
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java
Wed Oct 28 07:24:14 2009
+++
/releases/2.0/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java
Tue Jan 19 07:13:03 2010
@@ -140,7 +140,8 @@
+ urlExpressions[1] + " : " + urlExpressions[0] + ",");
}
sw.println(rect.getLeft() + ", " + rect.getTop() + ", " +
rect.getWidth()
- + ", " + rect.getHeight() + ", " + rect.isAnimated());
+ + ", " + rect.getHeight() + ", " + rect.isAnimated() + ", "
+ + rect.isLossy());
sw.outdent();
sw.print(")");
@@ -245,8 +246,8 @@
URL normalContents;
rect = e.getImageRect();
- if (rect.isAnimated()) {
- // Can't re-encode animated images, so we emit it as-is
+ if (rect.isAnimated() || rect.isLossy()) {
+ // Can't re-encode animated or lossy images, so we emit it as-is
normalContents = resource;
} else {
normalContents = reencodeToTempFile(logger, rect);
=======================================
---
/releases/2.0/user/test/com/google/gwt/resources/client/ImageResourceTest.java
Wed Nov 25 10:09:37 2009
+++
/releases/2.0/user/test/com/google/gwt/resources/client/ImageResourceTest.java
Tue Jan 19 07:13:03 2010
@@ -23,6 +23,7 @@
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
+import com.google.gwt.resources.client.impl.ImageResourcePrototype;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
@@ -34,6 +35,13 @@
@Source("animated.gif")
ImageResource animated();
+ /**
+ * This image shouldn't be re-encoded as a PNG or it will dramatically
+ * increase in size, although it's still small enough to be encoded as
a
+ * data URL as-is.
+ */
+ ImageResource complexLossy();
+
@Source("16x16.png")
ImageResource i16x16();
@@ -83,6 +91,7 @@
ImageResource a = r.animated();
assertTrue(a.isAnimated());
+ assertFalse(((ImageResourcePrototype) a).isLossy());
assertEquals(16, a.getWidth());
assertEquals(16, a.getHeight());
assertEquals(0, a.getLeft());
@@ -137,12 +146,10 @@
ImageResource lossy = r.largeLossy();
ImageResource lossless = r.largeLossless();
- // The large, lossless image should not be bundled
- if (!i64.getURL().startsWith("data:")) {
- assertFalse(i64.getURL().equals(lossless.getURL()));
- }
+ assertFalse(((ImageResourcePrototype) lossless).isLossy());
// Make sure that the large, lossy image isn't bundled with the rest
+ assertTrue(((ImageResourcePrototype) lossy).isLossy());
assertTrue(!i64.getURL().equals(lossy.getURL()));
assertEquals(16, r.i16x16Vertical().getWidth());
=======================================
--- /releases/2.0/user/test/com/google/gwt/resources/client/largeLossy.jpg
Wed Mar 11 15:01:48 2009
+++ /releases/2.0/user/test/com/google/gwt/resources/client/largeLossy.jpg
Tue Jan 19 07:13:03 2010
Binary file, no diff available.
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors