Ticket #16733: 16733.patch

File 16733.patch, 14.2 KB (added by simon04, 6 years ago)
  • build.xml

    commit 6b04f8fb548874b9139abc4bb08ac675b6a66829
    Author: Simon Legner <Simon.Legner@gmail.com>
    Date:   2020-03-22 14:35:14 +0100
    
        see #16733 - Use radiance-photon for transcoding SVG icons to Java classes
    
    diff --git a/build.xml b/build.xml
    index 465f7df38..e75e4b6b8 100644
    a b Build-Date: ${build.tstamp}  
    11871187        <ivy:retrieve pattern="${lib.dir}/compile/[artifact]-[type].[ext]" conf="compile"/>
    11881188        <ivy:retrieve pattern="${lib.dir}/runtime/[artifact]-[type].[ext]" conf="runtime"/>
    11891189        <ivy:retrieve pattern="${lib.dir}/sources/[artifact]-[type].[ext]" conf="sources"/>
     1190        <ivy:retrieve file="${tools.ivy}" pattern="${lib.dir}/radiance-photon/[artifact]-[type].[ext]" conf="radiance-photon"/>
    11901191        <ivy:retrieve pattern="${lib.dir}/tools/[artifact]-[type].[ext]" conf="javacc,checkstyle" file="${tools.ivy}"/>
    11911192    </target>
     1193    <target name="transform-svg" depends="resolve">
     1194        <ivy:cachepath file="${tools.ivy}" pathid="radiance-photon.classpath" conf="radiance-photon"/>
     1195        <mkdir dir="src/org/openstreetmap/josm/images"/>
     1196        <java classname="org.pushingpixels.photon.api.transcoder.SvgBatchConverter" failonerror="true">
     1197            <classpath refid="radiance-photon.classpath"/>
     1198            <arg value="sourceFolder=resources/images/"/>
     1199            <arg value="maxDepth=10"/>
     1200            <arg value="outputFolder=src/org/openstreetmap/josm/images"/>
     1201            <arg value="outputPackageName=org.openstreetmap.josm.images"/>
     1202            <arg value="outputClassNamePrefix=img_"/>
     1203            <arg value="outputLanguage=java"/>
     1204            <arg value="templateFile=/org/pushingpixels/photon/api/transcoder/java/SvgTranscoderTemplateResizable.templ"/>
     1205        </java>
     1206    </target>
    11921207</project>
  • ivy.xml

    diff --git a/ivy.xml b/ivy.xml
    index 8e76fba07..f3ad56601 100644
    a b  
    2424        <dependency org="org.tukaani" name="xz" rev="1.8" conf="api->default"/>
    2525        <dependency org="com.drewnoakes" name="metadata-extractor" rev="2.13.0" conf="api->default"/>
    2626        <dependency org="ch.poole" name="OpeningHoursParser" rev="0.21.1" conf="api->default"/>
     27        <dependency org="org.pushing-pixels" name="radiance-neon" rev="3.0-SNAPSHOT" conf="api->default"/>
    2728        <!-- sources->sources -->
    2829        <dependency org="javax.json" name="javax.json-api" rev="1.1.4" conf="sources->sources"/>
    2930        <dependency org="org.glassfish" name="javax.json" rev="1.1.4" conf="sources->sources"/>
  • ivysettings.xml

    diff --git a/ivysettings.xml b/ivysettings.xml
    index 3cd393631..e919942b1 100644
    a b  
    22<!-- License: GPL. For details, see LICENSE file. -->
    33<ivysettings>
    44  <settings defaultResolver="chain"/>
     5  <property name="m2-pattern" value="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision](-[classifier]).[ext]" override="false" />
    56  <resolvers>
    67    <chain name="chain">
     8      <filesystem name="local-maven2" m2compatible="true" >
     9        <artifact pattern="${m2-pattern}"/>
     10        <ivy pattern="${m2-pattern}"/>
     11      </filesystem>
    712      <ibiblio name="josm-nexus" m2compatible="true" root="https://josm.openstreetmap.de/nexus/content/repositories/public/" />
    813      <ibiblio name="jcenter" m2compatible="true" root="https://jcenter.bintray.com/" />
    914    </chain>
  • src/org/openstreetmap/josm/tools/ImageProvider.java

    diff --git a/src/org/openstreetmap/josm/tools/ImageProvider.java b/src/org/openstreetmap/josm/tools/ImageProvider.java
    index 89de2b570..15b1f2f44 100644
    a b  
    1515import java.awt.RenderingHints;
    1616import java.awt.Toolkit;
    1717import java.awt.Transparency;
     18import java.awt.geom.Dimension2D;
    1819import java.awt.image.BufferedImage;
    1920import java.awt.image.ColorModel;
    2021import java.awt.image.FilteredImageSource;
     
    8182import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
    8283import org.openstreetmap.josm.io.CachedFile;
    8384import org.openstreetmap.josm.spi.preferences.Config;
     85import org.pushingpixels.neon.api.icon.ResizableIcon;
    8486import org.w3c.dom.Element;
    8587import org.w3c.dom.Node;
    8688import org.w3c.dom.NodeList;
    private ImageResource getIfAvailableImpl() {  
    853855        // for example in loops in map entries (ie freeze when such entry is retrieved)
    854856
    855857        String prefix = isDisabled ? "dis:" : "";
     858
     859        if (Utils.hasExtension(name, "svg")) {
     860            final ImageResource ir = getResizableIcon();
     861            if (ir != null) {
     862                cache.put(prefix + name, ir);
     863                return ir;
     864            }
     865        }
     866
    856867        if (name.startsWith("data:")) {
    857868            String url = name;
    858869            ImageResource ir = cache.get(prefix + url);
    private ImageResource getIfAvailableImpl() {  
    955966        return null;
    956967    }
    957968
     969    private ImageResource getResizableIcon() {
     970        try {
     971            // rewrite foo/bar/baz.svg to org.openstreetmap.josm.images.foo.bar.img_baz (class is prefixed with img_)
     972            final String[] nameParts = name.replaceAll("[ -]", "_").split("/");
     973            nameParts[nameParts.length - 1] = "img_" + nameParts[nameParts.length - 1].replaceFirst(".svg$", "");
     974            final String className = "org.openstreetmap.josm.images." + String.join(".", nameParts);
     975            final Class<?> imageClass = Class.forName(className);
     976            final ResizableIcon.Factory factory = (ResizableIcon.Factory) imageClass.getDeclaredMethod("factory").invoke(null);
     977
     978            Logging.info("ImageProvider: For image {0}, using {1}", name, imageClass);
     979            final ResizableIcon resizableIcon = factory.createNewIcon();
     980            return new ImageResource(resizableIcon);
     981
     982        } catch (Exception ex) {
     983            Logging.warn(ex);
     984        }
     985        return null;
     986    }
     987
    958988    /**
    959989     * Internal implementation of the image request for URL's.
    960990     *
    public static BufferedImage createImageFromSvg(SVGDiagram svg, Dimension dim) {  
    16401670        }
    16411671        final float sourceWidth = svg.getWidth();
    16421672        final float sourceHeight = svg.getHeight();
    1643         final float realWidth;
    1644         final float realHeight;
    1645         if (dim.width >= 0) {
    1646             realWidth = dim.width;
    1647             if (dim.height >= 0) {
    1648                 realHeight = dim.height;
    1649             } else {
    1650                 realHeight = sourceHeight * realWidth / sourceWidth;
    1651             }
    1652         } else if (dim.height >= 0) {
    1653             realHeight = dim.height;
    1654             realWidth = sourceWidth * realHeight / sourceHeight;
    1655         } else {
    1656             realWidth = GuiSizesHelper.getSizeDpiAdjusted(sourceWidth);
    1657             realHeight = GuiSizesHelper.getSizeDpiAdjusted(sourceHeight);
    1658         }
    16591673
    1660         int roundedWidth = Math.round(realWidth);
    1661         int roundedHeight = Math.round(realHeight);
     1674        final Dimension2D realDimension = new ComputedDimension(dim, sourceWidth, sourceHeight);
     1675        int roundedWidth = (int) Math.round(realDimension.getWidth());
     1676        int roundedHeight = (int) Math.round(realDimension.getHeight());
    16621677        if (roundedWidth <= 0 || roundedHeight <= 0 || roundedWidth >= Integer.MAX_VALUE || roundedHeight >= Integer.MAX_VALUE) {
    1663             Logging.error("createImageFromSvg: {0} {1} realWidth={2} realHeight={3}",
    1664                     svg.getXMLBase(), dim, Float.toString(realWidth), Float.toString(realHeight));
     1678            Logging.error("createImageFromSvg: {0} {1} realDimension={2}", svg.getXMLBase(), dim, realDimension);
    16651679            return null;
    16661680        }
    16671681        BufferedImage img = new BufferedImage(roundedWidth, roundedHeight, BufferedImage.TYPE_INT_ARGB);
    16681682        Graphics2D g = img.createGraphics();
    16691683        g.setClip(0, 0, img.getWidth(), img.getHeight());
    1670         g.scale(realWidth / sourceWidth, realHeight / sourceHeight);
     1684        g.scale((float) realDimension.getWidth() / sourceWidth, (float) realDimension.getHeight() / sourceHeight);
    16711685        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    16721686        try {
    16731687            synchronized (getSvgUniverse()) {
    public String toString() {  
    21232137                + (archive != null ? "archive=" + archive + ", " : "")
    21242138                + (inArchiveDir != null && !inArchiveDir.isEmpty() ? "inArchiveDir=" + inArchiveDir : "") + ']').replaceAll(", \\]", "]");
    21252139    }
     2140
     2141    static class ComputedDimension extends Dimension2D {
     2142        private final float realWidth;
     2143        private final float realHeight;
     2144
     2145        ComputedDimension(Dimension dim, float sourceWidth, float sourceHeight) {
     2146            dim = GuiSizesHelper.getDimensionDpiAdjusted(dim);
     2147            if (dim.width >= 0) {
     2148                realWidth = dim.width;
     2149                if (dim.height >= 0) {
     2150                    realHeight = dim.height;
     2151                } else {
     2152                    realHeight = sourceHeight * realWidth / sourceWidth;
     2153                }
     2154            } else if (dim.height >= 0) {
     2155                realHeight = dim.height;
     2156                realWidth = sourceWidth * realHeight / sourceHeight;
     2157            } else {
     2158                realWidth = GuiSizesHelper.getSizeDpiAdjusted(sourceWidth);
     2159                realHeight = GuiSizesHelper.getSizeDpiAdjusted(sourceHeight);
     2160            }
     2161        }
     2162
     2163        @Override
     2164        public double getWidth() {
     2165            return realWidth;
     2166        }
     2167
     2168        @Override
     2169        public double getHeight() {
     2170            return realHeight;
     2171        }
     2172
     2173        @Override
     2174        public void setSize(double width, double height) {
     2175            throw new UnsupportedOperationException();
     2176        }
     2177
     2178        @Override
     2179        public String toString() {
     2180            return "ComputedDimension{realWidth=" + realWidth + ", realHeight=" + realHeight + '}';
     2181        }
     2182    }
    21262183}
  • src/org/openstreetmap/josm/tools/ImageResource.java

    diff --git a/src/org/openstreetmap/josm/tools/ImageResource.java b/src/org/openstreetmap/josm/tools/ImageResource.java
    index 56f5d4f87..62301ddfb 100644
    a b  
    33
    44import java.awt.Dimension;
    55import java.awt.Image;
     6import java.awt.geom.Dimension2D;
    67import java.awt.image.BufferedImage;
    78import java.util.List;
    89import java.util.Map;
     
    1617import javax.swing.UIManager;
    1718
    1819import com.kitfox.svg.SVGDiagram;
     20import org.pushingpixels.neon.api.icon.ResizableIcon;
    1921
    2022/**
    2123 * Holds data for one particular image.
     
    3537     * SVG diagram information in case of SVG vector image.
    3638     */
    3739    private SVGDiagram svg;
     40
     41    private ResizableIcon resizableIcon;
     42    private short resizableIconWidth;
     43    private short resizableIconHeight;
    3844    /**
    3945     * Use this dimension to request original file dimension.
    4046     */
    public ImageResource(SVGDiagram svg) {  
    7076        this.svg = svg;
    7177    }
    7278
     79    public ImageResource(ResizableIcon resizableIcon) {
     80        CheckParameterUtil.ensureParameterNotNull(resizableIcon);
     81        this.resizableIcon = resizableIcon;
     82        this.resizableIconWidth = (short) resizableIcon.getIconWidth();
     83        this.resizableIconHeight = (short) resizableIcon.getIconHeight();
     84    }
     85
    7386    /**
    7487     * Constructs a new {@code ImageResource} from another one and sets overlays.
    7588     * @param res the existing resource
    public ImageResource(SVGDiagram svg) {  
    7891     */
    7992    public ImageResource(ImageResource res, List<ImageOverlay> overlayInfo) {
    8093        this.svg = res.svg;
     94        this.resizableIcon = res.resizableIcon;
     95        this.resizableIconWidth = res.resizableIconWidth;
     96        this.resizableIconHeight = res.resizableIconHeight;
    8197        this.baseImage = res.baseImage;
    8298        this.overlayInfo = overlayInfo;
    8399    }
    public ImageIcon getImageIcon(Dimension dim, boolean multiResolution) {  
    158174                () -> dim + " is invalid");
    159175        BufferedImage img = imgCache.get(dim);
    160176        if (img == null) {
    161             if (svg != null) {
    162                 Dimension realDim = GuiSizesHelper.getDimensionDpiAdjusted(dim);
    163                 img = ImageProvider.createImageFromSvg(svg, realDim);
     177            if (resizableIcon != null) {
     178                final Dimension2D dimension = new ImageProvider.ComputedDimension(dim, resizableIconWidth, resizableIconHeight);
     179                resizableIcon.setDimension(new Dimension((int) dimension.getWidth(), (int) dimension.getHeight()));
     180                img = resizableIcon.toImage();
     181            } else if (svg != null) {
     182                img = ImageProvider.createImageFromSvg(svg, dim);
    164183                if (img == null) {
    165184                    return null;
    166185                }
    public ImageIcon getImageIconBounded(Dimension maxSize, boolean multiResolution)  
    248267        float sourceHeight;
    249268        int maxWidth = maxSize.width;
    250269        int maxHeight = maxSize.height;
    251         if (svg != null) {
     270        if (resizableIcon != null) {
     271            sourceHeight = resizableIconHeight;
     272            sourceWidth = resizableIconWidth;
     273        } else if (svg != null) {
    252274            sourceWidth = svg.getWidth();
    253275            sourceHeight = svg.getHeight();
    254276        } else {
  • tools/ivy.xml

    diff --git a/tools/ivy.xml b/tools/ivy.xml
    index dd4fc3b9b..f3c990041 100644
    a b  
    88        <conf name="proguard" description="Everything needed for running ProGuard"/>
    99        <conf name="pmd" description="Everything needed for running PMD"/>
    1010        <conf name="spotbugs" description="Everything needed for running SpotBugs"/>
     11        <conf name="radiance-photon" description="Everything needed for running radiance-photon"/>
    1112    </configurations>
    1213    <dependencies>
    1314        <!-- javacc->default -->
     
    2627        <!-- spotbugs->default -->
    2728        <dependency org="com.github.spotbugs" name="spotbugs" rev="3.1.12" conf="spotbugs->default"/>
    2829        <dependency org="com.github.spotbugs" name="spotbugs-ant" rev="3.1.12" conf="spotbugs->default"/>
     30        <!-- radiance-photon->default -->
     31        <dependency org="org.pushing-pixels" name="radiance-photon" rev="3.0-SNAPSHOT" conf="radiance-photon->default"/>
     32        <dependency org="org.apache.xmlgraphics" name="batik-all" rev="1.12" conf="radiance-photon->default">
     33            <artifact name="batik-all" type="pom" ext="pom"/>
     34        </dependency>
    2935    </dependencies>
    3036</ivy-module>