Revision: 5841
Author: [email protected]
Date: Thu Jul 30 11:19:40 2009
Log: Add support for animated images to ImageResource.
This specifically enables using @sprite with animated .gif files.

Patch by: bobv
Review by: jgw
http://code.google.com/p/google-web-toolkit/source/detail?r=5841

Added:
  /trunk/user/test/com/google/gwt/resources/client/animated.gif
Modified:
  /trunk/user/src/com/google/gwt/resources/client/ImageResource.java
   
/trunk/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
  /trunk/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java
  /trunk/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java
  /trunk/user/test/com/google/gwt/resources/client/ImageResourceTest.java

=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/resources/client/animated.gif       Thu Jul 
 
30 11:19:40 2009
@@ -0,0 +1,69 @@
+GIF89a    ô  ÿÿÿ  ÿððþŠŠþààþFFþzzþ  ÿXXþ$$þ¬¬þ¾¾þ  þœœþ  þ66þhhþ               
                              !ÿ NETSCAPE2.0     !þ Created  
with  
ajaxload.info !ù 
+   ,          w        !å¨ DB ÇA «H
+‰àȬ ³Áa° ¦D‚ æ@ ^¶ AéXø p...@ñ¸"Uƒ‚³Q#      ÎáB \;ŸÍ Ã1ª    oÏ:2$ v @ 
+$|,3  
+
+ ‚_#    
+d €5  3—" s5  e! !ù 
+   ,          v    i...@e9Žda ÉA Œ²ŠÄñÀ  /« `ph$  Ca%@  
 ŒÇépH©    °x½F  ÂuS‰  ƒ x#
+ 
+  Â.¿Ý„†Y fŽ  L _"  
+p
+3BƒW     ˆ]|L 
+\6’{|zš8 7[7! !ù 
+   ,          x    Ù e9Ž D E"  ²Š„ƒÀ2r,«  qPÄ ‡ €   j´Â`ð8   ë Â@  8b H ,  
*Ñâ0 -¦
+ðmFW îä9½LP¤E3+ 
+ (‚ B"
+  f {ˆ*BW_/‰  
+...@_$‰‚~kr 7Ar7! !ù 
+   ,          v   
  Ù4e9Ž„! Hñ"Ë*    ÐQ /@ƒ±ˆ-    4€   ép 4 ŒR+÷¼-  Ÿèµp­ ȧ`ÑP(–6 ƒá   ðU/ü  
          *, „)  (+/]"lO
+/†*Ak‘ “Š K”ŒŠ]A~66 6! !ù 
+   ,          l    i e9Ž " Çñ
+Ë* ‡   ½¾  -Ö80H  ‚±€=N;¡ ÐÊ T„EìÐ ½ ® îq   è¤í±ež êUoK2_WZòÝŒV‰´1jgW 
e...@tuh//w`?
+‰f~#’‰–6”“#! !ù 
+   ,          ~    ¹,e9Ž‚" ƒñ Ä*
+†; pR³% „°#0 ¤š`¡ À 'Ãc™(¤  ”J@@
+
+¿ Áµ   /1Ái 4 ˆÂ`½V­ ‰  Bâ¾V  
+u}„"c   aNi/  ]  )) -   Lel      mi}   
+me[+! !ù 
+   ,          y    I e9ŽÂ" Mó6Ä*¨"7EÍ–„ @G((L&Ô...@z
+§‰ùº   „...@­   w¬Z)  „pl (
+ ‡ Ô­Ž  qõu*    R&c     `  ))(    s _J  ˆ>_\  ' Gm7 Œ$+! !ù 
+   ,          w    I e9Ž *,‹ (Ä*¾(üB5[ 1  ² ¥Z²ÓIah! G—ªex z²ìj0ˆe¿6�...@v| 
U«  ñ4º¶Dm²
+%$ Í›ëp 
+       \  G  x
+} @+ |      =+
+ 1“-   Ea5 l)+! !ù 
+   ,          y    )œä¨ž'AœK©’¯àÚ ,¢¶ý  “‰E\(lƒœ©&;5  à 5 D‰Ä €0è
+³3‚a¬0- ‹  µ-
+ Ñ
+¡À ” ŽÃƒpH4   V         %
+i     
+p[R"|   Œ   ‘#
+™       6 iZwcw*! !ù 
+   ,          y    )œä¨ž,K”*ù¶Ä ‹¨0Ÿ aš;׋а Y8 b`4én¤
+ ¨Bb ‚b»x
+¾ ,±ÁÔ  ¾‘ ±Ë ¾Í äÑ(     Ƚ°
+     %
+>  
+  
+2*    Š   i*   /  : ™+$  v*! !ù 
+   ,          u    )œä¨žl[ª$á
+²J q[£Âq 3™`Q[ø 5  ø:  Š•ð IX!0ÀrAD8  Cv« É  ÜHPfi ¾äi Q”  �...@p  C 
+%D 
+P    Q46   Š 
+ici   Nj0w
+„)#! !ù 
+   ,          y    )œä¨. q¾¨
+,G  ®J  r(¯
+J 8  ‡Cðä* Ї†B´,™ Ž
+ê& <
+
+ Œ´Û  h± W~- ¼‘`Ñ,      ‡–õ¤ ,ì>    ;
+
+8RN<,  
+ <1T  ]  
+˜c ‘—'
+qk$
+@)#! ;         
=======================================
--- /trunk/user/src/com/google/gwt/resources/client/ImageResource.java  Wed  
Mar 11 17:58:41 2009
+++ /trunk/user/src/com/google/gwt/resources/client/ImageResource.java  Thu  
Jul 30 11:19:40 2009
@@ -34,6 +34,14 @@
    @Documented
    @Target(ElementType.METHOD)
    public @interface ImageOptions {
+    /**
+     * If <code>true</code>, the image will be flipped about the y-axis  
when
+     * {...@link com.google.gwt.i18n.client.LocaleInfo#isRTL()} returns
+     * <code>true</code>. This is intended to be used by graphics that are
+     * sensitive to layout direction, such as arrows and disclosure  
indicators.
+     */
+    boolean flipRtl() default false;
+
      /**
       * This option affects the image bundling optimization to allow the  
image to
       * be used with the {...@link CssResource} {...@code @sprite} rule where
@@ -42,14 +50,6 @@
       * @see "CssResource documentation"
       */
      RepeatStyle repeatStyle() default RepeatStyle.None;
-
-    /**
-     * If <code>true</code>, the image will be flipped along the y-axis  
when
-     * {...@link com.google.gwt.i18n.client.LocaleInfo#isRTL()} returns
-     * <code>true</code>. This is intended to be used by graphics that are
-     * sensitive to layout direction, such as arrows and disclosure  
indicators.
-     */
-    boolean flipRtl() default false;
    }

    /**
@@ -103,4 +103,9 @@
     * Returns the width of the image.
     */
    int getWidth();
-}
+
+  /**
+   * Return <code>true</code> if the image contains multiple frames.
+   */
+  boolean isAnimated();
+}
=======================================
---  
/trunk/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
         
Wed Mar 11 17:58:41 2009
+++  
/trunk/user/src/com/google/gwt/resources/client/impl/ImageResourcePrototype.java
         
Thu Jul 30 11:19:40 2009
@@ -23,6 +23,7 @@
   */
  public class ImageResourcePrototype implements ImageResource {

+  private final boolean animated;
    private final String name;
    private final String url;
    private final int left;
@@ -30,14 +31,18 @@
    private final int width;
    private final int height;

+  /**
+   * Only called by generated code.
+   */
    public ImageResourcePrototype(String name, String url, int left, int top,
-      int width, int height) {
+      int width, int height, boolean animated) {
      this.name = name;
      this.left = left;
      this.top = top;
      this.height = height;
      this.width = width;
      this.url = url;
+    this.animated = animated;
    }

    /**
@@ -78,4 +83,8 @@
    public int getWidth() {
      return width;
    }
-}
+
+  public boolean isAnimated() {
+    return animated;
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java Fri  
Mar 27 13:23:50 2009
+++ /trunk/user/src/com/google/gwt/resources/rg/ImageBundleBuilder.java Thu  
Jul 30 11:19:40 2009
@@ -31,11 +31,14 @@
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashMap;
+import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;

  import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.MemoryCacheImageInputStream;

  /**
   * Accumulates state for the bundled image.
@@ -213,6 +216,8 @@

      BufferedImage getImage();

+    BufferedImage[] getImages();
+
      int getLeft();

      String getName();
@@ -287,7 +292,7 @@

      private boolean hasBeenPositioned;
      private final int height, width;
-    private final BufferedImage image;
+    private final BufferedImage[] images;
      private int left, top;
      private final String name;
      private final AffineTransform transform = new AffineTransform();
@@ -299,7 +304,7 @@
        this.name = other.getName();
        this.height = other.getHeight();
        this.width = other.getWidth();
-      this.image = other.getImage();
+      this.images = other.getImages();
        this.left = other.getLeft();
        this.top = other.getTop();
        setTransform(other.getTransform());
@@ -307,17 +312,28 @@

      public ImageRect(String name, BufferedImage image) {
        this.name = name;
-      this.image = image;
+      this.images = new BufferedImage[] {image};
        this.width = image.getWidth();
        this.height = image.getHeight();
      }
+
+    public ImageRect(String name, BufferedImage[] images) {
+      this.name = name;
+      this.images = images;
+      this.width = images[0].getWidth();
+      this.height = images[0].getHeight();
+    }

      public int getHeight() {
        return height;
      }

      public BufferedImage getImage() {
-      return image;
+      return images[0];
+    }
+
+    public BufferedImage[] getImages() {
+      return images;
      }

      public int getLeft() {
@@ -343,6 +359,10 @@
      public boolean hasBeenPositioned() {
        return hasBeenPositioned;
      }
+
+    public boolean isAnimated() {
+      return images.length > 1;
+    }

      public void setPosition(int left, int top) {
        hasBeenPositioned = true;
@@ -603,10 +623,40 @@
      logger = logger.branch(TreeLogger.TRACE,
          "Adding image '" + imageName + "'", null);

-    BufferedImage image;
+    BufferedImage image = null;
      // Load the image
      try {
-      image = ImageIO.read(imageUrl);
+      String path = imageUrl.getPath();
+      String suffix = path.substring(path.lastIndexOf('.') + 1);
+
+      /*
+       * ImageIO uses an SPI pattern API. We don't care about the  
particulars of
+       * the implementation, so just choose the first ImageReader.
+       */
+      Iterator<ImageReader> it = ImageIO.getImageReadersBySuffix(suffix);
+      if (it.hasNext()) {
+        ImageReader reader = it.next();
+
+        reader.setInput(new  
MemoryCacheImageInputStream(imageUrl.openStream()));
+
+        int numImages = reader.getNumImages(true);
+        if (numImages == 0) {
+          // Fall through
+
+        } else if (numImages == 1) {
+          image = reader.read(0);
+
+        } else {
+          // Read all contained images
+          BufferedImage[] images = new BufferedImage[numImages];
+          for (int i = 0; i < numImages; i++) {
+            images[i] = reader.read(i);
+          }
+
+          ImageRect rect = new ImageRect(imageName, images);
+          throw new UnsuitableForStripException(rect);
+        }
+      }
      } catch (IllegalArgumentException iex) {
        if (imageName.toLowerCase().endsWith("png")
            && iex.getMessage() != null
@@ -625,7 +675,7 @@
          throw iex;
        }
      } catch (IOException e) {
-      logger.log(TreeLogger.ERROR, "Unable to read image resource", null);
+      logger.log(TreeLogger.ERROR, "Unable to read image resource", e);
        throw new UnableToCompleteException();
      }

=======================================
--- /trunk/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java     
 
Thu Mar 12 11:16:43 2009
+++ /trunk/user/src/com/google/gwt/resources/rg/ImageResourceGenerator.java     
 
Thu Jul 30 11:19:40 2009
@@ -86,7 +86,7 @@
            + urlExpressions[1] + " : " + urlExpressions[0] + ",");
      }
      sw.println(rect.getLeft() + ", " + rect.getTop() + ", " +  
rect.getWidth()
-        + ", " + rect.getHeight());
+        + ", " + rect.getHeight() + ", " + rect.isAnimated());

      sw.outdent();
      sw.print(")");
@@ -224,9 +224,17 @@
      } catch (UnsuitableForStripException e) {
        // Add the image to the output as a separate resource
        rect = e.getImageRect();
-      byte[] imageBytes = ImageBundleBuilder.toPng(logger, rect);
-      String urlExpression = context.deploy(rect.getName() + ".png",
-          "image/png", imageBytes, false);
+
+      String urlExpression;
+      if (rect.isAnimated()) {
+        // Can't re-encode animated images, so we emit it as-is
+        urlExpression = context.deploy(resource, false);
+      } else {
+        // Re-encode the image as a PNG to strip random header data
+        byte[] imageBytes = ImageBundleBuilder.toPng(logger, rect);
+        urlExpression = context.deploy(rect.getName()  
+ ".png", "image/png",
+            imageBytes, false);
+      }
        urlsByExternalImageRect.put(rect, new String[] {urlExpression,  
null});
      }

=======================================
--- /trunk/user/test/com/google/gwt/resources/client/ImageResourceTest.java     
 
Tue Jun  9 12:10:22 2009
+++ /trunk/user/test/com/google/gwt/resources/client/ImageResourceTest.java     
 
Thu Jul 30 11:19:40 2009
@@ -31,6 +31,9 @@
   */
  public class ImageResourceTest extends GWTTestCase {
    static interface Resources extends ClientBundle {
+    @Source("animated.gif")
+    ImageResource animated();
+
      @Source("16x16.png")
      ImageResource i16x16();

@@ -73,6 +76,21 @@
    public String getModuleName() {
      return "com.google.gwt.resources.Resources";
    }
+
+  public void testAnimated() {
+    Resources r = GWT.create(Resources.class);
+
+    ImageResource a = r.animated();
+
+    assertTrue(a.isAnimated());
+    assertEquals(16, a.getWidth());
+    assertEquals(16, a.getHeight());
+    assertEquals(0, a.getLeft());
+    assertEquals(0, a.getTop());
+
+    // Make sure the animated image is encoded separately
+    assertFalse(a.getURL().equals(r.i16x16().getURL()));
+  }

    public void testDedup() {
      Resources r = GWT.create(Resources.class);

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to