From 82777a0074e324a11d8afd83f2dba5bf6f2a98b1 Mon Sep 17 00:00:00 2001 From: Paul Sterl Date: Thu, 16 Jun 2022 17:03:02 +0200 Subject: [PATCH] https://github.com/sterlp/svg2png/issues/11 - added a way to force white background --- .../java/org/sterl/svg2png/CliOptions.java | 5 + src/main/java/org/sterl/svg2png/Svg2Png.java | 3 + .../sterl/svg2png/config/OutputConfig.java | 5 + .../{TestSvg2Png.java => Svg2PngTest.java} | 441 ++++++++++-------- 4 files changed, 249 insertions(+), 205 deletions(-) rename src/test/java/org/sterl/svg2png/{TestSvg2Png.java => Svg2PngTest.java} (82%) diff --git a/src/main/java/org/sterl/svg2png/CliOptions.java b/src/main/java/org/sterl/svg2png/CliOptions.java index a094d81..d4c4b2f 100644 --- a/src/main/java/org/sterl/svg2png/CliOptions.java +++ b/src/main/java/org/sterl/svg2png/CliOptions.java @@ -22,6 +22,8 @@ public enum CliOptions { CONFIG("c", null, true, "JSON Config file for the file output."), ALLOW_EXTERNAL("e", "allow-external", false, "Allow external entities to be loaded by the SVG."), + FORCE_TRANCPARENT_WHITE(null, "transparent-white", false, "This is a trick so that viewers which do not support the alpha channel will see a white background (and not a black one)."), + ANDROID(null, "android", false, "Android Icon 48dp mdpi 48x48 -> xxxhdpi 192x192."), ANDROID_LAUNCH(null, "android-launch", false, "Android Launcher Icon config mdpi 48x48 -> xxxhdpi 192x192."), ANDROID_ICON(null, "android-icon", false, "Android Icon (Action Bar, Dialog etc.) config mdpi 36x36 -> xxxhdpi 128x128."), @@ -111,6 +113,9 @@ public static OutputConfig parse(CommandLine cmd) { if (cmd.hasOption(ALLOW_EXTERNAL.longName)) { result.setAllowExternalResource(true); } + if (cmd.hasOption(FORCE_TRANCPARENT_WHITE.longName)) { + result.setForceTransparentWhite(true); + } result.setInputFile(getValue(cmd, FILE)); result.setInputDirectory(getValue(cmd, FOLDER)); result.setOutputName(getValue(cmd, NAME)); diff --git a/src/main/java/org/sterl/svg2png/Svg2Png.java b/src/main/java/org/sterl/svg2png/Svg2Png.java index 0e37273..d321f45 100644 --- a/src/main/java/org/sterl/svg2png/Svg2Png.java +++ b/src/main/java/org/sterl/svg2png/Svg2Png.java @@ -51,6 +51,9 @@ private static List convertFile(File input, OutputConfig cfg) throws IOExc // Disable XXE t.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, cfg.isAllowExternalResource()); + // https://github.com/sterlp/svg2png/issues/11 + t.addTranscodingHint(PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE, cfg.isForceTransparentWhite()); + final List generated = new ArrayList<>(); final String inputPath = input.getParent(); diff --git a/src/main/java/org/sterl/svg2png/config/OutputConfig.java b/src/main/java/org/sterl/svg2png/config/OutputConfig.java index ad24714..bc4fafd 100644 --- a/src/main/java/org/sterl/svg2png/config/OutputConfig.java +++ b/src/main/java/org/sterl/svg2png/config/OutputConfig.java @@ -16,7 +16,12 @@ public class OutputConfig { private String inputFile; private String outputName; private String outputDirectory; + /** + * https://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/transcoder/image/ImageTranscoder.html#KEY_FORCE_TRANSPARENT_WHITE + * PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE + */ private boolean allowExternalResource = false; + private boolean forceTransparentWhite = false; private List files = new ArrayList<>(); diff --git a/src/test/java/org/sterl/svg2png/TestSvg2Png.java b/src/test/java/org/sterl/svg2png/Svg2PngTest.java similarity index 82% rename from src/test/java/org/sterl/svg2png/TestSvg2Png.java rename to src/test/java/org/sterl/svg2png/Svg2PngTest.java index e7f547d..b173dcd 100644 --- a/src/test/java/org/sterl/svg2png/TestSvg2Png.java +++ b/src/test/java/org/sterl/svg2png/Svg2PngTest.java @@ -1,205 +1,236 @@ -package org.sterl.svg2png; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.sterl.svg2png.AssertUtil.assertEndsWith; - -import java.io.File; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sterl.svg2png.config.OutputConfig; - -public class TestSvg2Png { - - File tmpDir; - - @Before - public void before() { - tmpDir = new File("./tmp1"); - tmpDir.mkdirs(); - tmpDir.deleteOnExit(); - } - @After - public void after() throws Exception { - FileUtils.deleteDirectory(tmpDir); - } - - @Test - public void testConversionOfOneFile() throws Exception { - OutputConfig cfg = OutputConfig.fromPath(getClass().getResource("/svgfolder/sample.svg").toURI().toString()); - - List convert = new Svg2Png(cfg).convert(); - System.out.println(convert); - assertEquals(1, convert.size()); - assertTrue(convert.get(0).exists()); - assertTrue(convert.get(0).isFile()); - assertTrue(convert.get(0).getTotalSpace() > 1); - - convert.get(0).delete(); - } - - @Test - public void testFileFormCmd() throws Exception { - List files = Main.run(new String[]{getClass().getResource("/svgfolder/sample.svg").toURI().toString()}); - System.out.println(files); - assertEquals(1, files.size()); - files.get(0).delete(); - } - - @Test - public void testCliSingleFile() throws Exception { - List files = Main.run(new String[]{ "-f", getClass().getResource("/svgfolder/sample.svg").toURI().toString()}); - System.out.println(files); - assertEquals(1, files.size()); - assertEquals("sample.png", files.get(0).getName()); - files.get(0).delete(); - } - - @Test - public void testNameConversionFile() throws Exception { - List files = Main.run(new String[]{ - "-n", "testConversion.png", - "-f", getClass().getResource("/svgfolder/sample.svg").toURI().toString() - }); - System.out.println(files); - assertEquals(1, files.size()); - assertEquals("testConversion.png", files.get(0).getName()); - files.get(0).delete(); - } - - @Test - public void testNameMultipleFilesOutputs() throws Exception { - List files = Main.run(new String[]{ - "--android-launch", - "-n","testConversion.png", - "-f", getClass().getResource("/svgfolder/sample.svg").toURI().toString() - }); - assertEquals(6, files.size()); - for (File file : files) { - assertEquals("testConversion.png", file.getName()); - file.deleteOnExit(); - } - } - - @Test - public void testNameMultipleFilesDefaultName() throws Exception { - List files = Main.run(new String[]{ - "--android-launch", - "-f", getClass().getResource("/svgfolder/sample.svg").toURI().toString() - }); - assertEquals(6, files.size()); - files.forEach((f) -> f.deleteOnExit()); - - for (File file : files) { - assertEquals("sample.png", file.getName()); - } - } - - @Test - public void testConversionDirectory() throws Exception { - OutputConfig cfg = OutputConfig.fromPath(new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent()); - List convert = new Svg2Png(cfg).convert(); - convert.stream().forEach(f -> f.deleteOnExit()); - - assertEquals(2, convert.size()); - assertTrue("sample.png not found", - convert.stream().filter(f -> "sample.png".equals(f.getName())).findFirst().isPresent()); - assertTrue("sample2.png not found", - convert.stream().filter(f -> "sample2.png".equals(f.getName())).findFirst().isPresent()); - - convert.stream().forEach(f -> f.delete()); - } - - @Test - public void testWithConfig() throws Exception { - List files = Main.run(new String[] { - "-f", - getClass().getResource("/svgfolder/sample.svg").toURI().toString(), - "-c", - getClass().getResource("/android.json").toURI().toString(), - "-o", - tmpDir.getAbsolutePath() - }); - assertEquals(5, files.size()); - assertEndsWith(files.get(0).getAbsolutePath(), "/tmp1/drawable-xxxhdpi/sample.png".replace('/', File.separatorChar)); - assertEndsWith(files.get(1).getAbsolutePath(), "/tmp1/drawable-xxhdpi/sample.png".replace('/', File.separatorChar)); - assertEndsWith(files.get(2).getAbsolutePath(), "/tmp1/drawable-xhdpi/sample.png".replace('/', File.separatorChar)); - assertEndsWith(files.get(3).getAbsolutePath(), "/tmp1/drawable-hdpi/sample.png".replace('/', File.separatorChar)); - assertEndsWith(files.get(4).getAbsolutePath(), "/tmp1/drawable-mdpi/sample.png".replace('/', File.separatorChar)); - } - - @Test - public void testInternalConfig() throws Exception { - List files = Main.run(new String[] { - "-d", - new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent(), - "-android-small", - "-o", - tmpDir.getAbsolutePath() - }); - assertEquals(10, files.size()); - } - - @Test - public void testIcon() throws Exception { - List files = Main.run(new String[] { - "-d", - new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent(), - "-android-icon", - "-o", - tmpDir.getAbsolutePath() - }); - assertEquals(10, files.size()); - } - - @Test - public void testConversionOfFileWithExternalResource() throws Exception { - Svg2PngException ex = assertThrows(Svg2PngException.class, () -> - Main.run(new String[] { - "--allow-external", - "-d", - new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), - "-android-icon", - "-o", - tmpDir.getAbsolutePath() - }) - ); - assertTrue(ex.getMessage().contains("http://localhost:8080/svg")); - - ex = assertThrows(Svg2PngException.class, () -> - Main.run(new String[] { - "-e", - "-d", - new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), - "-android-icon", - "-o", - tmpDir.getAbsolutePath() - }) - ); - assertTrue(ex.getMessage().contains("http://localhost:8080/svg")); - - } - - @Test - public void testConversionOfFileWithExternalResourceFails() throws Exception { - Svg2PngException ex = assertThrows(Svg2PngException.class, () -> - Main.run(new String[] { - "-d", - new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), - "-android-icon", - "-o", - tmpDir.getAbsolutePath() - }) - ); - Throwable exception = ex.getCause(); - System.err.println(exception.getMessage()); - assertEquals( - "The security settings do not allow any external resources to be referenced from the document", - exception.getMessage()); - } -} +package org.sterl.svg2png; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.sterl.svg2png.AssertUtil.assertEndsWith; + +import java.io.File; +import java.net.URISyntaxException; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.sterl.svg2png.config.OutputConfig; + +public class Svg2PngTest { + + File tmpDir; + + @Before + public void before() { + tmpDir = new File("./tmp1"); + tmpDir.mkdirs(); + tmpDir.deleteOnExit(); + } + @After + public void after() throws Exception { + FileUtils.deleteDirectory(tmpDir); + } + + @Test + public void testConversionOfOneFile() throws Exception { + OutputConfig cfg = OutputConfig.fromPath(svgPath("sample.svg")); + + List convert = new Svg2Png(cfg).convert(); + System.out.println(convert); + assertEquals(1, convert.size()); + assertTrue(convert.get(0).exists()); + assertTrue(convert.get(0).isFile()); + assertTrue(convert.get(0).getTotalSpace() > 1); + + convert.get(0).delete(); + } + + @Test + public void testFileFormCmd() throws Exception { + List files = Main.run(new String[]{svgPath("sample.svg")}); + System.out.println(files); + assertEquals(1, files.size()); + files.get(0).delete(); + } + + @Test + public void testCliSingleFile() throws Exception { + List files = Main.run(new String[]{ "-f", svgPath("sample.svg")}); + System.out.println(files); + assertEquals(1, files.size()); + assertEquals("sample.png", files.get(0).getName()); + files.get(0).delete(); + } + + @Test + public void testNameConversionFile() throws Exception { + List files = Main.run(new String[]{ + "-n", "testConversion.png", + "-f", svgPath("sample.svg") + }); + System.out.println(files); + assertEquals(1, files.size()); + assertEquals("testConversion.png", files.get(0).getName()); + files.get(0).delete(); + } + + @Test + public void testNameMultipleFilesOutputs() throws Exception { + List files = Main.run(new String[]{ + "--android-launch", + "-n","testConversion.png", + "-f", svgPath("sample.svg") + }); + assertEquals(6, files.size()); + for (File file : files) { + assertEquals("testConversion.png", file.getName()); + file.deleteOnExit(); + } + } + + @Test + public void testNameMultipleFilesDefaultName() throws Exception { + List files = Main.run(new String[]{ + "--android-launch", + "-f", svgPath("sample.svg") + }); + assertEquals(6, files.size()); + files.forEach((f) -> f.deleteOnExit()); + + for (File file : files) { + assertEquals("sample.png", file.getName()); + } + } + + @Test + public void testConversionDirectory() throws Exception { + OutputConfig cfg = OutputConfig.fromPath(new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent()); + List convert = new Svg2Png(cfg).convert(); + convert.stream().forEach(f -> f.deleteOnExit()); + + assertEquals(2, convert.size()); + assertTrue("sample.png not found", + convert.stream().filter(f -> "sample.png".equals(f.getName())).findFirst().isPresent()); + assertTrue("sample2.png not found", + convert.stream().filter(f -> "sample2.png".equals(f.getName())).findFirst().isPresent()); + + convert.stream().forEach(f -> f.delete()); + } + + @Test + public void testWithConfig() throws Exception { + List files = Main.run(new String[] { + "-f", + svgPath("sample.svg"), + "-c", + getClass().getResource("/android.json").toURI().toString(), + "-o", + tmpDir.getAbsolutePath() + }); + assertEquals(5, files.size()); + assertEndsWith(files.get(0).getAbsolutePath(), "/tmp1/drawable-xxxhdpi/sample.png".replace('/', File.separatorChar)); + assertEndsWith(files.get(1).getAbsolutePath(), "/tmp1/drawable-xxhdpi/sample.png".replace('/', File.separatorChar)); + assertEndsWith(files.get(2).getAbsolutePath(), "/tmp1/drawable-xhdpi/sample.png".replace('/', File.separatorChar)); + assertEndsWith(files.get(3).getAbsolutePath(), "/tmp1/drawable-hdpi/sample.png".replace('/', File.separatorChar)); + assertEndsWith(files.get(4).getAbsolutePath(), "/tmp1/drawable-mdpi/sample.png".replace('/', File.separatorChar)); + } + + @Test + public void testInternalConfig() throws Exception { + List files = Main.run(new String[] { + "-d", + new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent(), + "-android-small", + "-o", + tmpDir.getAbsolutePath() + }); + assertEquals(10, files.size()); + } + + @Test + public void testIcon() throws Exception { + List files = Main.run(new String[] { + "-d", + new File(getClass().getResource("/svgfolder/sample.svg").toURI()).getParent(), + "-android-icon", + "-o", + tmpDir.getAbsolutePath() + }); + assertEquals(10, files.size()); + } + + @Test + public void testConversionOfFileWithExternalResource() throws Exception { + Svg2PngException ex = assertThrows(Svg2PngException.class, () -> + Main.run(new String[] { + "--allow-external", + "-d", + new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), + "-android-icon", + "-o", + tmpDir.getAbsolutePath() + }) + ); + assertTrue(ex.getMessage().contains("http://localhost:8080/svg")); + + ex = assertThrows(Svg2PngException.class, () -> + Main.run(new String[] { + "-e", + "-d", + new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), + "-android-icon", + "-o", + tmpDir.getAbsolutePath() + }) + ); + assertTrue(ex.getMessage().contains("http://localhost:8080/svg")); + + } + + @Test + public void testConversionOfFileWithExternalResourceFails() throws Exception { + Svg2PngException ex = assertThrows(Svg2PngException.class, () -> + Main.run(new String[] { + "-d", + new File(getClass().getResource("/svg-with-external-resource.svg").toURI()).getParent(), + "-android-icon", + "-o", + tmpDir.getAbsolutePath() + }) + ); + Throwable exception = ex.getCause(); + System.err.println(exception.getMessage()); + assertEquals( + "The security settings do not allow any external resources to be referenced from the document", + exception.getMessage()); + } + + @Test + public void testForceWhite() throws Exception { + // GIVEN + final File normal = convertFile(new String[]{ + "-n", "normal.png", + "-f", svgPath("sample.svg") + }); + + // WHEN + final File white = convertFile(new String[]{ + "-n", "white.png", + "-f", svgPath("sample.svg"), + "-transparent-white" + }); + + // THEN they should not be equal + assertNotEquals(normal.hashCode(), white.hashCode()); + } + private String svgPath(String file) throws URISyntaxException { + return getClass().getResource("/svgfolder/" + file).toString(); + } + + private static File convertFile(String[] args) throws Svg2PngException, URISyntaxException { + List files = Main.run(args); + for (File file : files) file.deleteOnExit(); + assertEquals(1, files.size()); + return files.get(0); + } +}