/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.resources.rg;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;

import org.w3c.dom.Node;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
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.Locale;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.stream.MemoryCacheImageInputStream;

/**
 * Accumulates state for the bundled image.
 */
class ImageBundleBuilder {
  /**
   * Abstracts the process of arranging a number of images into a composite
   * image.
   */
  interface Arranger {
    /**
     * Determine the total area required to store a composite image.
     */
    Size arrangeImages(Collection<ImageRect> rects);
  }

  /**
   * Arranges the images to try to decrease the overall area of the resulting
   * bundle. This uses a strategy that is basically Next-Fit Decreasing Height
   * Decreasing Width (NFDHDW). The rectangles to be packed are sorted in
   * decreasing order by height. The tallest rectangle is placed at the far
   * left. We attempt to stack the remaining rectangles on top of one another to
   * construct as many columns as necessary. After finishing each column, we
   * also attempt to do some horizontal packing to fill up the space left due to
   * widths of rectangles differing in the column.
   */
  static class BestFitArranger implements Arranger {
    private static final Comparator<ImageRect> decreasingHeightComparator = new Comparator<ImageRect>() {
      public int compare(ImageRect a, ImageRect b) {
        final int c = b.getHeight() - a.getHeight();
        // If we encounter equal heights, use the name to keep things
        // deterministic.
        return (c != 0) ? c : b.getName().compareTo(a.getName());
      }
    };

    private static final Comparator<ImageRect> decreasingWidthComparator = new Comparator<ImageRect>() {
      public int compare(ImageRect a, ImageRect b) {
        final int c = b.getWidth() - a.getWidth();
        // If we encounter equal heights, use the name to keep things
        // deterministic.
        return (c != 0) ? c : b.getName().compareTo(a.getName());
      }
    };

    public Size arrangeImages(Collection<ImageRect> rects) {
      if (rects.size() == 0) {
        return new Size(0, 0);
      }

      // Create a list of ImageRects ordered by decreasing height used for
      // constructing columns.
      final ArrayList<ImageRect> rectsOrderedByHeight = new ArrayList<ImageRect>(
          rects);
      Collections.sort(rectsOrderedByHeight, decreasingHeightComparator);

      // Create a list of ImageRects ordered by decreasing width used for
      // packing
      // individual columns.
      final ArrayList<ImageRect> rectsOrderedByWidth = new ArrayList<ImageRect>(
          rects);
      Collections.sort(rectsOrderedByWidth, decreasingWidthComparator);

      // Place the first, tallest image as the first column.
      final ImageRect first = rectsOrderedByHeight.get(0);
      first.setPosition(0, 0);

      // Setup state for laying things cumulatively.
      int curX = first.getWidth();
      final int colH = first.getHeight();

      for (int i = 1, n = rectsOrderedByHeight.size(); i < n; i++) {
        // If this ImageRect has been positioned already, move on.
        if (rectsOrderedByHeight.get(i).hasBeenPositioned()) {
          continue;
        }

        int colW = 0;
        int curY = 0;

        final ArrayList<ImageRect> rectsInColumn = new ArrayList<ImageRect>();
        for (int j = i; j < n; j++) {
          final ImageRect current = rectsOrderedByHeight.get(j);
          // Look for rects that have not been positioned with a small enough
          // height to go in this column.
          if (!current.hasBeenPositioned()
              && (curY + current.getHeight()) <= colH) {

            // Set the horizontal position here, the top field will be set in
            // arrangeColumn after we've collected a full set of ImageRects.
            current.setPosition(curX, 0);
            colW = Math.max(colW, current.getWidth());
            curY += current.getHeight();

            // Keep the ImageRects in this column in decreasing order by width.
            final int pos = Collections.binarySearch(rectsInColumn, current,
                decreasingWidthComparator);
            assert pos < 0;
            rectsInColumn.add(-1 - pos, current);
          }
        }

        // Having selected a set of ImageRects that fill out this column
        // vertical,
        // now we'll scan the remaining ImageRects to try to fit some in the
        // horizontal gaps.
        if (!rectsInColumn.isEmpty()) {
          arrangeColumn(rectsInColumn, rectsOrderedByWidth);
        }

        // We're done with that column, so move the horizontal accumulator by
        // the
        // width of the column we just finished.
        curX += colW;
      }

      return new Size(curX, colH);
    }

