Changeset 6172 in josm for trunk


Ignore:
Timestamp:
2013-08-21T18:15:12+02:00 (11 years ago)
Author:
Don-vip
Message:

fix #8849:

  • Used scaled down (16x16 pixels) of large (.svg) images if no size is explicitely defined
  • rendering of emergency=aed with recently added svg
  • optimizations/refactoring in icons rotating/rescaling code
  • fix of various warnings, javadoc
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r6162 r6172  
    66import java.awt.Color;
    77import java.awt.Component;
     8import java.awt.Dimension;
    89import java.awt.Font;
    910import java.awt.FontMetrics;
     
    2930import java.util.Iterator;
    3031import java.util.List;
     32
    3133import javax.swing.AbstractButton;
    3234import javax.swing.FocusManager;
    33 import javax.swing.ImageIcon;
    3435
    3536import org.openstreetmap.josm.Main;
     
    904905
    905906    public void drawRestriction(Image img, Point pVia, double vx, double vx2, double vy, double vy2, double angle, boolean selected) {
    906         /* rotate image with direction last node in from to */
    907         Image rotatedImg = ImageProvider.createRotatedImage(null , img, angle);
    908 
    909         /* scale down image to 16*16 pixels */
    910         Image smallImg = new ImageIcon(rotatedImg.getScaledInstance(16 , 16, Image.SCALE_SMOOTH)).getImage();
     907        // rotate image with direction last node in from to, and scale down image to 16*16 pixels
     908        Image smallImg = ImageProvider.createRotatedImage(img, angle, new Dimension(16, 16));
    911909        int w = smallImg.getWidth(null), h=smallImg.getHeight(null);
    912910        g.drawImage(smallImg, (int)(pVia.x+vx+vx2)-w/2, (int)(pVia.y+vy+vy2)-h/2, nc);
  • trunk/src/org/openstreetmap/josm/gui/dialogs/DialogsPanel.java

    r3530 r6172  
    11// License: GPL. See LICENSE file for details.
    2 
    32package org.openstreetmap.josm.gui.dialogs;
    43
     
    1110import javax.swing.JSplitPane;
    1211
    13 import org.openstreetmap.josm.gui.MultiSplitPane;
    1412import org.openstreetmap.josm.gui.MultiSplitLayout.Divider;
    1513import org.openstreetmap.josm.gui.MultiSplitLayout.Leaf;
    1614import org.openstreetmap.josm.gui.MultiSplitLayout.Node;
    1715import org.openstreetmap.josm.gui.MultiSplitLayout.Split;
    18 
    19 public class DialogsPanel extends JPanel {
     16import org.openstreetmap.josm.gui.MultiSplitPane;
     17import org.openstreetmap.josm.tools.Destroyable;
     18
     19public class DialogsPanel extends JPanel implements Destroyable {
    2020    protected List<ToggleDialog> allDialogs = new ArrayList<ToggleDialog>();
    2121    protected MultiSplitPane mSpltPane = new MultiSplitPane();
     
    292292    }
    293293
     294    @Override
    294295    public void destroy() {
    295296        for (ToggleDialog t : allDialogs) {
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java

    r6170 r6172  
    1313import java.awt.GridBagLayout;
    1414import java.awt.GridLayout;
    15 import java.awt.Image;
    1615import java.awt.Rectangle;
    1716import java.awt.Toolkit;
     
    3332import javax.swing.AbstractAction;
    3433import javax.swing.BorderFactory;
    35 import javax.swing.ImageIcon;
    3634import javax.swing.JButton;
    3735import javax.swing.JCheckBoxMenuItem;
     
    462460
    463461            // scale down the dialog icon
    464             ImageIcon inIcon = ImageProvider.get("dialogs", iconName);
    465             ImageIcon smallIcon = new ImageIcon(inIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
    466             lblTitle = new JLabel("",smallIcon, JLabel.TRAILING);
     462            lblTitle = new JLabel("", new ImageProvider("dialogs", iconName).setWidth(16).get(), JLabel.TRAILING);
    467463            lblTitle.setIconTextGap(8);
    468464
     
    500496            // show the pref button if applicable
    501497            if (preferenceClass != null) {
    502                 inIcon = ImageProvider.get("preference");
    503                 smallIcon = new ImageIcon(inIcon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH));
    504                 JButton pref = new JButton(smallIcon);
     498                JButton pref = new JButton(new ImageProvider("preference").setWidth(16).get());
    505499                pref.setToolTipText(tr("Open preferences for this panel"));
    506500                pref.setBorder(BorderFactory.createEmptyBorder());
  • trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java

    r5812 r6172  
    66import java.awt.BasicStroke;
    77import java.awt.Color;
     8import java.awt.Image;
    89import java.awt.Rectangle;
    910import java.awt.Stroke;
     
    1920import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
    2021import org.openstreetmap.josm.gui.mappaint.StyleCache.StyleList;
     22import org.openstreetmap.josm.tools.ImageProvider;
    2123import org.openstreetmap.josm.tools.Utils;
    2224
     
    2527 */
    2628public class NodeElemStyle extends ElemStyle implements StyleKeys {
    27     public MapImage mapImage;
    28     public Symbol symbol;
     29    public final MapImage mapImage;
     30    public final Symbol symbol;
     31   
     32    private Image enabledNodeIcon;
     33    private Image disabledNodeIcon;
    2934
    3035    public enum SymbolShape { SQUARE, CIRCLE, TRIANGLE, PENTAGON, HEXAGON, HEPTAGON, OCTAGON, NONAGON, DECAGON }
     
    230235    }
    231236
     237    private Image getRealNodeIcon(final Image image) {
     238        final int maxSize = 16;
     239        // Scale down large (.svg) images to 16x16 pixels if no size is explicitely specified
     240        if ((mapImage.width  == -1 && image.getWidth(null) > maxSize)
     241         || (mapImage.height == -1 && image.getHeight(null) > maxSize)) {
     242            return ImageProvider.createBoundedImage(image, maxSize);
     243        } else {
     244            return image;
     245        }
     246    }
     247   
    232248    @Override
    233249    public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings settings, StyledMapRenderer painter, boolean selected, boolean member) {
     
    235251            Node n = (Node) primitive;
    236252            if (mapImage != null && painter.isShowIcons()) {
    237                 painter.drawNodeIcon(n, (painter.isInactiveMode() || n.isDisabled()) ? mapImage.getDisabled() : mapImage.getImage(),
    238                         Utils.color_int2float(mapImage.alpha), selected, member);
     253                final Image nodeIcon;
     254                if (painter.isInactiveMode() || n.isDisabled()) {
     255                    if (disabledNodeIcon == null) {
     256                        disabledNodeIcon = getRealNodeIcon(mapImage.getDisabled());
     257                    }
     258                    nodeIcon = disabledNodeIcon;
     259                } else {
     260                    if (enabledNodeIcon == null) {
     261                        enabledNodeIcon = getRealNodeIcon(mapImage.getImage());
     262                    }
     263                    nodeIcon = enabledNodeIcon;
     264                }
     265                painter.drawNodeIcon(n, nodeIcon, Utils.color_int2float(mapImage.alpha), selected, member);
    239266            } else if (symbol != null) {
    240267                Color fillColor = symbol.fillColor;
  • trunk/src/org/openstreetmap/josm/gui/widgets/TextContextualPopupMenu.java

    r6084 r6172  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.Image;
    76import java.awt.event.ActionEvent;
    87import java.beans.PropertyChangeEvent;
     
    149148            mi.setText(label);
    150149            if (iconName != null && Main.pref.getBoolean("text.popupmenu.useicons", true)) {
    151                 ImageIcon icon = ImageProvider.get(iconName);
     150                ImageIcon icon = new ImageProvider(iconName).setWidth(16).get();
    152151                if (icon != null) {
    153                     mi.setIcon(new ImageIcon(icon.getImage().getScaledInstance(16 , 16, Image.SCALE_SMOOTH)));
     152                    mi.setIcon(icon);
    154153                }
    155154            }
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r6151 r6172  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.Component;
    76import java.awt.Cursor;
    87import java.awt.Dimension;
     
    8382    }
    8483
     84    /**
     85     * Supported image types
     86     */
    8587    public static enum ImageType {
    86         SVG,    // scalable vector graphics
    87         OTHER   // everything else, e.g. png, gif (must be supported by Java)
     88        /** Scalable vector graphics */
     89        SVG,
     90        /** Everything else, e.g. png, gif (must be supported by Java) */
     91        OTHER
    8892    }
    8993
     
    107111     * The icon cache
    108112     */
    109     private static Map<String, ImageResource> cache = new HashMap<String, ImageResource>();
    110 
    111     private final static ExecutorService imageFetcher = Executors.newSingleThreadExecutor();
     113    private static final Map<String, ImageResource> cache = new HashMap<String, ImageResource>();
     114
     115    /**
     116     * Caches the image data for rotated versions of the same image.
     117     */
     118    private static final Map<Image, Map<Long, ImageResource>> rotateCache = new HashMap<Image, Map<Long, ImageResource>>();
     119
     120    private static final ExecutorService imageFetcher = Executors.newSingleThreadExecutor();
    112121
    113122    public interface ImageCallback {
     
    116125
    117126    /**
     127     * Constructs a new {@code ImageProvider} from a filename in a given directory.
    118128     * @param subdir    subdirectory the image lies in
    119129     * @param name      the name of the image. If it does not end with '.png' or '.svg',
     
    125135    }
    126136
     137    /**
     138     * Constructs a new {@code ImageProvider} from a filename.
     139     * @param name      the name of the image. If it does not end with '.png' or '.svg',
     140     *                  both extensions are tried.
     141     */
    127142    public ImageProvider(String name) {
    128143        this.name = name;
     
    131146    /**
    132147     * Directories to look for the image.
     148     * @param dirs The directories to look for.
     149     * @return the current object, for convenience
    133150     */
    134151    public ImageProvider setDirs(Collection<String> dirs) {
     
    141158     * If name starts with <tt>http://</tt> Id is not used for the cache.
    142159     * (A URL is unique anyway.)
     160     * @return the current object, for convenience
    143161     */
    144162    public ImageProvider setId(String id) {
     
    151169     *
    152170     * (optional)
     171     * @return the current object, for convenience
    153172     */
    154173    public ImageProvider setArchive(File archive) {
     
    163182     *
    164183     * (optional)
     184     * @return the current object, for convenience
    165185     */
    166186    public ImageProvider setInArchiveDir(String inArchiveDir) {
     
    175195     * The width part of the dimension can be -1. Then it will only set the height but
    176196     * keep the aspect ratio. (And the other way around.)
     197     * @return the current object, for convenience
    177198     */
    178199    public ImageProvider setSize(Dimension size) {
     
    184205    /**
    185206     * @see #setSize
     207     * @return the current object, for convenience
    186208     */
    187209    public ImageProvider setWidth(int width) {
     
    192214    /**
    193215     * @see #setSize
     216     * @return the current object, for convenience
    194217     */
    195218    public ImageProvider setHeight(int height) {
     
    205228     *
    206229     * 'size' and 'maxSize' are not compatible, you should set only one of them.
     230     * @return the current object, for convenience
    207231     */
    208232    public ImageProvider setMaxSize(Dimension maxSize) {
     
    214238    /**
    215239     * Convenience method, see {@link #setMaxSize(Dimension)}.
     240     * @return the current object, for convenience
    216241     */
    217242    public ImageProvider setMaxSize(int maxSize) {
     
    221246    /**
    222247     * @see #setMaxSize
     248     * @return the current object, for convenience
    223249     */
    224250    public ImageProvider setMaxWidth(int maxWidth) {
     
    229255    /**
    230256     * @see #setMaxSize
     257     * @return the current object, for convenience
    231258     */
    232259    public ImageProvider setMaxHeight(int maxHeight) {
     
    253280     *
    254281     * In combination with setOptional(true);
     282     * @return the current object, for convenience
    255283     */
    256284    public ImageProvider setSuppressWarnings(boolean suppressWarnings) {
     
    261289    /**
    262290     * Add a collection of additional class loaders to search image for.
     291     * @return the current object, for convenience
    263292     */
    264293    public ImageProvider setAdditionalClassLoaders(Collection<ClassLoader> additionalClassLoaders) {
     
    388417                }
    389418            } catch (UnsupportedEncodingException ex) {
    390                 throw new RuntimeException(ex.getMessage(), ex);
    391             } catch (IOException ex) {
    392419                throw new RuntimeException(ex.getMessage(), ex);
    393420            }
     
    482509
    483510    private static ImageResource getIfAvailableHttp(String url, ImageType type) {
     511        MirroredInputStream is = null;
    484512        try {
    485             MirroredInputStream is = new MirroredInputStream(url,
     513            is = new MirroredInputStream(url,
    486514                    new File(Main.pref.getCacheDirectory(), "images").getPath());
    487515            switch (type) {
     
    501529        } catch (IOException e) {
    502530            return null;
     531        } finally {
     532            Utils.close(is);
    503533        }
    504534    }
     
    791821     * Creates a rotated version of the input image.
    792822     *
    793      * @param c The component to get properties useful for painting, e.g. the foreground or
    794      * background color.
    795823     * @param img the image to be rotated.
    796824     * @param rotatedAngle the rotated angle, in degree, clockwise. It could be any double but we
    797      * will mod it with 360 before using it.
     825     * will mod it with 360 before using it. More over for caching performance, it will be rounded to
     826     * an entire value between 0 and 360.
    798827     *
    799828     * @return the image after rotating.
    800      */
    801     public static Image createRotatedImage(Component c, Image img, double rotatedAngle) {
    802         // convert rotatedAngle to a value from 0 to 360
    803         double originalAngle = rotatedAngle % 360;
     829     * @since 6172
     830     */
     831    public static Image createRotatedImage(Image img, double rotatedAngle) {
     832        return createRotatedImage(img, rotatedAngle, ImageResource.DEFAULT_DIMENSION);
     833    }
     834   
     835    /**
     836     * Creates a rotated version of the input image, scaled to the given dimension.
     837     *
     838     * @param img the image to be rotated.
     839     * @param rotatedAngle the rotated angle, in degree, clockwise. It could be any double but we
     840     * will mod it with 360 before using it. More over for caching performance, it will be rounded to
     841     * an entire value between 0 and 360.
     842     * @param dimension The requested dimensions. Use (-1,-1) for the original size
     843     * and (width, -1) to set the width, but otherwise scale the image proportionally.
     844     * @return the image after rotating and scaling.
     845     * @since 6172
     846     */
     847    public static Image createRotatedImage(Image img, double rotatedAngle, Dimension dimension) {
     848        CheckParameterUtil.ensureParameterNotNull(img, "img");
     849       
     850        // convert rotatedAngle to an integer value from 0 to 360
     851        Long originalAngle = Math.round(rotatedAngle % 360);
    804852        if (rotatedAngle != 0 && originalAngle == 0) {
    805             originalAngle = 360.0;
    806         }
    807 
    808         // convert originalAngle to a value from 0 to 90
    809         double angle = originalAngle % 90;
    810         if (originalAngle != 0.0 && angle == 0.0) {
    811             angle = 90.0;
    812         }
    813 
    814         double radian = Math.toRadians(angle);
    815 
    816         new ImageIcon(img); // load completely
    817         int iw = img.getWidth(null);
    818         int ih = img.getHeight(null);
    819         int w;
    820         int h;
    821 
    822         if ((originalAngle >= 0 && originalAngle <= 90) || (originalAngle > 180 && originalAngle <= 270)) {
    823             w = (int) (iw * Math.sin(DEGREE_90 - radian) + ih * Math.sin(radian));
    824             h = (int) (iw * Math.sin(radian) + ih * Math.sin(DEGREE_90 - radian));
    825         } else {
    826             w = (int) (ih * Math.sin(DEGREE_90 - radian) + iw * Math.sin(radian));
    827             h = (int) (ih * Math.sin(radian) + iw * Math.sin(DEGREE_90 - radian));
    828         }
    829         BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    830         Graphics g = image.getGraphics();
    831         Graphics2D g2d = (Graphics2D) g.create();
    832 
    833         // calculate the center of the icon.
    834         int cx = iw / 2;
    835         int cy = ih / 2;
    836 
    837         // move the graphics center point to the center of the icon.
    838         g2d.translate(w / 2, h / 2);
    839 
    840         // rotate the graphics about the center point of the icon
    841         g2d.rotate(Math.toRadians(originalAngle));
    842 
    843         g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    844         g2d.drawImage(img, -cx, -cy, c);
    845 
    846         g2d.dispose();
    847         new ImageIcon(image); // load completely
    848         return image;
     853            originalAngle = 360L;
     854        }
     855       
     856        ImageResource imageResource = null;
     857
     858        synchronized (rotateCache) {
     859            Map<Long, ImageResource> cacheByAngle = rotateCache.get(img);
     860            if (cacheByAngle == null) {
     861                rotateCache.put(img, cacheByAngle = new HashMap<Long, ImageResource>());
     862            }
     863           
     864            imageResource = cacheByAngle.get(originalAngle);
     865           
     866            if (imageResource == null) {
     867                // convert originalAngle to a value from 0 to 90
     868                double angle = originalAngle % 90;
     869                if (originalAngle != 0.0 && angle == 0.0) {
     870                    angle = 90.0;
     871                }
     872       
     873                double radian = Math.toRadians(angle);
     874       
     875                new ImageIcon(img); // load completely
     876                int iw = img.getWidth(null);
     877                int ih = img.getHeight(null);
     878                int w;
     879                int h;
     880       
     881                if ((originalAngle >= 0 && originalAngle <= 90) || (originalAngle > 180 && originalAngle <= 270)) {
     882                    w = (int) (iw * Math.sin(DEGREE_90 - radian) + ih * Math.sin(radian));
     883                    h = (int) (iw * Math.sin(radian) + ih * Math.sin(DEGREE_90 - radian));
     884                } else {
     885                    w = (int) (ih * Math.sin(DEGREE_90 - radian) + iw * Math.sin(radian));
     886                    h = (int) (ih * Math.sin(radian) + iw * Math.sin(DEGREE_90 - radian));
     887                }
     888                Image image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
     889                cacheByAngle.put(originalAngle, imageResource = new ImageResource(image));
     890                Graphics g = image.getGraphics();
     891                Graphics2D g2d = (Graphics2D) g.create();
     892       
     893                // calculate the center of the icon.
     894                int cx = iw / 2;
     895                int cy = ih / 2;
     896       
     897                // move the graphics center point to the center of the icon.
     898                g2d.translate(w / 2, h / 2);
     899       
     900                // rotate the graphics about the center point of the icon
     901                g2d.rotate(Math.toRadians(originalAngle));
     902       
     903                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
     904                g2d.drawImage(img, -cx, -cy, null);
     905       
     906                g2d.dispose();
     907                new ImageIcon(image); // load completely
     908            }
     909            return imageResource.getImageIcon(dimension).getImage();
     910        }
     911    }
     912   
     913    /**
     914     * Creates a scaled down version of the input image to fit maximum dimensions. (Keeps aspect ratio)
     915     *
     916     * @param img the image to be scaled down.
     917     * @param maxSize the maximum size in pixels (both for width and height)
     918     *
     919     * @return the image after scaling.
     920     * @since 6172
     921     */
     922    public static Image createBoundedImage(Image img, int maxSize) {
     923        return new ImageResource(img).getImageIconBounded(new Dimension(maxSize, maxSize)).getImage();
    849924    }
    850925
     
    886961        Graphics2D g = img.createGraphics();
    887962        g.setClip(0, 0, width, height);
    888         if (scaleX != null) {
     963        if (scaleX != null && scaleY != null) {
    889964            g.scale(scaleX, scaleY);
    890965        }
  • trunk/styles/standard/elemstyles.xml

    r6153 r6172  
    18161816        </rule>
    18171817
     1818    <rule>
     1819        <condition k="emergency" v="aed"/>
     1820        <icon annotate="true" src="presets/aed.svg"/>
     1821        <area colour="amenity_light#f7efb7"/>
     1822    </rule>
     1823
    18181824        <rule>
    18191825                <condition k="amenity" v="toilets"/>
Note: See TracChangeset for help on using the changeset viewer.