001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.tools;
003    
004    import com.kitfox.svg.SVGDiagram;
005    
006    import java.awt.Dimension;
007    import java.awt.Image;
008    import java.awt.image.BufferedImage;
009    import java.util.HashMap;
010    import javax.swing.ImageIcon;
011    
012    /**
013     * Holds data for one particular image.
014     * It can be backed by a svg or raster image.
015     * 
016     * In the first case, 'svg' is not null and in the latter case, 'imgCache' has 
017     * at least one entry for the key DEFAULT_DIMENSION.
018     */
019    class ImageResource {
020        
021        /**
022         * Caches the image data for resized versions of the same image.
023         */
024        private HashMap<Dimension, BufferedImage> imgCache = new HashMap<Dimension, BufferedImage>();
025        private SVGDiagram svg;
026        public static final Dimension DEFAULT_DIMENSION = new Dimension(-1, -1);
027     
028        public ImageResource(BufferedImage img) {
029            CheckParameterUtil.ensureParameterNotNull(img);
030            imgCache.put(DEFAULT_DIMENSION, img);
031        }
032    
033        public ImageResource(SVGDiagram svg) {
034            CheckParameterUtil.ensureParameterNotNull(svg);
035            this.svg = svg;
036        }
037    
038        public ImageIcon getImageIcon() {
039            return getImageIcon(DEFAULT_DIMENSION);
040        }
041    
042        /**
043         * Get an ImageIcon object for the image of this resource
044         * @param   dim The requested dimensions. Use (-1,-1) for the original size
045         *          and (width, -1) to set the width, but otherwise scale the image
046         *          proportionally.
047         */
048        public ImageIcon getImageIcon(Dimension dim) {
049            if (dim.width < -1 || dim.width == 0 || dim.height < -1 || dim.height == 0)
050                throw new IllegalArgumentException();
051            BufferedImage img = imgCache.get(dim);
052            if (img != null) {
053                return new ImageIcon(img);
054            }
055            if (svg != null) {
056                img = ImageProvider.createImageFromSvg(svg, dim);
057                imgCache.put(dim, img);
058                return new ImageIcon(img);
059            } else {
060                BufferedImage base = imgCache.get(DEFAULT_DIMENSION);
061                if (base == null) throw new AssertionError();
062                
063                int width = dim.width;
064                int height = dim.height;
065                ImageIcon icon = new ImageIcon(base);
066                if (width == -1) {
067                    width = icon.getIconWidth() * height / icon.getIconHeight();
068                } else if (height == -1) {
069                    height = icon.getIconHeight() * width / icon.getIconWidth();
070                }
071                Image i = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
072                img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
073                img.getGraphics().drawImage(i, 0, 0, null);
074                imgCache.put(dim, img);
075                return new ImageIcon(img);
076            }
077        }
078    
079        /**
080         * Get image icon with a certain maximum size. The image is scaled down
081         * to fit maximum dimensions. (Keeps aspect ratio)
082         *
083         * @param maxSize The maximum size. One of the dimensions (widht or height) can be -1,
084         * which means it is not bounded.
085         */
086        public ImageIcon getImageIconBounded(Dimension maxSize) {
087            if (maxSize.width < -1 || maxSize.width == 0 || maxSize.height < -1 || maxSize.height == 0)
088                throw new IllegalArgumentException();
089            float realWidth;
090            float realHeight;
091            if (svg != null) {
092                realWidth = svg.getWidth();
093                realHeight = svg.getHeight();
094            } else {
095                BufferedImage base = imgCache.get(DEFAULT_DIMENSION);
096                if (base == null) throw new AssertionError();
097                ImageIcon icon = new ImageIcon(base);
098                realWidth = icon.getIconWidth();
099                realHeight = icon.getIconHeight();
100            }
101            int maxWidth = maxSize.width;
102            int maxHeight = maxSize.height;
103    
104            if (realWidth <= maxWidth) {
105                maxWidth = -1;
106            }
107            if (realHeight <= maxHeight) {
108                maxHeight = -1;
109            }
110    
111            if (maxWidth == -1 && maxHeight == -1)
112                return getImageIcon(DEFAULT_DIMENSION);
113            else if (maxWidth == -1)
114                return getImageIcon(new Dimension(-1, maxHeight));
115            else if (maxHeight == -1)
116                return getImageIcon(new Dimension(maxWidth, -1));
117            else
118                if (realWidth / maxWidth > realHeight / maxHeight)
119                    return getImageIcon(new Dimension(maxWidth, -1));
120                else
121                    return getImageIcon(new Dimension(-1, maxHeight));
122       }
123    }