    /**
     * Companion method to {@link #arrangeImages()}. This method does a best
     * effort horizontal packing of a column after it was packed vertically.
     * This is the Decreasing Width part of Next-Fit Decreasing Height
     * Decreasing Width. The basic strategy is to sort the remaining rectangles
     * by decreasing width and try to fit them to the left of each of the
     * rectangles we've already picked for this column.
     *
     * @param rectsInColumn the ImageRects that were already selected for this
     *          column
     * @param remainingRectsOrderedByWidth the sub list of ImageRects that may
     *          not have been positioned yet
     */
    private void arrangeColumn(List<ImageRect> rectsInColumn,
        List<ImageRect> remainingRectsOrderedByWidth) {
      final ImageRect first = rectsInColumn.get(0);

      final int columnWidth = first.getWidth();
      int curY = first.getHeight();

      // Skip this first ImageRect because it is guaranteed to consume the full
      // width of the column.
      for (int i = 1, m = rectsInColumn.size(); i < m; i++) {
        final ImageRect r = rectsInColumn.get(i);
        // The ImageRect was previously positioned horizontally, now set the top
        // field.
        r.setPosition(r.getLeft(), curY);
        int curX = r.getWidth();

        // Search for ImageRects that are shorter than the left most ImageRect
        // and
        // narrow enough to fit in the column.
        for (int j = 0, n = remainingRectsOrderedByWidth.size(); j < n; j++) {
          final ImageRect current = remainingRectsOrderedByWidth.get(j);
          if (!current.hasBeenPositioned()
              && (curX + current.getWidth()) <= columnWidth
              && (current.getHeight() <= r.getHeight())) {
            current.setPosition(r.getLeft() + curX, r.getTop());
            curX += current.getWidth();
          }
        }

        // Update the vertical accumulator so we'll know where to place the next
        // ImageRect.
        curY += r.getHeight();
      }
    }
  }

  /**
   * Performs a simple horizontal arrangement of rectangles. Images will be
   * tiled vertically to fill to fill the full height of the image.
   */
  static class HorizontalArranger implements Arranger {
    public Size arrangeImages(Collection<ImageRect> rects) {
      int height = 1;
      int width = 0;

      for (ImageRect rect : rects) {
        rect.setPosition(width, 0);
        width += rect.getWidth();
        height = lcm(height, rect.getHeight());
      }

      List<ImageRect> toAdd = new ArrayList<ImageRect>();
      for (ImageRect rect : rects) {
        int y = rect.getHeight();
        while (y < height) {
          ImageRect newRect = new ImageRect(rect);
          newRect.setPosition(rect.getLeft(), y);
          y += rect.getHeight();
          toAdd.add(newRect);
        }
      }
      rects.addAll(toAdd);

      return new Size(width, height);
    }
  }

  /**
   * Does not rearrange the rectangles, but simply computes the size of the
   * canvas needed to hold the images in their current positions.
   */
  static class IdentityArranger implements Arranger {
    public Size arrangeImages(Collection<ImageRect> rects) {
      int height = 0;
      int width = 0;

      for (ImageRect rect : rects) {
        height = Math.max(height, rect.getTop() + rect.getHeight());
        width = Math.max(width, rect.getLeft() + rect.getWidth());
      }

      return new Size(width, height);
    }
  }

  /**
   * The rectangle at which the original image is placed into the composite
   * image.
   */
  static class ImageRect {

    private boolean hasBeenPositioned, lossy;
    private int height, width;
    private final int intrinsicHeight, intrinsicWidth;
    private final BufferedImage[] images;
    private int left, top;
    private final String name;
    private final AffineTransform transform = new AffineTransform();

    /**
     * Copy constructor.
     */
    public ImageRect(ImageRect other) {
      this.name = other.getName();
      this.height = other.height;
      this.width = other.width;
      this.images = other.getImages();
      this.left = other.getLeft();
      this.top = other.getTop();
      this.intrinsicHeight = other.intrinsicHeight;
      this.intrinsicWidth = other.intrinsicWidth;
      setTransform(other.getTransform());
    }

    public ImageRect(String name, BufferedImage... images) {
      this.name = name;
      this.images = images;
      this.intrinsicWidth = images[0].getWidth();
      this.intrinsicHeight = images[0].getHeight();
      this.height = this.width = -1;
    }

    public int getHeight() {
      return height > 0 ? height : intrinsicHeight;
    }

    public BufferedImage getImage() {
      return images[0];
    }

    public BufferedImage[] getImages() {
      return images;
    }

    public int getLeft() {
      return left;
    }

    public String getName() {
      return name;
    }

    public int getTop() {
      return top;
    }

    public AffineTransform getTransform() {
      return new AffineTransform(transform);
    }

    public int getWidth() {
      return width > 0 ? width : intrinsicWidth;
    }

    public boolean hasBeenPositioned() {
      return hasBeenPositioned;
    }

