1 16 package com.google.gwt.user.rebind.ui; 17 18 import com.google.gwt.core.ext.GeneratorContext; 19 import com.google.gwt.core.ext.TreeLogger; 20 import com.google.gwt.core.ext.UnableToCompleteException; 21 import com.google.gwt.dev.util.Util; 22 23 import java.awt.Graphics2D ; 24 import java.awt.image.BufferedImage ; 25 import java.io.BufferedInputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.OutputStream ; 29 import java.net.URL ; 30 import java.security.MessageDigest ; 31 import java.security.NoSuchAlgorithmException ; 32 import java.util.ArrayList ; 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Map ; 37 38 import javax.imageio.ImageIO ; 39 40 43 class ImageBundleBuilder { 44 45 49 public static class ImageRect { 50 51 public final int height; 52 public final BufferedImage image; 53 public int left; 54 public final int width; 55 56 public ImageRect(BufferedImage image) { 57 this.image = image; 58 this.width = image.getWidth(); 59 this.height = image.getHeight(); 60 } 61 } 62 63 private final Map imageNameToImageRectMap = new HashMap (); 64 private final MessageDigest md5; 65 private final List orderedImageRects = new ArrayList (); 66 67 public ImageBundleBuilder() { 68 try { 69 md5 = MessageDigest.getInstance("MD5"); 70 } catch (NoSuchAlgorithmException e) { 71 throw new RuntimeException ("Error initializing MD5", e); 72 } 73 } 74 75 85 public void assimilate(TreeLogger logger, String imageName) 86 throws UnableToCompleteException { 87 88 94 ImageRect rect = getMapping(imageName); 95 if (rect == null) { 96 rect = addImage(logger, imageName); 98 99 putMapping(imageName, rect); 102 } 103 } 104 105 public ImageRect getMapping(String imageName) { 106 return (ImageRect) imageNameToImageRectMap.get(imageName); 107 } 108 109 public String writeBundledImage(TreeLogger logger, GeneratorContext context) 110 throws UnableToCompleteException { 111 112 int nextLeft = 0; 115 int maxHeight = 0; 116 for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) { 117 ImageRect imageRect = (ImageRect) iter.next(); 118 imageRect.left = nextLeft; 119 nextLeft += imageRect.width; 120 if (imageRect.height > maxHeight) { 121 maxHeight = imageRect.height; 122 } 123 } 124 125 BufferedImage bundledImage = new BufferedImage (nextLeft, maxHeight, 127 BufferedImage.TYPE_INT_ARGB_PRE); 128 Graphics2D g2d = bundledImage.createGraphics(); 129 130 for (Iterator iter = orderedImageRects.iterator(); iter.hasNext();) { 131 ImageRect imageRect = (ImageRect) iter.next(); 132 g2d.drawImage(imageRect.image, imageRect.left, 0, null); 133 } 134 g2d.dispose(); 135 136 byte[] hash = md5.digest(); 138 char[] strongName = new char[2 * hash.length]; 139 int j = 0; 140 for (int i = 0; i < hash.length; i++) { 141 strongName[j++] = Util.HEX_CHARS[(hash[i] & 0xF0) >> 4]; 142 strongName[j++] = Util.HEX_CHARS[hash[i] & 0x0F]; 143 } 144 145 String bundleFileType = "png"; 148 149 String bundleFileName = new String (strongName) + ".cache." + bundleFileType; 152 153 OutputStream outStream = context.tryCreateResource(logger, bundleFileName); 154 155 if (outStream != null) { 156 try { 157 if (!ImageIO.write(bundledImage, bundleFileType, outStream)) { 159 logger.log(TreeLogger.ERROR, "Unsupported output file type", null); 160 throw new UnableToCompleteException(); 161 } 162 163 context.commitResource(logger, outStream); 165 166 } catch (IOException e) { 167 logger.log(TreeLogger.ERROR, "Failed while writing", e); 168 throw new UnableToCompleteException(); 169 } 170 } else { 171 logger.log( 172 TreeLogger.TRACE, 173 "Generated image bundle file already exists; no need to rewrite it.", 174 null); 175 } 176 177 return bundleFileName; 178 } 179 180 private ImageRect addImage(TreeLogger logger, String imageName) 181 throws UnableToCompleteException { 182 183 logger = logger.branch(TreeLogger.TRACE, 184 "Adding image '" + imageName + "'", null); 185 186 BufferedImage image = null; 188 try { 189 URL imageUrl = getClass().getClassLoader().getResource(imageName); 192 if (imageUrl == null) { 193 logger.log( 198 TreeLogger.ERROR, 199 "Resource not found on classpath (is the name specified as Class.getResource() would expect?)", 200 null); 201 throw new UnableToCompleteException(); 202 } 203 204 InputStream is = imageUrl.openStream(); 206 BufferedInputStream bis = new BufferedInputStream (is); 207 byte imgByte; 208 while ((imgByte = (byte) bis.read()) != -1) { 209 md5.update(imgByte); 210 } 211 is.close(); 212 213 image = ImageIO.read(imageUrl); 216 if (image == null) { 217 logger.log(TreeLogger.ERROR, "Unrecognized image file format", null); 218 throw new UnableToCompleteException(); 219 } 220 221 } catch (IOException e) { 222 logger.log(TreeLogger.ERROR, "Unable to read image resource", null); 223 throw new UnableToCompleteException(); 224 } 225 226 ImageRect imageRect = new ImageRect(image); 227 orderedImageRects.add(imageRect); 228 return imageRect; 229 } 230 231 private void putMapping(String imageName, ImageRect rect) { 232 imageNameToImageRectMap.put(imageName, rect); 233 } 234 235 } 236 | Popular Tags |