    public boolean isAnimated() {
      return images.length > 1;
    }

    public boolean isLossy() {
      return lossy;
    }

    public void setHeight(int height) {
      this.height = height;
      if (width <= 0) {
        width = (int) Math.round((double) height / intrinsicHeight
            * intrinsicWidth);
      }
    }

    public void setLossy(boolean lossy) {
      this.lossy = lossy;
    }

    public void setPosition(int left, int top) {
      hasBeenPositioned = true;
      this.left = left;
      this.top = top;
    }

    public void setTransform(AffineTransform transform) {
      this.transform.setTransform(transform);
    }

    public void setWidth(int width) {
      this.width = width;
      if (height <= 0) {
        height = (int) Math.round((double) width / intrinsicWidth
            * intrinsicHeight);
      }
    }

    public AffineTransform transform() {
      AffineTransform toReturn = new AffineTransform();

      // Translate
      toReturn.translate(left, top);

      // Scale
      assert !(height > 0 ^ width > 0);
      if (height > 0) {
        toReturn.scale((double) height / intrinsicHeight, (double) width
            / intrinsicWidth);
      }

      // Use the base concatenation
      toReturn.concatenate(transform);

      assert checkTransform(toReturn);
      return toReturn;
    }

    private boolean checkTransform(AffineTransform tx) {
      double[] in = {0, 0, intrinsicWidth, intrinsicHeight};
      double[] out = {0, 0, 0, 0};

      tx.transform(in, 0, out, 0, 2);

      // Sanity check on bounds
      assert out[0] >= 0;
      assert out[1] >= 0;
      assert out[2] >= 0;
      assert out[3] >= 0;

      // Check scaling
      assert getWidth() == Math.round(Math.abs(out[0] - out[2])) : "Width "
          + getWidth() + " != " + Math.round(Math.abs(out[0] - out[2]));
      assert getHeight() == Math.round(Math.abs(out[1] - out[3])) : "Height "
          + getHeight() + "!=" + Math.round(Math.abs(out[1] - out[3]));

      return true;
    }
  }

  /**
   * Used to return the size of the resulting image from the method
   * {@link ImageBundleBuilder#arrangeImages()}.
   */
  static class Size {
    private final int width, height;

    Size(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }

  /**
   * Performs a simple vertical arrangement of rectangles. Images will be tiled
   * horizontally to fill the full width of the image.
   */
  static class VerticalArranger implements Arranger {
    public Size arrangeImages(Collection<ImageRect> rects) {
      int height = 0;
      int width = 1;

      for (ImageRect rect : rects) {
        rect.setPosition(0, height);
        width = lcm(width, rect.getWidth());
        height += rect.getHeight();
      }

      List<ImageRect> toAdd = new ArrayList<ImageRect>();
      for (ImageRect rect : rects) {
        int x = rect.getWidth();
        while (x < width) {
          ImageRect newRect = new ImageRect(rect);
          newRect.setPosition(x, rect.getTop());
          x += rect.getWidth();
          toAdd.add(newRect);
        }
      }
      rects.addAll(toAdd);

      return new Size(width, height);
    }
  }

  /*
   * Only PNG is supported right now. In the future, we may be able to infer the
   * best output type, and get rid of this constant.
   */
  static final String BUNDLE_FILE_TYPE = "png";
  static final String BUNDLE_MIME_TYPE = "image/png";
  private static final int IMAGE_MAX_SIZE = Integer.getInteger(
      "gwt.imageResource.maxBundleSize", 256);

  public static void main(String[] args) {
    final TreeLogger logger = new PrintWriterTreeLogger(new PrintWriter(
        System.out));
    if (args.length < 2) {
      logger.log(TreeLogger.ERROR, ImageBundleBuilder.class.getSimpleName()
          + " <output file> <input file> ...");
      System.exit(-1);
    }

    ImageBundleBuilder builder = new ImageBundleBuilder();
    boolean fail = false;
    for (int i = 1, j = args.length; i < j; i++) {
      TreeLogger loopLogger = logger.branch(TreeLogger.DEBUG,
          "Processing argument " + args[i]);
      File file = new File(args[i]);

      Exception ex = null;
      try {
        builder.assimilate(loopLogger, args[i], file.toURI().toURL());
      } catch (MalformedURLException e) {
        ex = e;
      } catch (UnableToCompleteException e) {
        ex = e;
      } catch (UnsuitableForStripException e) {
        ex = e;
      }
      if (ex != null) {
        loopLogger.log(TreeLogger.ERROR, "Unable to assimilate image", ex);
        fail = true;
      }
    }

    if (fail) {
      System.exit(-1);
    }

    final String outFile = args[0];
    try {
      BufferedImage bundledImage = builder.drawBundledImage(new BestFitArranger());
      byte[] bytes = createImageBytes(logger, bundledImage);

      FileOutputStream out = new FileOutputStream(outFile);
      out.write(bytes);
      out.close();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Unable to write output file", e);
      System.exit(-2);
    } catch (UnableToCompleteException e) {
      logger.log(TreeLogger.ERROR, "Unable to draw output image", e);
      System.exit(-2);
    }

    System.exit(0);
  }

  public static byte[] toPng(TreeLogger logger, ImageRect rect)
      throws UnableToCompleteException {
    // Create the bundled image.
    BufferedImage bundledImage = new BufferedImage(rect.getWidth(),
        rect.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);

    SpeedTracerLogger.Event createGraphicsEvent =
      SpeedTracerLogger.start(CompilerEventType.GRAPHICS_INIT,
          "java.awt.headless", System.getProperty("java.awt.headless"));
    Graphics2D g2d = bundledImage.createGraphics();
    createGraphicsEvent.end();

    setBetterRenderingQuality(g2d);

    g2d.drawImage(rect.getImage(), rect.transform(), null);
    g2d.dispose();

    byte[] imageBytes = createImageBytes(logger, bundledImage);
    return imageBytes;
  }

  /**
   * Write the bundled image into a byte array, so that we can compute its
   * strong name.
   */
  private static byte[] createImageBytes(TreeLogger logger,
      BufferedImage bundledImage) throws UnableToCompleteException {
    byte[] imageBytes;

    try {
      ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
      boolean writerAvailable = ImageIO.write(bundledImage, BUNDLE_FILE_TYPE,
          byteOutputStream);
      if (!writerAvailable) {
        logger.log(TreeLogger.ERROR, "No " + BUNDLE_FILE_TYPE
            + " writer available");
        throw new UnableToCompleteException();
      }
      imageBytes = byteOutputStream.toByteArray();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR,
          "An error occurred while trying to write the image bundle.", e);
      throw new UnableToCompleteException();
    }
    return imageBytes;
  }

  /**
   * Compute the greatest common denominator of two numbers.
   */
  private static int gcd(int a, int b) {
    while (b != 0) {
      int t = b;
      b = a % b;
      a = t;
    }
    return a;
  }

  /**
   * Compute the least common multiple of two numbers. This is used by
   * {@link HorizontalArranger} and {@link VerticalArranger} to determine how
   * large the composite image should be to allow every image to line up when
   * repeated.
   */
  private static int lcm(int a, int b) {
    return b / gcd(a, b) * a;
  }

  private static void setBetterRenderingQuality(Graphics2D g2d) {
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
        RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
  }

  private final Map<String, ImageRect> imageNameToImageRectMap = new HashMap<String, ImageRect>();

  public ImageBundleBuilder() {
  }

  /**
   * Copy constructor.
   */
  public ImageBundleBuilder(ImageBundleBuilder other) {
    for (Map.Entry<String, ImageRect> entry : other.imageNameToImageRectMap.entrySet()) {
      imageNameToImageRectMap.put(entry.getKey(), new ImageRect(
          entry.getValue()));
    }
  }

  /**
   * Assimilates the image associated with a particular image method into the
   * master composite. If the method names an image that has already been
   * assimilated, the existing image rectangle is reused.
   *
   * @param logger a hierarchical logger which logs to the hosted console
   * @param imageName the name of an image that can be found on the classpath
   * @param resource the URL from which the image data wil be loaded
   * @throws UnableToCompleteException if the image with name
   *           <code>imageName</code> cannot be added to the master composite
   *           image
   */
  public ImageRect assimilate(TreeLogger logger, String imageName, URL resource)
      throws UnableToCompleteException, UnsuitableForStripException {

    /*
     * Decide whether or not we need to add to the composite image. Either way,
     * we associated it with the rectangle of the specified image as it exists
     * within the composite image. Note that the coordinates of the rectangle
     * aren't computed until the composite is written.
     */
    ImageRect rect = getMapping(imageName);

    if (rect == null) {
      // Assimilate the image into the composite.
      rect = addImage(logger, imageName, resource);

      imageNameToImageRectMap.put(imageName, rect);
    }
    return rect;
  }

  public int getImageCount() {
    return imageNameToImageRectMap.size();
  }

  public ImageRect getMapping(String imageName) {
    return imageNameToImageRectMap.get(imageName);
  }

  /**
   * Remove an image from the builder.
   */
  public ImageRect removeMapping(String imageName) {
    return imageNameToImageRectMap.remove(imageName);
  }

  /**
   * Render the composited image into an array of bytes.
   */
  public byte[] render(TreeLogger logger, Arranger arranger)
      throws UnableToCompleteException {
    if (imageNameToImageRectMap.isEmpty()) {
      return null;
    }

    // Create the bundled image from all of the constituent images.
    BufferedImage bundledImage = drawBundledImage(arranger);

    byte[] imageBytes = createImageBytes(logger, bundledImage);

    return imageBytes;
  }

  private ImageRect addImage(TreeLogger logger, String imageName, URL imageUrl)
      throws UnableToCompleteException, UnsuitableForStripException {

    logger = logger.branch(TreeLogger.TRACE,
        "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 (InputStream is = imageUrl.openStream();
         MemoryCacheImageInputStream imageInputStream = new MemoryCacheImageInputStream(is)) {
      /*
       * 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.getImageReaders(imageInputStream);
      readers : while (it.hasNext()) {
        ImageReader reader = it.next();
        reader.setInput(imageInputStream);

        int numImages = reader.getNumImages(true);
        if (numImages == 0) {
          // Fall through

        } 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;
          }

        } else {
          // Read all contained images
          BufferedImage[] images = new BufferedImage[numImages];

          try {
            for (int i = 0; i < numImages; i++) {
              images[i] = reader.read(i);
            }
          } catch (Exception e) {
            // Hope we have another reader that can handle the image
            continue readers;
          }

          ImageRect rect = new ImageRect(imageName, images);
          throw new UnsuitableForStripException(rect);
        }
      }
    } catch (IllegalArgumentException iex) {
      if (imageName.toLowerCase(Locale.ROOT).endsWith("png")
          && iex.getMessage() != null
          && iex.getStackTrace()[0].getClassName().equals(
              "javax.imageio.ImageTypeSpecifier$Indexed")) {
        logger.log(TreeLogger.ERROR,
            "Unable to read image. The image may not be in valid PNG format. "
                + "This problem may also be due to a bug in versions of the "
                + "JRE prior to 1.6. See "
                + "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5098176 "
                + "for more information. If this bug is the cause of the "
                + "error, try resaving the image using a different image "
                + "program, or upgrade to a newer JRE.", null);
        throw new UnableToCompleteException();
      } else {
        throw iex;
      }
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Unable to read image resource", e);
      throw new UnableToCompleteException();
    }

    if (image == null) {
      logger.log(TreeLogger.ERROR, "Unrecognized image file format", null);
      throw new UnableToCompleteException();
    }

    ImageRect toReturn = new ImageRect(imageName, image);
    toReturn.setLossy(lossy);

    // Don't composite the image if it's lossy or if it is too big
    if (lossy || toReturn.getHeight() > IMAGE_MAX_SIZE
        || toReturn.getWidth() > IMAGE_MAX_SIZE) {
      throw new UnsuitableForStripException(toReturn);
    }

    return toReturn;
  }

  /**
   * This method creates the bundled image through the composition of the other
   * images.
   *
   * In this particular implementation, we use NFDHDW (see
   * {@link #arrangeImages()}) to get an approximate optimal image packing.
   *
   * The most important aspect of drawing the bundled image is that it be drawn
   * in a deterministic way. The drawing of the image should not rely on
   * implementation details of the Generator system which may be subject to
   * change.
   */
  private BufferedImage drawBundledImage(Arranger arranger) {

    /*
     * There is no need to impose any order here, because arrangeImages will
     * position the ImageRects in a deterministic fashion, even though we might
     * paint them in a non-deterministic order.
     */
    Collection<ImageRect> imageRects = new LinkedList<ImageRect>(
        imageNameToImageRectMap.values());

    // Arrange images and determine the size of the resulting bundle.
    Size size = arranger.arrangeImages(imageRects);

    // Create the bundled image.
    BufferedImage bundledImage = new BufferedImage(size.width, size.height,
        BufferedImage.TYPE_INT_ARGB_PRE);

    SpeedTracerLogger.Event graphicsEvent = SpeedTracerLogger.start(CompilerEventType.GRAPHICS_INIT,
        "java.awt.headless", System.getProperty("java.awt.headless"));
    Graphics2D g2d = bundledImage.createGraphics();

    setBetterRenderingQuality(g2d);

    graphicsEvent.end();

    for (ImageRect imageRect : imageRects) {
      g2d.drawImage(imageRect.getImage(), imageRect.transform(), null);
    }
    g2d.dispose();

    return bundledImage;
  }
}
