From 3c0e660ebf7f4b081f9783f3544ed332e1737a3e Mon Sep 17 00:00:00 2001 From: Paul Sterl Date: Sat, 16 Dec 2023 19:20:05 +0100 Subject: [PATCH] update to jdk 11 (#23) * update to jdk 11 * using java 11 * clean * update versions * fix test-reporter * fix path * adjust path * use install * removed dependency graph * removed cache as it is not working --- .github/workflows/codeql-analysis.yml | 70 +- .github/workflows/deploy.yml | 14 +- .github/workflows/maven.yml | 23 +- .gitignore | 8 +- icon.svg => cli/icon.svg | 0 cli/pom.xml | 166 +++++ .../java/org/sterl/svg2png/CliOptions.java | 381 +++++----- .../main/java/org/sterl/svg2png/Main.java | 216 +++--- {src => cli/src}/main/resources/examples.txt | 0 .../org/sterl/svg2png/AbstractFileTest.java | 0 .../org/sterl/svg2png/CliOptionsTest.java | 78 +- .../org/sterl/svg2png/MainConfigTest.java | 22 +- .../java/org/sterl/svg2png/Svg2PngTest.java | 678 +++++++++--------- .../test/java/org/sterl/svg2png/TestUtil.java | 36 +- .../src}/test/resources/Bug21-config.json | 0 .../resources/background-128x128-0077FF.png | Bin .../src}/test/resources/no-alpha-0077FF.png | Bin .../src}/test/resources/normal-128x128.png | Bin .../resources/svg-with-external-resource.png | 0 .../resources/svg-with-external-resource.svg | 0 .../src}/test/resources/svgfolder/sample.svg | 0 .../src}/test/resources/svgfolder/sample2.svg | 0 core/pom.xml | 92 +++ .../main/java/org/sterl/svg2png/Svg2Png.java | 338 ++++----- .../org/sterl/svg2png/Svg2PngException.java | 44 +- .../org/sterl/svg2png/config/FileOutput.java | 125 ++-- .../sterl/svg2png/config/OutputConfig.java | 156 ++-- .../java/org/sterl/svg2png/util/FileUtil.java | 30 + .../src}/main/resources/android-24dp.json | 0 .../src}/main/resources/android-36dp.json | 0 .../src}/main/resources/android-48dp.json | 0 .../src}/main/resources/android-icon.json | 0 .../src}/main/resources/android-launcher.json | 0 .../src}/main/resources/android-small.json | 0 {src => core/src}/main/resources/android.json | 0 .../src}/main/resources/contents.json | 230 +++--- {src => core/src}/main/resources/ios.json | 160 ++--- .../java/org/sterl/svg2png/AssertUtil.java | 12 + .../svg2png/config/TestFileConfigParsing.java | 50 +- .../sterl/svg2png/config/TestFileOutput.java | 95 ++- core/src/test/resources/svgfolder/sample.svg | 86 +++ pom.xml | 326 ++++----- readme.md | 5 +- .../java/org/sterl/svg2png/util/FileUtil.java | 24 - 44 files changed, 1917 insertions(+), 1548 deletions(-) rename icon.svg => cli/icon.svg (100%) create mode 100644 cli/pom.xml rename {src => cli/src}/main/java/org/sterl/svg2png/CliOptions.java (88%) rename {src => cli/src}/main/java/org/sterl/svg2png/Main.java (97%) rename {src => cli/src}/main/resources/examples.txt (100%) rename {src => cli/src}/test/java/org/sterl/svg2png/AbstractFileTest.java (100%) rename {src => cli/src}/test/java/org/sterl/svg2png/CliOptionsTest.java (97%) rename {src => cli/src}/test/java/org/sterl/svg2png/MainConfigTest.java (81%) rename {src => cli/src}/test/java/org/sterl/svg2png/Svg2PngTest.java (96%) rename {src => cli/src}/test/java/org/sterl/svg2png/TestUtil.java (97%) rename {src => cli/src}/test/resources/Bug21-config.json (100%) rename {src => cli/src}/test/resources/background-128x128-0077FF.png (100%) rename {src => cli/src}/test/resources/no-alpha-0077FF.png (100%) rename {src => cli/src}/test/resources/normal-128x128.png (100%) rename {src => cli/src}/test/resources/svg-with-external-resource.png (100%) rename {src => cli/src}/test/resources/svg-with-external-resource.svg (100%) rename {src => cli/src}/test/resources/svgfolder/sample.svg (100%) rename {src => cli/src}/test/resources/svgfolder/sample2.svg (100%) create mode 100644 core/pom.xml rename {src => core/src}/main/java/org/sterl/svg2png/Svg2Png.java (97%) rename {src => core/src}/main/java/org/sterl/svg2png/Svg2PngException.java (96%) rename {src => core/src}/main/java/org/sterl/svg2png/config/FileOutput.java (93%) rename {src => core/src}/main/java/org/sterl/svg2png/config/OutputConfig.java (96%) create mode 100644 core/src/main/java/org/sterl/svg2png/util/FileUtil.java rename {src => core/src}/main/resources/android-24dp.json (100%) rename {src => core/src}/main/resources/android-36dp.json (100%) rename {src => core/src}/main/resources/android-48dp.json (100%) rename {src => core/src}/main/resources/android-icon.json (100%) rename {src => core/src}/main/resources/android-launcher.json (100%) rename {src => core/src}/main/resources/android-small.json (100%) rename {src => core/src}/main/resources/android.json (100%) rename {src => core/src}/main/resources/contents.json (95%) rename {src => core/src}/main/resources/ios.json (94%) create mode 100644 core/src/test/java/org/sterl/svg2png/AssertUtil.java rename {src => core/src}/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java (97%) rename {src => core/src}/test/java/org/sterl/svg2png/config/TestFileOutput.java (90%) create mode 100644 core/src/test/resources/svgfolder/sample.svg delete mode 100644 src/main/java/org/sterl/svg2png/util/FileUtil.java diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9729542..760533c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,12 +2,12 @@ name: "CodeQL" on: push: - branches: [ master ] + branches: [master] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [master] schedule: - - cron: '43 10 * * 2' + - cron: "43 10 * * 2" jobs: analyze: @@ -21,40 +21,40 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'java' ] + language: ["java"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more: # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b74f662..7b9784a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,22 +2,24 @@ name: deploy tags on: push: - tags: ['v*.*.*'] + tags: ["v*.*.*"] jobs: build: runs-on: ubuntu-latest steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v4 - - - name: Import GPG key + - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.PGP_PASSPHRASE }} - + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: 11 + distribution: "zulu" - name: Build site and deploy maven registry env: GPG_KEYNAME: ${{ secrets.PGP_KEYNAME }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 100a0e0..87d8003 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,9 +4,9 @@ name: Java CI with Maven on: push: - branches: [master] + branches: [master, jdk8-version] pull_request: - branches: [master] + branches: [master, jdk8-version] jobs: build: @@ -15,22 +15,21 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 1.8 + - name: Set up JDK 11 uses: actions/setup-java@v4 with: - java-version: 8 + java-version: 11 distribution: "zulu" - cache: maven - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B install --file pom.xml - name: Report Junit uses: dorny/test-reporter@v1 if: always() with: name: Test results - path: target/surefire-reports/*.xml + path: "**/**/surefire-reports/*.xml" reporter: java-junit fail-on-error: true @@ -43,26 +42,24 @@ jobs: path: "target/pmd.xml" title: PMD Result - - name: Update dependency graph - uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 - deploy: runs-on: ubuntu-latest needs: build if: github.ref == 'refs/heads/master' steps: - uses: actions/checkout@v4 + - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.PGP_PASSPHRASE }} - - name: Set up JDK 1.8 + + - name: Set up JDK 11 uses: actions/setup-java@v4 with: - java-version: 8 + java-version: 11 distribution: "zulu" - cache: maven - name: Build and deploy maven registry env: diff --git a/.gitignore b/.gitignore index fbfcc25..41f9d72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ -/target/ +target/ .settings .classpath .project .factorypath -/tmp1/ -/sample.png -/sample2.png +tmp1/ +sample.png +sample2.png diff --git a/icon.svg b/cli/icon.svg similarity index 100% rename from icon.svg rename to cli/icon.svg diff --git a/cli/pom.xml b/cli/pom.xml new file mode 100644 index 0000000..5e19d87 --- /dev/null +++ b/cli/pom.xml @@ -0,0 +1,166 @@ + + + 4.0.0 + + + org.sterl.svg2png + svg2png-root + 1.3.0-SNAPSHOT + ../pom.xml + + + svg2png-cli + + + + ${project.groupId} + svg2png-core + ${project.version} + + + + commons-cli + commons-cli + + + + org.projectlombok + lombok + provided + + + + com.github.romankh3 + image-comparison + test + + + + org.junit.jupiter + junit-jupiter + test + + + + org.junit.jupiter + junit-jupiter-params + test + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.21.0 + + + true + + true + + + + + check + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 + + + package + + shade + + + false + false + + + + org.sterl.svg2png.Main + ${java.version} + ${java.version} + + + + + + + + + + + org.skife.maven + really-executable-jar-maven-plugin + 2.1.1 + + + + -Xmx1G + + + + svg2png + + + + + + + + + + + + + package + + really-executable-jar + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/sterl/svg2png/CliOptions.java b/cli/src/main/java/org/sterl/svg2png/CliOptions.java similarity index 88% rename from src/main/java/org/sterl/svg2png/CliOptions.java rename to cli/src/main/java/org/sterl/svg2png/CliOptions.java index 6537a9a..a9773db 100644 --- a/src/main/java/org/sterl/svg2png/CliOptions.java +++ b/cli/src/main/java/org/sterl/svg2png/CliOptions.java @@ -1,185 +1,196 @@ -package org.sterl.svg2png; - -import java.io.File; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; -import org.sterl.svg2png.config.OutputConfig; -import org.sterl.svg2png.util.FileUtil; - -import com.fasterxml.jackson.databind.ObjectMapper; - -public enum CliOptions { - FILE("f", "file", true, "Source file to convert."), - FOLDER("d", "in-dir", true, "Source directory with one or more files to convert."), - OUTPUT("o", "out-dir", true, "Output directory where to put the file."), - NAME("n", "name", true, "New name to use for all output files."), - WIDTH("w", "width", true, "Width of the output file."), - HEIGHT("h", "height", true, "Height of the output file."), - CONFIG("c", "config", true, "JSON Config file for the file output."), - ALLOW_EXTERNAL("e", "allow-external", false, "Allow external entities to be loaded by the SVG."), - NO_ALPHA("a", "no-alpha", true, "Saves PNG without alpha channel and with specified background hex triplet. (Needed for iOS assets.)"), - BACKGROUND_COLOR(null, "background-color", true, "Provide a custom background color to use for opaque image formats e.g. 0077FF."), - - FORCE_TRANSPARENT_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."), - ANDROID_SMALL(null, "android-small", false, "Android Small default config from mdpi 24x24 -> xxxhdpi 96x96."), - ANDROID_24dp(null, "android-24dp", false, "Android 24dp icons, with suffix _24dp -- mdpi 24x24 -> xxxhdpi 96x96."), - ANDROID_36dp(null, "android-36dp", false, "Android 36dp icons, with suffix _36dp -- mdpi 36x36 -> xxxhdpi 144x144."), - ANDROID_48dp(null, "android-48dp", false, "Android 48dp icons, with suffix _48dp -- mdpi 48x48 -> xxxhdpi 192x192."), - IOS_ICONS(null, "ios", false, "iOS icons and Contents.json.") - ; - - private final String shortName; - private final String longName; - private final boolean hasArg; - private final String description; - - CliOptions(String shortName, String longName, boolean hasArg, String description) { - this.shortName = shortName; - this.longName = longName; - this.hasArg = hasArg; - this.description = description; - } - - public static void addOptions(Options options) { - for (CliOptions o : CliOptions.values()) { - options.addOption(o.shortName, o.longName, o.hasArg, o.description); - } - } - - private static String getValue(CommandLine cmd, CliOptions option) { - if (option.shortName == null) return cmd.getOptionValue(option.longName); - else return cmd.getOptionValue(option.shortName); - } - - public static OutputConfig parse(CommandLine cmd) { - OutputConfig result = selectPredefinedJsonConfig(cmd); - - if (cmd.hasOption(ALLOW_EXTERNAL.longName)) { - result.setAllowExternalResource(true); - } - if (cmd.hasOption(NO_ALPHA.longName)) { - String bg = getValue(cmd, NO_ALPHA); - validateColor(bg, "--" + NO_ALPHA.longName); - result.setNoAlpha(bg); - } - - result.setInputFile(getValue(cmd, FILE)); - result.setInputDirectory(getValue(cmd, FOLDER)); - result.setOutputName(getValue(cmd, NAME)); - result.setOutputDirectory(getValue(cmd, OUTPUT)); - if (result.getOutputDirectory() == null) { - result.setOutputDirectory(new File(".").getAbsolutePath()); - } - - if (result.getFiles().isEmpty()) result.newOutput(); - - result.applyFileName(getValue(cmd, NAME)); - - applyWidthAndHeigth(cmd, result); - - if (cmd.hasOption(BACKGROUND_COLOR.longName)) { - String color = getValue(cmd, BACKGROUND_COLOR); - validateColor(color, "--" + BACKGROUND_COLOR.longName); - result.applyBackgroundColor(color); - } - - if (cmd.hasOption(FORCE_TRANSPARENT_WHITE.longName)) { - result.enableForceTransparentWhite(); - } - return result; - } - - private static void applyWidthAndHeigth(CommandLine cmd, OutputConfig out) { - int width = -1; - int height = -1; - if (cmd.hasOption(WIDTH.shortName)) { - width = Integer.parseInt(getValue(cmd, WIDTH)); - } - if (cmd.hasOption(HEIGHT.shortName)) { - height = Integer.parseInt(getValue(cmd, HEIGHT)); - } - out.applyOutputSize(width, height); - } - - private static void validateColor(String color, String name) { - if (color == null || color.length() <= 5) - throw new RuntimeException("Background must be specified as hex triplet e.g. " + name + " 2a5c8b"); - - final Pattern pattern = Pattern.compile("[0-9a-f]{6}", Pattern.CASE_INSENSITIVE); - final Matcher matcher = pattern.matcher(color); - if (!matcher.find()) - throw new RuntimeException("Background must be specified as hex triplet e.g. " + name + " 2a5c8b"); - } - - private static OutputConfig selectPredefinedJsonConfig(CommandLine cmd) { - OutputConfig result; - final ObjectMapper m = new ObjectMapper(); - if (cmd.hasOption(CONFIG.shortName)) { - try { - result = m.readValue(FileUtil.newFile(cmd.getOptionValue(CONFIG.shortName)), OutputConfig.class); - } catch (Exception e) { - throw new RuntimeException("Failed to parse config '" + cmd.getOptionValue(CONFIG.shortName) + "'. " + e.getMessage(), e); - } - } else if (cmd.hasOption(ANDROID.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_SMALL.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-small.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_ICON.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-icon.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_LAUNCH.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-launcher.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_24dp.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-24dp.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_36dp.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-36dp.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(ANDROID_48dp.longName)) { - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/android-48dp.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (cmd.hasOption(IOS_ICONS.longName)) { - if (!cmd.hasOption(NAME.shortName)) - throw new RuntimeException("-n name must be specified when --ios is used."); - - try { - result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/ios.json")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - result = new OutputConfig(); - } - return result; - } -} +package org.sterl.svg2png; + +import java.io.File; +import java.io.InputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.sterl.svg2png.config.OutputConfig; +import org.sterl.svg2png.util.FileUtil; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.Getter; + +@Getter +public enum CliOptions { + FILE("f", "file", true, "Source file to convert."), + FOLDER("d", "in-dir", true, "Source directory with one or more files to convert."), + OUTPUT("o", "out-dir", true, "Output directory where to put the file."), + NAME("n", "name", true, "New name to use for all output files."), + WIDTH("w", "width", true, "Width of the output file."), + HEIGHT("h", "height", true, "Height of the output file."), + CONFIG("c", "config", true, "JSON Config file for the file output."), + ALLOW_EXTERNAL("e", "allow-external", false, "Allow external entities to be loaded by the SVG."), + NO_ALPHA("a", "no-alpha", true, "Saves PNG without alpha channel and with specified background hex triplet. (Needed for iOS assets.)"), + BACKGROUND_COLOR(null, "background-color", true, "Provide a custom background color to use for opaque image formats e.g. 0077FF."), + + FORCE_TRANSPARENT_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."), + ANDROID_SMALL(null, "android-small", false, "Android Small default config from mdpi 24x24 -> xxxhdpi 96x96."), + ANDROID_24dp(null, "android-24dp", false, "Android 24dp icons, with suffix _24dp -- mdpi 24x24 -> xxxhdpi 96x96."), + ANDROID_36dp(null, "android-36dp", false, "Android 36dp icons, with suffix _36dp -- mdpi 36x36 -> xxxhdpi 144x144."), + ANDROID_48dp(null, "android-48dp", false, "Android 48dp icons, with suffix _48dp -- mdpi 48x48 -> xxxhdpi 192x192."), + IOS_ICONS(null, "ios", false, "iOS icons and Contents.json.") + ; + + private final String shortName; + private final String longName; + private final boolean hasArg; + private final String description; + + CliOptions(String shortName, String longName, boolean hasArg, String description) { + this.shortName = shortName; + this.longName = longName; + this.hasArg = hasArg; + this.description = description; + } + + public static void addOptions(Options options) { + for (CliOptions o : CliOptions.values()) { + options.addOption(o.shortName, o.longName, o.hasArg, o.description); + } + } + + private static String getValue(CommandLine cmd, CliOptions option) { + if (option.shortName == null) return cmd.getOptionValue(option.longName); + else return cmd.getOptionValue(option.shortName); + } + + public static OutputConfig parse(CommandLine cmd) { + OutputConfig result = selectPredefinedJsonConfig(cmd); + + if (cmd.hasOption(ALLOW_EXTERNAL.longName)) { + result.setAllowExternalResource(true); + } + if (cmd.hasOption(NO_ALPHA.longName)) { + String bg = getValue(cmd, NO_ALPHA); + validateColor(bg, "--" + NO_ALPHA.longName); + result.setNoAlpha(bg); + } + + result.setInputFile(getValue(cmd, FILE)); + result.setInputDirectory(getValue(cmd, FOLDER)); + result.setOutputName(getValue(cmd, NAME)); + result.setOutputDirectory(getValue(cmd, OUTPUT)); + if (result.getOutputDirectory() == null) { + result.setOutputDirectory(new File(".").getAbsolutePath()); + } + + if (result.getFiles().isEmpty()) result.newOutput(); + + result.applyFileName(getValue(cmd, NAME)); + + applyWidthAndHeigth(cmd, result); + + if (cmd.hasOption(BACKGROUND_COLOR.longName)) { + String color = getValue(cmd, BACKGROUND_COLOR); + validateColor(color, "--" + BACKGROUND_COLOR.longName); + result.applyBackgroundColor(color); + } + + if (cmd.hasOption(FORCE_TRANSPARENT_WHITE.longName)) { + result.enableForceTransparentWhite(); + } + return result; + } + + private static void applyWidthAndHeigth(CommandLine cmd, OutputConfig out) { + int width = -1; + int height = -1; + if (cmd.hasOption(WIDTH.shortName)) { + width = Integer.parseInt(getValue(cmd, WIDTH)); + } + if (cmd.hasOption(HEIGHT.shortName)) { + height = Integer.parseInt(getValue(cmd, HEIGHT)); + } + out.applyOutputSize(width, height); + } + + private static void validateColor(String color, String name) { + if (color == null || color.length() <= 5) + throw new RuntimeException("Background must be specified as hex triplet e.g. " + name + " 2a5c8b"); + + final Pattern pattern = Pattern.compile("[0-9a-f]{6}", Pattern.CASE_INSENSITIVE); + final Matcher matcher = pattern.matcher(color); + if (!matcher.find()) + throw new RuntimeException("Background must be specified as hex triplet e.g. " + name + " 2a5c8b"); + } + + private static OutputConfig selectPredefinedJsonConfig(CommandLine cmd) { + OutputConfig result; + final ObjectMapper m = new ObjectMapper(); + if (cmd.hasOption(CONFIG.shortName)) { + try { + try (InputStream r = CliOptions.class.getResourceAsStream(cmd.getOptionValue(CONFIG.shortName))) { + if (r != null) { + result = m.readValue(r, OutputConfig.class); + } else { + result = m.readValue(FileUtil.newFile(cmd.getOptionValue(CONFIG.shortName)), OutputConfig.class); + } + } + } catch (Exception e) { + throw new RuntimeException("Failed to parse config '" + cmd.getOptionValue(CONFIG.shortName) + "'. " + e.getMessage(), e); + } + } else if (cmd.hasOption(ANDROID.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_SMALL.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-small.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_ICON.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-icon.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_LAUNCH.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-launcher.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_24dp.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-24dp.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_36dp.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-36dp.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(ANDROID_48dp.longName)) { + try { + result = m.readerFor(OutputConfig.class).readValue(OutputConfig.class.getResourceAsStream("/android-48dp.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (cmd.hasOption(IOS_ICONS.longName)) { + if (!cmd.hasOption(NAME.shortName)) { + throw new RuntimeException("-n name must be specified when --ios is used."); + } + + try { + result = m.readerFor(OutputConfig.class).readValue(CliOptions.class.getResourceAsStream("/ios.json")); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + result = new OutputConfig(); + } + return result; + } +} diff --git a/src/main/java/org/sterl/svg2png/Main.java b/cli/src/main/java/org/sterl/svg2png/Main.java similarity index 97% rename from src/main/java/org/sterl/svg2png/Main.java rename to cli/src/main/java/org/sterl/svg2png/Main.java index 0a3a181..3b653bf 100644 --- a/src/main/java/org/sterl/svg2png/Main.java +++ b/cli/src/main/java/org/sterl/svg2png/Main.java @@ -1,108 +1,108 @@ -package org.sterl.svg2png; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.List; - -import org.apache.batik.transcoder.TranscoderException; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.sterl.svg2png.config.OutputConfig; -import org.sterl.svg2png.util.FileUtil; - -//https://commons.apache.org/proper/commons-cli/usage.html -public class Main { - - static Options options = new Options(); - static HelpFormatter formatter = new HelpFormatter(); - - static { - CliOptions.addOptions(options); - } - - public static void main(String[] args) throws IOException { - try { - run(args); - } catch (Svg2PngException e) { - printHelp(); - System.err.println("\n\n*** Error: " + e.getMessage() + " ***"); - OutputConfig c = e.getCfg(); - if (c != null) { - if (c.getInputFile() != null) System.err.println("Input File: " + c.getInputFile()); - if (c.getOutputName() != null) System.err.println("Output Name: " + c.getOutputName()); - System.err.println("Output Directory: " + c.getOutputDirectory()); - } - System.err.println("\n\n"); - } - } - - static List run(String[] args) throws Svg2PngException { - OutputConfig cfg = null; - try { - if (null == args || args.length == 0) { - printHelp(); - System.exit(0); - } - - cfg = buildOutputConfig(args); - - return new Svg2Png(cfg).convert(); - - } catch (TranscoderException e) { - final Exception ex = e.getException(); - if (ex.getMessage().contains("do not allow any external resources")) { - System.out.println("SVG tried to load resources by URI, if this is okay use '--allow-external' or '-e' option."); - } - throw new Svg2PngException(ex, cfg); - } catch (Exception e) { - throw new Svg2PngException(e, cfg); - } - } - - static OutputConfig buildOutputConfig(String[] args) throws ParseException { - OutputConfig cfg; - if (args.length == 1) { - cfg = OutputConfig.fromPath(args[0]); - } else { - CommandLine cmd = new DefaultParser().parse(options, args); - cfg = CliOptions.parse(cmd); - } - - // validation - if (!cfg.hasDirectoryOrFile()) { - throw new IllegalArgumentException("Please specify either a directory or a file to convert!"); - } else if (cfg.getInputFile() != null) { - File f = FileUtil.newFile(cfg.getInputFile()); - if (!f.exists()) throw new IllegalArgumentException("File '" + cfg.getInputFile() + "' not found!"); - if (!f.isFile()) throw new IllegalArgumentException(cfg.getInputFile() + " is not a file!"); - } else if (cfg.getInputDirectory() != null) { - File d = FileUtil.newFile(cfg.getInputDirectory()); - if (!d.exists()) throw new IllegalArgumentException("Directory " + cfg.getInputDirectory() + " not found!"); - if (!d.isDirectory()) throw new IllegalArgumentException(cfg.getInputDirectory() + " is not a directory!"); - } - if (cfg.getOutputDirectory() == null && cfg.getOutputName() != null) { - cfg.setOutputDirectory("./"); - } - return cfg; - } - - private static void printHelp() throws IOException { - System.out.println(StringUtils.repeat("=", 80)); - System.out.println(StringUtils.center("SVG to PNG", 80)); - System.out.println(); - formatter.printHelp( "svg2png", options ); - System.out.println(); - System.out.println("Examples:"); - System.out.println("---------"); - System.out.println(IOUtils.toString( - Main.class.getResourceAsStream("/examples.txt"), - StandardCharsets.UTF_8)); - } - -} +package org.sterl.svg2png; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import org.apache.batik.transcoder.TranscoderException; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.sterl.svg2png.config.OutputConfig; +import org.sterl.svg2png.util.FileUtil; + +//https://commons.apache.org/proper/commons-cli/usage.html +public class Main { + + static Options options = new Options(); + static HelpFormatter formatter = new HelpFormatter(); + + static { + CliOptions.addOptions(options); + } + + public static void main(String[] args) throws IOException { + try { + run(args); + } catch (Svg2PngException e) { + printHelp(); + System.err.println("\n\n*** Error: " + e.getMessage() + " ***"); + OutputConfig c = e.getCfg(); + if (c != null) { + if (c.getInputFile() != null) System.err.println("Input File: " + c.getInputFile()); + if (c.getOutputName() != null) System.err.println("Output Name: " + c.getOutputName()); + System.err.println("Output Directory: " + c.getOutputDirectory()); + } + System.err.println("\n\n"); + } + } + + static List run(String[] args) throws Svg2PngException { + OutputConfig cfg = null; + try { + if (null == args || args.length == 0) { + printHelp(); + System.exit(0); + } + + cfg = buildOutputConfig(args); + + return new Svg2Png(cfg).convert(); + + } catch (TranscoderException e) { + final Exception ex = e.getException(); + if (ex.getMessage().contains("do not allow any external resources")) { + System.out.println("SVG tried to load resources by URI, if this is okay use '--allow-external' or '-e' option."); + } + throw new Svg2PngException(ex, cfg); + } catch (Exception e) { + throw new Svg2PngException(e, cfg); + } + } + + static OutputConfig buildOutputConfig(String[] args) throws ParseException { + OutputConfig cfg; + if (args.length == 1) { + cfg = OutputConfig.fromPath(args[0]); + } else { + CommandLine cmd = new DefaultParser().parse(options, args); + cfg = CliOptions.parse(cmd); + } + + // validation + if (!cfg.hasDirectoryOrFile()) { + throw new IllegalArgumentException("Please specify either a directory or a file to convert!"); + } else if (cfg.getInputFile() != null) { + File f = FileUtil.newFile(cfg.getInputFile()); + if (!f.exists()) throw new IllegalArgumentException("File '" + cfg.getInputFile() + "' not found!"); + if (!f.isFile()) throw new IllegalArgumentException(cfg.getInputFile() + " is not a file!"); + } else if (cfg.getInputDirectory() != null) { + File d = FileUtil.newFile(cfg.getInputDirectory()); + if (!d.exists()) throw new IllegalArgumentException("Directory " + cfg.getInputDirectory() + " not found!"); + if (!d.isDirectory()) throw new IllegalArgumentException(cfg.getInputDirectory() + " is not a directory!"); + } + if (cfg.getOutputDirectory() == null && cfg.getOutputName() != null) { + cfg.setOutputDirectory("./"); + } + return cfg; + } + + private static void printHelp() throws IOException { + System.out.println(StringUtils.repeat("=", 80)); + System.out.println(StringUtils.center("SVG to PNG", 80)); + System.out.println(); + formatter.printHelp( "svg2png", options ); + System.out.println(); + System.out.println("Examples:"); + System.out.println("---------"); + System.out.println(IOUtils.toString( + Main.class.getResourceAsStream("/examples.txt"), + StandardCharsets.UTF_8)); + } + +} diff --git a/src/main/resources/examples.txt b/cli/src/main/resources/examples.txt similarity index 100% rename from src/main/resources/examples.txt rename to cli/src/main/resources/examples.txt diff --git a/src/test/java/org/sterl/svg2png/AbstractFileTest.java b/cli/src/test/java/org/sterl/svg2png/AbstractFileTest.java similarity index 100% rename from src/test/java/org/sterl/svg2png/AbstractFileTest.java rename to cli/src/test/java/org/sterl/svg2png/AbstractFileTest.java diff --git a/src/test/java/org/sterl/svg2png/CliOptionsTest.java b/cli/src/test/java/org/sterl/svg2png/CliOptionsTest.java similarity index 97% rename from src/test/java/org/sterl/svg2png/CliOptionsTest.java rename to cli/src/test/java/org/sterl/svg2png/CliOptionsTest.java index b415aae..52b2af4 100644 --- a/src/test/java/org/sterl/svg2png/CliOptionsTest.java +++ b/cli/src/test/java/org/sterl/svg2png/CliOptionsTest.java @@ -1,39 +1,39 @@ -package org.sterl.svg2png; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.File; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.Options; -import org.junit.jupiter.api.Test; -import org.sterl.svg2png.config.FileOutput; -import org.sterl.svg2png.config.OutputConfig; - -public class CliOptionsTest { - - @Test - public void test() throws Exception { - Options options = new Options(); - CliOptions.addOptions(options); - - CommandLine cmd = new DefaultParser().parse(options, new String[]{"--android", "-f", "ic_launcher.svg"}); - OutputConfig cfg = CliOptions.parse(cmd); - - assertNull(cfg.getInputDirectory()); - assertEquals(new File(".").getAbsolutePath(), cfg.getOutputDirectory()); - assertNull(cfg.getOutputName()); - assertEquals(5, cfg.getFiles().size()); - assertEquals("ic_launcher.svg", cfg.getInputFile()); - - for (FileOutput fo : cfg.getFiles()) { - final String outPath = fo.toOutputFile(new File("ic_launcher.svg"), null, null).getAbsolutePath(); - System.out.println(outPath); - assertTrue(!outPath.startsWith("null/")); - assertTrue(outPath.endsWith("/ic_launcher.png".replace('/', File.separatorChar))); - } - } -} +package org.sterl.svg2png; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.junit.jupiter.api.Test; +import org.sterl.svg2png.config.FileOutput; +import org.sterl.svg2png.config.OutputConfig; + +public class CliOptionsTest { + + @Test + public void test() throws Exception { + Options options = new Options(); + CliOptions.addOptions(options); + + CommandLine cmd = new DefaultParser().parse(options, new String[]{"--android", "-f", "ic_launcher.svg"}); + OutputConfig cfg = CliOptions.parse(cmd); + + assertNull(cfg.getInputDirectory()); + assertEquals(new File(".").getAbsolutePath(), cfg.getOutputDirectory()); + assertNull(cfg.getOutputName()); + assertEquals(5, cfg.getFiles().size()); + assertEquals("ic_launcher.svg", cfg.getInputFile()); + + for (FileOutput fo : cfg.getFiles()) { + final String outPath = fo.toOutputFile(new File("ic_launcher.svg"), null, null).getAbsolutePath(); + System.out.println(outPath); + assertTrue(!outPath.startsWith("null/")); + assertTrue(outPath.endsWith("/ic_launcher.png".replace('/', File.separatorChar))); + } + } +} diff --git a/src/test/java/org/sterl/svg2png/MainConfigTest.java b/cli/src/test/java/org/sterl/svg2png/MainConfigTest.java similarity index 81% rename from src/test/java/org/sterl/svg2png/MainConfigTest.java rename to cli/src/test/java/org/sterl/svg2png/MainConfigTest.java index 16a575e..6b0cc49 100644 --- a/src/test/java/org/sterl/svg2png/MainConfigTest.java +++ b/cli/src/test/java/org/sterl/svg2png/MainConfigTest.java @@ -55,7 +55,7 @@ void testWidthAndHightOverrides() throws Exception { @Test void testAndroid() throws Exception { // WHEN - final OutputConfig config = buildOutputConfigForJson("/android.json"); + final OutputConfig config = buildOutputConfigForJson(CliOptions.ANDROID); assertEquals(5, config.getFiles().size()); assertEquals(192, config.getFiles().get(0).getHeight()); assertEquals(192, config.getFiles().get(0).getWidth()); @@ -65,7 +65,7 @@ void testAndroid() throws Exception { @Test void testAndroidSmall() throws Exception { // WHEN - final OutputConfig config = buildOutputConfigForJson("/android-small.json"); + final OutputConfig config = buildOutputConfigForJson(CliOptions.ANDROID_SMALL); assertEquals(5, config.getFiles().size()); assertEquals(96, config.getFiles().get(0).getHeight()); assertEquals(96, config.getFiles().get(0).getWidth()); @@ -75,7 +75,7 @@ void testAndroidSmall() throws Exception { @Test void testAndroidIcon() throws Exception { // WHEN - final OutputConfig config = buildOutputConfigForJson("/android-icon.json"); + final OutputConfig config = buildOutputConfigForJson(CliOptions.ANDROID_ICON); // THEN assertEquals(5, config.getFiles().size()); @@ -87,21 +87,29 @@ void testAndroidIcon() throws Exception { @Test void testIos() throws Exception { // WHEN - final OutputConfig config = buildOutputConfigForJson("/ios.json"); - // THEN + final OutputConfig config = buildOutputConfigForJson(CliOptions.IOS_ICONS); + // THEN assertEquals(15, config.getFiles().size()); assertEquals(20, config.getFiles().get(0).getHeight()); assertEquals(20, config.getFiles().get(0).getWidth()); assertEquals("ffffff", config.getNoAlpha()); assertTrue(config.isContentsJson()); assertNull(config.getFiles().get(0).getDirectory()); + } + private OutputConfig buildOutputConfigForJson(CliOptions option) throws ParseException, URISyntaxException { + return Main.buildOutputConfig(new String[] { + "-f", svgPath("sample.svg"), + "-n", "sample", + "--" + option.getLongName(), + "-o", tmpDir.getAbsolutePath() }); + } private OutputConfig buildOutputConfigForJson(String file) throws ParseException, URISyntaxException { return Main.buildOutputConfig(new String[] { "-f", svgPath("sample.svg"), - "-c", getClass().getResource(file).toURI().toString(), - "-o", "./" }); + "-c", file, + "-o", tmpDir.getAbsolutePath() }); } } diff --git a/src/test/java/org/sterl/svg2png/Svg2PngTest.java b/cli/src/test/java/org/sterl/svg2png/Svg2PngTest.java similarity index 96% rename from src/test/java/org/sterl/svg2png/Svg2PngTest.java rename to cli/src/test/java/org/sterl/svg2png/Svg2PngTest.java index 061a898..2d0a5e0 100644 --- a/src/test/java/org/sterl/svg2png/Svg2PngTest.java +++ b/cli/src/test/java/org/sterl/svg2png/Svg2PngTest.java @@ -1,340 +1,338 @@ -package org.sterl.svg2png; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.sterl.svg2png.TestUtil.assertEndsWith; -import static org.sterl.svg2png.TestUtil.svgPath; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileInputStream; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.Test; -import org.sterl.svg2png.config.OutputConfig; - -import com.github.romankh3.image.comparison.ImageComparison; -import com.github.romankh3.image.comparison.ImageComparisonUtil; -import com.github.romankh3.image.comparison.model.ImageComparisonResult; -import com.github.romankh3.image.comparison.model.ImageComparisonState; - -public class Svg2PngTest extends AbstractFileTest { - - @Test - public void testConversionOfOneFile() throws Exception { - // GIVEN - OutputConfig cfg = OutputConfig.fromPath(svgPath("sample.svg")); - cfg.applyOutputSize(128, 128); - - // WHEN - List convert = new Svg2Png(cfg).convert(); - convert.get(0).deleteOnExit(); - - // THEN - assertEquals(1, convert.size()); - assertTrue(convert.get(0).exists()); - assertTrue(convert.get(0).isFile()); - assertTrue(convert.get(0).getTotalSpace() > 1); - - assertEqualImages("normal-128x128.png", convert.get(0).getAbsolutePath()); - - 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"), - "-o", tmpDir.getAbsolutePath() - }); - 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"), - "-o", tmpDir.getAbsolutePath() - }); - 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"), - "-o", tmpDir.getAbsolutePath() - }); - 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(convert.stream().filter(f -> "sample.png".equals(f.getName())).findFirst().isPresent(), - "sample.png not found"); - assertTrue(convert.stream().filter(f -> "sample2.png".equals(f.getName())).findFirst().isPresent(), - "sample2.png not found"); - - 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() - }) - ); - // THEN - assertTrue(ex.getMessage().contains("This is not allowed for security reasons and that resource will not be loaded"), - "'This is not allowed for security reasons and that resource will not be loaded'\n not found in:\n" + ex.getMessage()); - } - - @Test - public void testForceWhite() throws Exception { - // GIVEN - final File normal = convertFile(new String[]{ - "-n", "normal.png", - "-f", svgPath("sample.svg"), - "-o", tmpDir.getAbsolutePath() - }); - - // WHEN - final File white = convertFile(new String[]{ - "-n", "white.png", - "-f", svgPath("sample.svg"), - "-transparent-white", - "-o", tmpDir.getAbsolutePath() - }); - - // THEN they should not be equal - assertNotEquals(normal.hashCode(), white.hashCode()); - assertTrue(normal.length() < white.length(), "white background file should be bigger"); - } - - @Test - public void testCustomAlphaChannel() throws Exception { - // GIVEN - final File normal = convertFile(new String[]{ - "-n", "normal.png", - "-w", "128", - "-h", "128", - "-f", svgPath("sample.svg"), - "-o", tmpDir.getAbsolutePath() - }); - - // WHEN - final File noAlpha = convertFile(new String[]{ - "-n", "no-alpha.png", - "-w", "128", - "-h", "128", - "-f", svgPath("sample.svg"), - "--no-alpha", "0077ff", - "-o", tmpDir.getAbsolutePath() - }); - - // THEN the file without alpha channel should be smaller - assertNotEquals(normal.hashCode(), noAlpha.hashCode()); - assertTrue(normal.length() > noAlpha.length(), "Removed alpha file should be smaller"); - } - - @Test - public void testIosIcons() throws Exception { - // WHEN - List files = Main.run(new String[] { - "-f", svgPath("sample.svg"), - "--ios", - "-n", "sample-ios", - "-o", tmpDir.getAbsolutePath() - }); - // THEN - assertEquals(16, files.size()); - - // AND - File contentJson = new File(tmpDir.getAbsolutePath() + "/Contents.json"); - assertTrue(contentJson.exists() && contentJson.isFile(), - "Content.json doesn't exists " + contentJson.getAbsolutePath()); - - String contentsJsonString = IOUtils.toString(new FileInputStream(contentJson), StandardCharsets.UTF_8); - assertTrue(contentsJsonString.contains("sample-ios")); - assertFalse(contentsJsonString.contains("?PREFIX?")); - } - - @Test - public void testRequireNameWithIos() throws Exception { - Svg2PngException ex = assertThrows(Svg2PngException.class, () -> - Main.run(new String[] { - "-f", svgPath("sample.svg"), - "--ios", - "-o", tmpDir.getAbsolutePath() - }) - ); - Throwable exception = ex.getCause(); - System.err.println(exception.getMessage()); - assertEquals( - "-n name must be specified when --ios is used.", - exception.getMessage()); - } - - @Test - public void testInvalidNoAlphaBackground() throws Exception { - Svg2PngException ex = assertThrows(Svg2PngException.class, () -> - Main.run(new String[] { - "-f", svgPath("sample.svg"), - "--no-alpha", "zzz", - "-o", tmpDir.getAbsolutePath() - }) - ); - Throwable exception = ex.getCause(); - System.err.println(exception.getMessage()); - assertEquals( - "Background must be specified as hex triplet e.g. --no-alpha 2a5c8b", - exception.getMessage()); - } - - @Test - public void testCustomBackground() throws Exception { - // WHEN - final File subject = convertFile(new String[]{ - "-w", "128", - "-h", "128", - "-f", svgPath("sample.svg"), - "--background-color", "0077ff", - "-o", tmpDir.getAbsolutePath() - }); - - // THEN - assertEqualImages("background-128x128-0077FF.png", subject.getAbsolutePath()); - } - - private static void assertEqualImages(String source, String actual) { - BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources(source); - BufferedImage actualImage = ImageComparisonUtil.readImageFromResources(actual); - - // Create ImageComparison object and compare the images. - ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage).compareImages(); - - // Check the result - assertEquals(ImageComparisonState.MATCH, imageComparisonResult.getImageComparisonState(), - "Expected " + source + " to be " + actual); - } - - 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); - } -} +package org.sterl.svg2png; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.sterl.svg2png.TestUtil.assertEndsWith; +import static org.sterl.svg2png.TestUtil.svgPath; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import org.sterl.svg2png.config.OutputConfig; + +import com.github.romankh3.image.comparison.ImageComparison; +import com.github.romankh3.image.comparison.ImageComparisonUtil; +import com.github.romankh3.image.comparison.model.ImageComparisonResult; +import com.github.romankh3.image.comparison.model.ImageComparisonState; + +public class Svg2PngTest extends AbstractFileTest { + + @Test + public void testConversionOfOneFile() throws Exception { + // GIVEN + OutputConfig cfg = OutputConfig.fromPath(svgPath("sample.svg")); + cfg.applyOutputSize(128, 128); + + // WHEN + List convert = new Svg2Png(cfg).convert(); + convert.get(0).deleteOnExit(); + + // THEN + assertEquals(1, convert.size()); + assertTrue(convert.get(0).exists()); + assertTrue(convert.get(0).isFile()); + assertTrue(convert.get(0).getTotalSpace() > 1); + + assertEqualImages("normal-128x128.png", convert.get(0).getAbsolutePath()); + + convert.get(0).delete(); + } + + @Test + public void testFileFormCmd() throws Exception { + List files = Main.run(new String[]{svgPath("sample.svg")}); + 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"), + "-o", tmpDir.getAbsolutePath() + }); + 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"), + "-o", tmpDir.getAbsolutePath() + }); + 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"), + "-o", tmpDir.getAbsolutePath() + }); + 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(convert.stream().filter(f -> "sample.png".equals(f.getName())).findFirst().isPresent(), + "sample.png not found"); + assertTrue(convert.stream().filter(f -> "sample2.png".equals(f.getName())).findFirst().isPresent(), + "sample2.png not found"); + + convert.stream().forEach(f -> f.delete()); + } + + @Test + public void testWithConfig() throws Exception { + List files = Main.run(new String[] { + "-f", + svgPath("sample.svg"), + "-c", "/android.json", + "-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() + }) + ); + // THEN + assertTrue(ex.getMessage().contains("This is not allowed for security reasons and that resource will not be loaded"), + "'This is not allowed for security reasons and that resource will not be loaded'\n not found in:\n" + ex.getMessage()); + } + + @Test + public void testForceWhite() throws Exception { + // GIVEN + final File normal = convertFile(new String[]{ + "-n", "normal.png", + "-f", svgPath("sample.svg"), + "-o", tmpDir.getAbsolutePath() + }); + + // WHEN + final File white = convertFile(new String[]{ + "-n", "white.png", + "-f", svgPath("sample.svg"), + "-transparent-white", + "-o", tmpDir.getAbsolutePath() + }); + + // THEN they should not be equal + assertNotEquals(normal.hashCode(), white.hashCode()); + assertTrue(normal.length() < white.length(), "white background file should be bigger"); + } + + @Test + public void testCustomAlphaChannel() throws Exception { + // GIVEN + final File normal = convertFile(new String[]{ + "-n", "normal.png", + "-w", "128", + "-h", "128", + "-f", svgPath("sample.svg"), + "-o", tmpDir.getAbsolutePath() + }); + + // WHEN + final File noAlpha = convertFile(new String[]{ + "-n", "no-alpha.png", + "-w", "128", + "-h", "128", + "-f", svgPath("sample.svg"), + "--no-alpha", "0077ff", + "-o", tmpDir.getAbsolutePath() + }); + + // THEN the file without alpha channel should be smaller + assertNotEquals(normal.hashCode(), noAlpha.hashCode()); + assertTrue(normal.length() > noAlpha.length(), "Removed alpha file should be smaller"); + } + + @Test + public void testIosIcons() throws Exception { + // WHEN + List files = Main.run(new String[] { + "-f", svgPath("sample.svg"), + "--ios", + "-n", "sample-ios", + "-o", tmpDir.getAbsolutePath() + }); + // THEN + assertEquals(16, files.size()); + + // AND + File contentJson = new File(tmpDir.getAbsolutePath() + "/Contents.json"); + assertTrue(contentJson.exists() && contentJson.isFile(), + "Content.json doesn't exists " + contentJson.getAbsolutePath()); + + String contentsJsonString = IOUtils.toString(new FileInputStream(contentJson), StandardCharsets.UTF_8); + assertTrue(contentsJsonString.contains("sample-ios")); + assertFalse(contentsJsonString.contains("?PREFIX?")); + } + + @Test + public void testRequireNameWithIos() throws Exception { + Svg2PngException ex = assertThrows(Svg2PngException.class, () -> + Main.run(new String[] { + "-f", svgPath("sample.svg"), + "--ios", + "-o", tmpDir.getAbsolutePath() + }) + ); + Throwable exception = ex.getCause(); + System.err.println(exception.getMessage()); + assertEquals( + "-n name must be specified when --ios is used.", + exception.getMessage()); + } + + @Test + public void testInvalidNoAlphaBackground() throws Exception { + Svg2PngException ex = assertThrows(Svg2PngException.class, () -> + Main.run(new String[] { + "-f", svgPath("sample.svg"), + "--no-alpha", "zzz", + "-o", tmpDir.getAbsolutePath() + }) + ); + Throwable exception = ex.getCause(); + System.err.println(exception.getMessage()); + assertEquals( + "Background must be specified as hex triplet e.g. --no-alpha 2a5c8b", + exception.getMessage()); + } + + @Test + public void testCustomBackground() throws Exception { + // WHEN + final File subject = convertFile(new String[]{ + "-w", "128", + "-h", "128", + "-f", svgPath("sample.svg"), + "--background-color", "0077ff", + "-o", tmpDir.getAbsolutePath() + }); + + // THEN + assertEqualImages("background-128x128-0077FF.png", subject.getAbsolutePath()); + } + + private static void assertEqualImages(String source, String actual) { + BufferedImage expectedImage = ImageComparisonUtil.readImageFromResources(source); + BufferedImage actualImage = ImageComparisonUtil.readImageFromResources(actual); + + // Create ImageComparison object and compare the images. + ImageComparisonResult imageComparisonResult = new ImageComparison(expectedImage, actualImage).compareImages(); + + // Check the result + assertEquals(ImageComparisonState.MATCH, imageComparisonResult.getImageComparisonState(), + "Expected " + source + " to be " + actual); + } + + 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); + } +} diff --git a/src/test/java/org/sterl/svg2png/TestUtil.java b/cli/src/test/java/org/sterl/svg2png/TestUtil.java similarity index 97% rename from src/test/java/org/sterl/svg2png/TestUtil.java rename to cli/src/test/java/org/sterl/svg2png/TestUtil.java index 5065f06..b9b2f18 100644 --- a/src/test/java/org/sterl/svg2png/TestUtil.java +++ b/cli/src/test/java/org/sterl/svg2png/TestUtil.java @@ -1,18 +1,18 @@ -package org.sterl.svg2png; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.URISyntaxException; - -public final class TestUtil { - public final static void assertEndsWith(String absolutePath, String value) { - assertNotNull("Expected end with: " + value, absolutePath); - assertTrue(absolutePath.equals(value) || absolutePath.endsWith(value), - absolutePath + " doesn't end with: " + value); - } - - public final static String svgPath(String file) throws URISyntaxException { - return TestUtil.class.getResource("/svgfolder/" + file).toString(); - } -} +package org.sterl.svg2png; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URISyntaxException; + +public final class TestUtil { + public final static void assertEndsWith(String absolutePath, String value) { + assertNotNull("Expected end with: " + value, absolutePath); + assertTrue(absolutePath.equals(value) || absolutePath.endsWith(value), + absolutePath + " doesn't end with: " + value); + } + + public final static String svgPath(String file) throws URISyntaxException { + return TestUtil.class.getResource("/svgfolder/" + file).toString(); + } +} diff --git a/src/test/resources/Bug21-config.json b/cli/src/test/resources/Bug21-config.json similarity index 100% rename from src/test/resources/Bug21-config.json rename to cli/src/test/resources/Bug21-config.json diff --git a/src/test/resources/background-128x128-0077FF.png b/cli/src/test/resources/background-128x128-0077FF.png similarity index 100% rename from src/test/resources/background-128x128-0077FF.png rename to cli/src/test/resources/background-128x128-0077FF.png diff --git a/src/test/resources/no-alpha-0077FF.png b/cli/src/test/resources/no-alpha-0077FF.png similarity index 100% rename from src/test/resources/no-alpha-0077FF.png rename to cli/src/test/resources/no-alpha-0077FF.png diff --git a/src/test/resources/normal-128x128.png b/cli/src/test/resources/normal-128x128.png similarity index 100% rename from src/test/resources/normal-128x128.png rename to cli/src/test/resources/normal-128x128.png diff --git a/src/test/resources/svg-with-external-resource.png b/cli/src/test/resources/svg-with-external-resource.png similarity index 100% rename from src/test/resources/svg-with-external-resource.png rename to cli/src/test/resources/svg-with-external-resource.png diff --git a/src/test/resources/svg-with-external-resource.svg b/cli/src/test/resources/svg-with-external-resource.svg similarity index 100% rename from src/test/resources/svg-with-external-resource.svg rename to cli/src/test/resources/svg-with-external-resource.svg diff --git a/src/test/resources/svgfolder/sample.svg b/cli/src/test/resources/svgfolder/sample.svg similarity index 100% rename from src/test/resources/svgfolder/sample.svg rename to cli/src/test/resources/svgfolder/sample.svg diff --git a/src/test/resources/svgfolder/sample2.svg b/cli/src/test/resources/svgfolder/sample2.svg similarity index 100% rename from src/test/resources/svgfolder/sample2.svg rename to cli/src/test/resources/svgfolder/sample2.svg diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..0a7edd0 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,92 @@ + + + 4.0.0 + + + org.sterl.svg2png + svg2png-root + 1.3.0-SNAPSHOT + ../pom.xml + + + svg2png-core + jar + + + + + org.apache.commons + commons-lang3 + + + + org.apache.xmlgraphics + batik-svggen + + + org.apache.xmlgraphics + batik-transcoder + + + org.apache.xmlgraphics + batik-codec + + + org.apache.xmlgraphics + xmlgraphics-commons + + + + com.fasterxml.jackson.core + jackson-databind + + + org.projectlombok + lombok + provided + + + com.github.romankh3 + image-comparison + test + + + + org.junit.jupiter + junit-jupiter + test + + + + org.junit.jupiter + junit-jupiter-params + test + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + \ No newline at end of file diff --git a/src/main/java/org/sterl/svg2png/Svg2Png.java b/core/src/main/java/org/sterl/svg2png/Svg2Png.java similarity index 97% rename from src/main/java/org/sterl/svg2png/Svg2Png.java rename to core/src/main/java/org/sterl/svg2png/Svg2Png.java index 258796d..d319649 100644 --- a/src/main/java/org/sterl/svg2png/Svg2Png.java +++ b/core/src/main/java/org/sterl/svg2png/Svg2Png.java @@ -1,169 +1,169 @@ -package org.sterl.svg2png; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Scanner; - -import javax.imageio.ImageIO; - -import org.apache.batik.transcoder.SVGAbstractTranscoder; -import org.apache.batik.transcoder.TranscoderException; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.TranscodingHints; -import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.batik.transcoder.image.PNGTranscoder; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.sterl.svg2png.config.FileOutput; -import org.sterl.svg2png.config.OutputConfig; -import org.sterl.svg2png.util.FileUtil; - -public class Svg2Png { - - private final OutputConfig outCfg; - - public Svg2Png(OutputConfig outCfg) { - super(); - this.outCfg = outCfg; - } - - public List convert() throws IOException, TranscoderException { - List generated; - if (outCfg.getInputFile() != null) { - File input = FileUtil.newFile(outCfg.getInputFile()); - generated = convertFile(input, outCfg); - } else { - File dir = FileUtil.newFile(outCfg.getInputDirectory()); - Collection listFiles = FileUtils.listFiles(dir, new String[]{"svg"}, true); - generated = new ArrayList<>(); - for (File file : listFiles) { - generated.addAll(convertFile(file, outCfg)); - } - } - - return generated; - } - - private static List convertFile(File input, OutputConfig cfg) throws IOException, TranscoderException, FileNotFoundException { - final TranscoderInput ti = new TranscoderInput(input.toURI().toString()); - final PNGTranscoder t = new PNGTranscoder(); - - // Disable XXE - t.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, cfg.isAllowExternalResource()); - - - final List generated = new ArrayList<>(); - final String inputPath = input.getParent(); - final StringBuilder info = new StringBuilder(); - - for (FileOutput out : cfg.getFiles()) { - info.setLength(0); - info.append(StringUtils.rightPad(input.getName(), 12)); - - // https://github.com/sterlp/svg2png/issues/11 - t.addTranscodingHint(ImageTranscoder.KEY_FORCE_TRANSPARENT_WHITE, out.isForceTransparentWhite()); - if (out.getWidth() > 0) { - setSizeHint(SVGAbstractTranscoder.KEY_WIDTH, out.getWidth(), t, info); - } - if (out.getHeight() > 0) { - setSizeHint(SVGAbstractTranscoder.KEY_HEIGHT, out.getHeight(), t, info); - } - if (out.hasBackgroundColor()) { - t.addTranscodingHint(PNGTranscoder.KEY_BACKGROUND_COLOR, Color.decode("#" + out.getBackgroundColor())); - } - - final File outputFile = out.toOutputFile(input, cfg.getOutputDirectory(), cfg.getOutputName()); - FileUtil.recreateNewFile(outputFile); - - try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) { - t.transcode(ti, new TranscoderOutput(outStream)); - - if (cfg.getNoAlpha() == null) { - IOUtils.write(outStream.toByteArray(), new FileOutputStream(outputFile)); - } else { - replaceAlphaBackground(outStream.toByteArray(), outputFile, Color.decode("#" + cfg.getNoAlpha())); - } - - generated.add(outputFile); - String outF = outputFile.getCanonicalPath(); - if (inputPath != null && inputPath.length() > 0) { - outF = outF.replace(inputPath, ""); - } - info.append("\t").append(outF); - } - - System.out.println(info.toString()); - } - - if (cfg.isContentsJson()) { - final File contents = generateIOSContentJson(cfg); - generated.add(contents); - System.out.println("Generated iOS " + contents.getCanonicalPath()); - } - - return generated; - } - - private static void setSizeHint(TranscodingHints.Key hint, int size, final PNGTranscoder t, final StringBuilder info) { - if (size > 0) { - t.addTranscodingHint(hint, Float.valueOf(size)); - info.append(StringUtils.rightPad((SVGAbstractTranscoder.KEY_WIDTH == hint ? " w" : " h") + size, 6)); - } else t.removeTranscodingHint(hint); - } - - private static File generateIOSContentJson(OutputConfig cfg) throws IOException, FileNotFoundException { - String contentsJson; - - try (InputStream stream = Svg2Png.class.getResourceAsStream("/contents.json")) { - assert stream != null; - try (Scanner s = new Scanner(stream).useDelimiter("\\A")) { - contentsJson = s.hasNext() ? s.next() : ""; - } - } - - contentsJson = contentsJson.replace("?PREFIX?", cfg.getOutputName()); - - final File contents = new File(cfg.getOutputDirectory() + File.separator + "Contents.json"); - try (PrintWriter out = new PrintWriter(contents)) { - out.println(contentsJson); - } - return contents; - } - - private static void replaceAlphaBackground(byte[] inputBytes, - File outputFile, - final Color newBackground) throws IOException { - - try (ByteArrayInputStream sourceStream = new ByteArrayInputStream(inputBytes)) { - BufferedImage sourceImage = ImageIO.read(sourceStream); - - // Create new image without alpha channel - BufferedImage destImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_RGB); - - // Draw source onto dest canvas - Graphics2D g2d = destImage.createGraphics(); - g2d.setColor(newBackground); - g2d.fillRect(0, 0, destImage.getWidth(), destImage.getHeight()); - g2d.drawImage(sourceImage, 0, 0, null); - g2d.dispose(); - - if (!ImageIO.write(destImage, "png", outputFile)) { - throw new RuntimeException("No image writer found in Graphics2D, cannot replace the background!"); - } - } - } -} +package org.sterl.svg2png; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Scanner; + +import javax.imageio.ImageIO; + +import org.apache.batik.transcoder.SVGAbstractTranscoder; +import org.apache.batik.transcoder.TranscoderException; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.TranscodingHints; +import org.apache.batik.transcoder.image.ImageTranscoder; +import org.apache.batik.transcoder.image.PNGTranscoder; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.sterl.svg2png.config.FileOutput; +import org.sterl.svg2png.config.OutputConfig; +import org.sterl.svg2png.util.FileUtil; + +public class Svg2Png { + + private final OutputConfig outCfg; + + public Svg2Png(OutputConfig outCfg) { + super(); + this.outCfg = outCfg; + } + + public List convert() throws IOException, TranscoderException { + List generated; + if (outCfg.getInputFile() != null) { + File input = FileUtil.newFile(outCfg.getInputFile()); + generated = convertFile(input, outCfg); + } else { + File dir = FileUtil.newFile(outCfg.getInputDirectory()); + Collection listFiles = FileUtils.listFiles(dir, new String[]{"svg"}, true); + generated = new ArrayList<>(); + for (File file : listFiles) { + generated.addAll(convertFile(file, outCfg)); + } + } + + return generated; + } + + private static List convertFile(File input, OutputConfig cfg) throws IOException, TranscoderException, FileNotFoundException { + final TranscoderInput ti = new TranscoderInput(input.toURI().toString()); + final PNGTranscoder t = new PNGTranscoder(); + + // Disable XXE + t.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, cfg.isAllowExternalResource()); + + + final List generated = new ArrayList<>(); + final String inputPath = input.getParent(); + final StringBuilder info = new StringBuilder(); + + for (FileOutput out : cfg.getFiles()) { + info.setLength(0); + info.append(StringUtils.rightPad(input.getName(), 12)); + + // https://github.com/sterlp/svg2png/issues/11 + t.addTranscodingHint(ImageTranscoder.KEY_FORCE_TRANSPARENT_WHITE, out.isForceTransparentWhite()); + if (out.getWidth() > 0) { + setSizeHint(SVGAbstractTranscoder.KEY_WIDTH, out.getWidth(), t, info); + } + if (out.getHeight() > 0) { + setSizeHint(SVGAbstractTranscoder.KEY_HEIGHT, out.getHeight(), t, info); + } + if (out.hasBackgroundColor()) { + t.addTranscodingHint(PNGTranscoder.KEY_BACKGROUND_COLOR, Color.decode("#" + out.getBackgroundColor())); + } + + final File outputFile = out.toOutputFile(input, cfg.getOutputDirectory(), cfg.getOutputName()); + FileUtil.recreateNewFile(outputFile); + + try (ByteArrayOutputStream outStream = new ByteArrayOutputStream()) { + t.transcode(ti, new TranscoderOutput(outStream)); + + if (cfg.getNoAlpha() == null) { + IOUtils.write(outStream.toByteArray(), new FileOutputStream(outputFile)); + } else { + replaceAlphaBackground(outStream.toByteArray(), outputFile, Color.decode("#" + cfg.getNoAlpha())); + } + + generated.add(outputFile); + String outF = outputFile.getCanonicalPath(); + if (inputPath != null && inputPath.length() > 0) { + outF = outF.replace(inputPath, ""); + } + info.append("\t").append(outF); + } + + System.out.println(info.toString()); + } + + if (cfg.isContentsJson()) { + final File contents = generateIOSContentJson(cfg); + generated.add(contents); + System.out.println("Generated iOS " + contents.getCanonicalPath()); + } + + return generated; + } + + private static void setSizeHint(TranscodingHints.Key hint, int size, final PNGTranscoder t, final StringBuilder info) { + if (size > 0) { + t.addTranscodingHint(hint, Float.valueOf(size)); + info.append(StringUtils.rightPad((SVGAbstractTranscoder.KEY_WIDTH == hint ? " w" : " h") + size, 6)); + } else t.removeTranscodingHint(hint); + } + + private static File generateIOSContentJson(OutputConfig cfg) throws IOException, FileNotFoundException { + String contentsJson; + + try (InputStream stream = Svg2Png.class.getResourceAsStream("/contents.json")) { + assert stream != null; + try (Scanner s = new Scanner(stream).useDelimiter("\\A")) { + contentsJson = s.hasNext() ? s.next() : ""; + } + } + + contentsJson = contentsJson.replace("?PREFIX?", cfg.getOutputName()); + + final File contents = new File(cfg.getOutputDirectory() + File.separator + "Contents.json"); + try (PrintWriter out = new PrintWriter(contents)) { + out.println(contentsJson); + } + return contents; + } + + private static void replaceAlphaBackground(byte[] inputBytes, + File outputFile, + final Color newBackground) throws IOException { + + try (ByteArrayInputStream sourceStream = new ByteArrayInputStream(inputBytes)) { + BufferedImage sourceImage = ImageIO.read(sourceStream); + + // Create new image without alpha channel + BufferedImage destImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_RGB); + + // Draw source onto dest canvas + Graphics2D g2d = destImage.createGraphics(); + g2d.setColor(newBackground); + g2d.fillRect(0, 0, destImage.getWidth(), destImage.getHeight()); + g2d.drawImage(sourceImage, 0, 0, null); + g2d.dispose(); + + if (!ImageIO.write(destImage, "png", outputFile)) { + throw new RuntimeException("No image writer found in Graphics2D, cannot replace the background!"); + } + } + } +} diff --git a/src/main/java/org/sterl/svg2png/Svg2PngException.java b/core/src/main/java/org/sterl/svg2png/Svg2PngException.java similarity index 96% rename from src/main/java/org/sterl/svg2png/Svg2PngException.java rename to core/src/main/java/org/sterl/svg2png/Svg2PngException.java index 0d792af..38bb672 100644 --- a/src/main/java/org/sterl/svg2png/Svg2PngException.java +++ b/core/src/main/java/org/sterl/svg2png/Svg2PngException.java @@ -1,22 +1,22 @@ -package org.sterl.svg2png; - -import org.sterl.svg2png.config.OutputConfig; - -import lombok.Getter; - -public class Svg2PngException extends Exception { - private static final long serialVersionUID = 1L; - @Getter - private final OutputConfig cfg; - - public Svg2PngException(Throwable e, OutputConfig config) { - super(e); - cfg = config; - } - - @Override - public String getMessage() { - if (cfg == null) return super.getMessage(); - else return super.getMessage() + " Config: " + cfg; - } -} +package org.sterl.svg2png; + +import org.sterl.svg2png.config.OutputConfig; + +import lombok.Getter; + +public class Svg2PngException extends Exception { + private static final long serialVersionUID = 1L; + @Getter + private final OutputConfig cfg; + + public Svg2PngException(Throwable e, OutputConfig config) { + super(e); + cfg = config; + } + + @Override + public String getMessage() { + if (cfg == null) return super.getMessage(); + else return super.getMessage() + " Config: " + cfg; + } +} diff --git a/src/main/java/org/sterl/svg2png/config/FileOutput.java b/core/src/main/java/org/sterl/svg2png/config/FileOutput.java similarity index 93% rename from src/main/java/org/sterl/svg2png/config/FileOutput.java rename to core/src/main/java/org/sterl/svg2png/config/FileOutput.java index 0fd4f93..c690b85 100644 --- a/src/main/java/org/sterl/svg2png/config/FileOutput.java +++ b/core/src/main/java/org/sterl/svg2png/config/FileOutput.java @@ -1,63 +1,62 @@ -package org.sterl.svg2png.config; - -import java.io.File; - -import org.apache.commons.io.FilenameUtils; -import org.sterl.svg2png.util.FileUtil; - -import lombok.Data; -import lombok.NoArgsConstructor; -/** - * Meta information where to output one converted file. - */ -@Data @NoArgsConstructor -public class FileOutput { - private int height = -1; - private int width = -1; - private String name; - private String directory; - private String nameSuffix; - private String namePrefix; - private String backgroundColor = null; - /** - * https://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/transcoder/image/ImageTranscoder.html#KEY_FORCE_TRANSPARENT_WHITE - * PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE - */ - private boolean forceTransparentWhite = false; - - public File toOutputFile(File source, String basePath, String outName) { - // either a set path or the one of the parent - String path = basePath != null ? basePath : source.getParent(); - if (path == null) path = ""; - // if the configured path is absolute we take it, otherwise we append it - if (directory != null && directory.startsWith(File.separator)) { - path = directory; - } - if (directory != null) { - if (path.length() > 0) { - path += File.separator + directory; - } else { - path += directory; - } - } - // setting the name - path += File.separator + buildName(FilenameUtils.getBaseName(source.getName()), name != null ? name : outName, namePrefix, nameSuffix); - - return FileUtil.newFile(path); - } - - static String buildName(String srcName, String outName, String prefix, String suffix) { - String name = outName != null ? outName : srcName; - String result; - if (prefix != null && !name.startsWith(prefix)) result = prefix + name; - else result = name; - - if (suffix != null && !result.endsWith(suffix)) result += suffix; - if (!result.endsWith(".png")) result += ".png"; - return result; - } - - public boolean hasBackgroundColor() { - return backgroundColor != null && backgroundColor.length() > 0; - } -} +package org.sterl.svg2png.config; + +import java.io.File; + +import org.apache.commons.io.FilenameUtils; + +import lombok.Data; +import lombok.NoArgsConstructor; +/** + * Meta information where to output one converted file. + */ +@Data @NoArgsConstructor +public class FileOutput { + private int height = -1; + private int width = -1; + private String name; + private String directory; + private String nameSuffix; + private String namePrefix; + private String backgroundColor = null; + /** + * https://xmlgraphics.apache.org/batik/javadoc/org/apache/batik/transcoder/image/ImageTranscoder.html#KEY_FORCE_TRANSPARENT_WHITE + * PNGTranscoder.KEY_FORCE_TRANSPARENT_WHITE + */ + private boolean forceTransparentWhite = false; + + public File toOutputFile(File source, String basePath, String outName) { + // either a set path or the one of the parent + String path = basePath != null ? basePath : source.getParent(); + if (path == null) path = ""; + // if the configured path is absolute we take it, otherwise we append it + if (directory != null && directory.startsWith(File.separator)) { + path = directory; + } + if (directory != null) { + if (path.length() > 0) { + path += File.separator + directory; + } else { + path += directory; + } + } + // setting the name + path += File.separator + buildName(FilenameUtils.getBaseName(source.getName()), name != null ? name : outName, namePrefix, nameSuffix); + + return new File(path); + } + + static String buildName(String srcName, String outName, String prefix, String suffix) { + String name = outName != null ? outName : srcName; + String result; + if (prefix != null && !name.startsWith(prefix)) result = prefix + name; + else result = name; + + if (suffix != null && !result.endsWith(suffix)) result += suffix; + if (!result.endsWith(".png")) result += ".png"; + return result; + } + + public boolean hasBackgroundColor() { + return backgroundColor != null && backgroundColor.length() > 0; + } +} diff --git a/src/main/java/org/sterl/svg2png/config/OutputConfig.java b/core/src/main/java/org/sterl/svg2png/config/OutputConfig.java similarity index 96% rename from src/main/java/org/sterl/svg2png/config/OutputConfig.java rename to core/src/main/java/org/sterl/svg2png/config/OutputConfig.java index 7e28522..ea7e60a 100644 --- a/src/main/java/org/sterl/svg2png/config/OutputConfig.java +++ b/core/src/main/java/org/sterl/svg2png/config/OutputConfig.java @@ -1,79 +1,79 @@ -package org.sterl.svg2png.config; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.sterl.svg2png.util.FileUtil; - -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -@Getter @Setter @ToString -public class OutputConfig { - private String inputDirectory; - private String inputFile; - private String outputName; - private String outputDirectory; - private boolean allowExternalResource = false; - private String noAlpha = null; - private boolean contentsJson = false; - - private List files = new ArrayList<>(); - - public static OutputConfig fromPath(String file) { - OutputConfig result = new OutputConfig(); - File f = FileUtil.newFile(file); - if (!f.exists()) throw new IllegalArgumentException(file + " not found!"); - - if (f.isFile()) result.setInputFile(f.getAbsolutePath()); - else result.setInputDirectory(f.getAbsolutePath()); - - - result.setOutputDirectory(new File(".").getAbsolutePath()); - result.addOutput(); // one result - return result; - } - - public void addOutput() { - files.add(new FileOutput()); - } - - public boolean hasDirectoryOrFile() { - return inputFile != null || inputDirectory != null; - } - - /** - * @param width -1 will be ignored - * @param height -1 will be ignored - */ - public void applyOutputSize(int width, int height) { - for (FileOutput fileOutput : files) { - if (width > -1) fileOutput.setWidth(width); - if (height > -1) fileOutput.setHeight(height); - } - } - - public void newOutput() { - this.files.add(new FileOutput()); - } - - public void applyFileName(String name) { - for (FileOutput f : files) { - f.setName(name); - } - } - - public void applyBackgroundColor(String color) { - for (FileOutput f : files) { - f.setBackgroundColor(color); - } - } - - public void enableForceTransparentWhite() { - for (FileOutput f : files) { - f.setForceTransparentWhite(true); - } - } +package org.sterl.svg2png.config; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.sterl.svg2png.util.FileUtil; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter @Setter @ToString +public class OutputConfig { + private String inputDirectory; + private String inputFile; + private String outputName; + private String outputDirectory; + private boolean allowExternalResource = false; + private String noAlpha = null; + private boolean contentsJson = false; + + private List files = new ArrayList<>(); + + public static OutputConfig fromPath(String file) { + OutputConfig result = new OutputConfig(); + File f = FileUtil.newFile(file); + if (!f.exists()) throw new IllegalArgumentException(file + " not found!"); + + if (f.isFile()) result.setInputFile(f.getAbsolutePath()); + else result.setInputDirectory(f.getAbsolutePath()); + + + result.setOutputDirectory(new File(".").getAbsolutePath()); + result.addOutput(); // one result + return result; + } + + public void addOutput() { + files.add(new FileOutput()); + } + + public boolean hasDirectoryOrFile() { + return inputFile != null || inputDirectory != null; + } + + /** + * @param width -1 will be ignored + * @param height -1 will be ignored + */ + public void applyOutputSize(int width, int height) { + for (FileOutput fileOutput : files) { + if (width > -1) fileOutput.setWidth(width); + if (height > -1) fileOutput.setHeight(height); + } + } + + public void newOutput() { + this.files.add(new FileOutput()); + } + + public void applyFileName(String name) { + for (FileOutput f : files) { + f.setName(name); + } + } + + public void applyBackgroundColor(String color) { + for (FileOutput f : files) { + f.setBackgroundColor(color); + } + } + + public void enableForceTransparentWhite() { + for (FileOutput f : files) { + f.setForceTransparentWhite(true); + } + } } \ No newline at end of file diff --git a/core/src/main/java/org/sterl/svg2png/util/FileUtil.java b/core/src/main/java/org/sterl/svg2png/util/FileUtil.java new file mode 100644 index 0000000..792ed44 --- /dev/null +++ b/core/src/main/java/org/sterl/svg2png/util/FileUtil.java @@ -0,0 +1,30 @@ +package org.sterl.svg2png.util; + +import java.io.File; +import java.io.IOException; +import java.net.URI; + +public class FileUtil { + + public static File newFile(String path) { + File result = new File(path); + if (!result.exists() && path.startsWith("file:/")) { + result = new File(URI.create(path)); + } + if (!result.exists() && FileUtil.class.getResource(path) != null) { + result = new File(URI.create(FileUtil.class.getResource(path).toString())); + } + if (!result.exists()) { + throw new IllegalArgumentException("File " + path + " not found!"); + } + return result; + } + + public static void recreateNewFile(File outputFile) throws IOException { + if (outputFile.exists()) { + outputFile.delete(); + } + outputFile.getParentFile().mkdirs(); + outputFile.createNewFile(); + } +} diff --git a/src/main/resources/android-24dp.json b/core/src/main/resources/android-24dp.json similarity index 100% rename from src/main/resources/android-24dp.json rename to core/src/main/resources/android-24dp.json diff --git a/src/main/resources/android-36dp.json b/core/src/main/resources/android-36dp.json similarity index 100% rename from src/main/resources/android-36dp.json rename to core/src/main/resources/android-36dp.json diff --git a/src/main/resources/android-48dp.json b/core/src/main/resources/android-48dp.json similarity index 100% rename from src/main/resources/android-48dp.json rename to core/src/main/resources/android-48dp.json diff --git a/src/main/resources/android-icon.json b/core/src/main/resources/android-icon.json similarity index 100% rename from src/main/resources/android-icon.json rename to core/src/main/resources/android-icon.json diff --git a/src/main/resources/android-launcher.json b/core/src/main/resources/android-launcher.json similarity index 100% rename from src/main/resources/android-launcher.json rename to core/src/main/resources/android-launcher.json diff --git a/src/main/resources/android-small.json b/core/src/main/resources/android-small.json similarity index 100% rename from src/main/resources/android-small.json rename to core/src/main/resources/android-small.json diff --git a/src/main/resources/android.json b/core/src/main/resources/android.json similarity index 100% rename from src/main/resources/android.json rename to core/src/main/resources/android.json diff --git a/src/main/resources/contents.json b/core/src/main/resources/contents.json similarity index 95% rename from src/main/resources/contents.json rename to core/src/main/resources/contents.json index f4c9553..1b06daf 100644 --- a/src/main/resources/contents.json +++ b/core/src/main/resources/contents.json @@ -1,116 +1,116 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20", - "filename" : "?PREFIX?-20@2x.png" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20", - "filename" : "?PREFIX?-20@3x.png" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29", - "filename" : "?PREFIX?-29@2x.png" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29", - "filename" : "?PREFIX?-29@3x.png" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40", - "filename" : "?PREFIX?-40@2x.png" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40", - "filename" : "?PREFIX?-40@3x.png" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60", - "filename" : "?PREFIX?-60@2x.png" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60", - "filename" : "?PREFIX?-60@3x.png" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20", - "filename" : "?PREFIX?-20@1x.png" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20", - "filename" : "?PREFIX?-20@2x.png" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29", - "filename" : "?PREFIX?-29@1x.png" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29", - "filename" : "?PREFIX?-29@2x.png" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40", - "filename" : "?PREFIX?-40@1x.png" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40", - "filename" : "?PREFIX?-40@2x.png" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76", - "filename" : "?PREFIX?-76@1x.png" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76", - "filename" : "?PREFIX?-76@2x.png" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5", - "filename" : "?PREFIX?-83.5@2x.png" - }, - { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024", - "filename" : "?PREFIX?-1024@1x.png" - } - ], - "info" : { - "author" : "svg2png", - "version" : 1 - } +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20", + "filename" : "?PREFIX?-20@2x.png" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20", + "filename" : "?PREFIX?-20@3x.png" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29", + "filename" : "?PREFIX?-29@2x.png" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29", + "filename" : "?PREFIX?-29@3x.png" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40", + "filename" : "?PREFIX?-40@2x.png" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40", + "filename" : "?PREFIX?-40@3x.png" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60", + "filename" : "?PREFIX?-60@2x.png" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60", + "filename" : "?PREFIX?-60@3x.png" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20", + "filename" : "?PREFIX?-20@1x.png" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20", + "filename" : "?PREFIX?-20@2x.png" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29", + "filename" : "?PREFIX?-29@1x.png" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29", + "filename" : "?PREFIX?-29@2x.png" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40", + "filename" : "?PREFIX?-40@1x.png" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40", + "filename" : "?PREFIX?-40@2x.png" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76", + "filename" : "?PREFIX?-76@1x.png" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76", + "filename" : "?PREFIX?-76@2x.png" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5", + "filename" : "?PREFIX?-83.5@2x.png" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024", + "filename" : "?PREFIX?-1024@1x.png" + } + ], + "info" : { + "author" : "svg2png", + "version" : 1 + } } \ No newline at end of file diff --git a/src/main/resources/ios.json b/core/src/main/resources/ios.json similarity index 94% rename from src/main/resources/ios.json rename to core/src/main/resources/ios.json index 8ffb200..7732e98 100644 --- a/src/main/resources/ios.json +++ b/core/src/main/resources/ios.json @@ -1,81 +1,81 @@ -{ - "files": [ - { - "nameSuffix": "-20@1x", - "height": 20, - "width": 20 - }, - { - "nameSuffix": "-20@2x", - "height": 40, - "width": 40 - }, - { - "nameSuffix": "-20@3x", - "height": 60, - "width": 60 - }, - { - "nameSuffix": "-29@1x", - "height": 29, - "width": 29 - }, - { - "nameSuffix": "-29@2x", - "height": 58, - "width": 58 - }, - { - "nameSuffix": "-29@3x", - "height": 87, - "width": 87 - }, - { - "nameSuffix": "-40@1x", - "height": 40, - "width": 40 - }, - { - "nameSuffix": "-40@2x", - "height": 80, - "width": 80 - }, - { - "nameSuffix": "-40@3x", - "height": 120, - "width": 120 - }, - { - "nameSuffix": "-60@2x", - "height": 120, - "width": 120 - }, - { - "nameSuffix": "-60@3x", - "height": 180, - "width": 180 - }, - { - "nameSuffix": "-76@1x", - "height": 76, - "width": 76 - }, - { - "nameSuffix": "-76@2x", - "height": 152, - "width": 152 - }, - { - "nameSuffix": "-83.5@2x", - "height": 167, - "width": 167 - }, - { - "nameSuffix": "-1024@1x", - "height": 1024, - "width": 1024 - } - ], - "noAlpha": "ffffff", - "contentsJson": true +{ + "files": [ + { + "nameSuffix": "-20@1x", + "height": 20, + "width": 20 + }, + { + "nameSuffix": "-20@2x", + "height": 40, + "width": 40 + }, + { + "nameSuffix": "-20@3x", + "height": 60, + "width": 60 + }, + { + "nameSuffix": "-29@1x", + "height": 29, + "width": 29 + }, + { + "nameSuffix": "-29@2x", + "height": 58, + "width": 58 + }, + { + "nameSuffix": "-29@3x", + "height": 87, + "width": 87 + }, + { + "nameSuffix": "-40@1x", + "height": 40, + "width": 40 + }, + { + "nameSuffix": "-40@2x", + "height": 80, + "width": 80 + }, + { + "nameSuffix": "-40@3x", + "height": 120, + "width": 120 + }, + { + "nameSuffix": "-60@2x", + "height": 120, + "width": 120 + }, + { + "nameSuffix": "-60@3x", + "height": 180, + "width": 180 + }, + { + "nameSuffix": "-76@1x", + "height": 76, + "width": 76 + }, + { + "nameSuffix": "-76@2x", + "height": 152, + "width": 152 + }, + { + "nameSuffix": "-83.5@2x", + "height": 167, + "width": 167 + }, + { + "nameSuffix": "-1024@1x", + "height": 1024, + "width": 1024 + } + ], + "noAlpha": "ffffff", + "contentsJson": true } \ No newline at end of file diff --git a/core/src/test/java/org/sterl/svg2png/AssertUtil.java b/core/src/test/java/org/sterl/svg2png/AssertUtil.java new file mode 100644 index 0000000..d9dd56f --- /dev/null +++ b/core/src/test/java/org/sterl/svg2png/AssertUtil.java @@ -0,0 +1,12 @@ +package org.sterl.svg2png; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public final class AssertUtil { + public final static void assertEndsWith(String absolutePath, String value) { + assertNotNull("Expected end with: " + value, absolutePath); + assertTrue(absolutePath.equals(value) || absolutePath.endsWith(value), + absolutePath + " doesn't end with: " + value); + } +} diff --git a/src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java b/core/src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java similarity index 97% rename from src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java rename to core/src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java index 50f7388..435d092 100644 --- a/src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java +++ b/core/src/test/java/org/sterl/svg2png/config/TestFileConfigParsing.java @@ -1,25 +1,25 @@ -package org.sterl.svg2png.config; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -public class TestFileConfigParsing { - - @Test - public void testNameGeneration() { - assertEquals("foo.png", FileOutput.buildName("foo", null, null, null)); - assertEquals("ic_foo.png", FileOutput.buildName("foo", null, "ic_", null)); - assertEquals("foo_24dp.png", FileOutput.buildName("foo", null, null, "_24dp")); - assertEquals("ic_foo_24dp.png", FileOutput.buildName("foo", null, "ic_", "_24dp")); - assertEquals("ic_foo_24dp.png", FileOutput.buildName("ic_foo_24dp", null, "ic_", "_24dp")); - - assertEquals("ic_foo.png", FileOutput.buildName("ic_foo", null, "ic_", null)); - - assertEquals("bar.png", FileOutput.buildName("foo", "bar", null, null)); - assertEquals("ic_bar.png", FileOutput.buildName("foo", "bar", "ic_", null)); - assertEquals("ic_bar_24dp.png", FileOutput.buildName("foo", "bar", "ic_", "_24dp")); - - assertEquals("ic_bar_24dp.png", FileOutput.buildName("foo", "ic_bar_24dp", "ic_", "_24dp")); - } -} +package org.sterl.svg2png.config; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TestFileConfigParsing { + + @Test + public void testNameGeneration() { + assertEquals("foo.png", FileOutput.buildName("foo", null, null, null)); + assertEquals("ic_foo.png", FileOutput.buildName("foo", null, "ic_", null)); + assertEquals("foo_24dp.png", FileOutput.buildName("foo", null, null, "_24dp")); + assertEquals("ic_foo_24dp.png", FileOutput.buildName("foo", null, "ic_", "_24dp")); + assertEquals("ic_foo_24dp.png", FileOutput.buildName("ic_foo_24dp", null, "ic_", "_24dp")); + + assertEquals("ic_foo.png", FileOutput.buildName("ic_foo", null, "ic_", null)); + + assertEquals("bar.png", FileOutput.buildName("foo", "bar", null, null)); + assertEquals("ic_bar.png", FileOutput.buildName("foo", "bar", "ic_", null)); + assertEquals("ic_bar_24dp.png", FileOutput.buildName("foo", "bar", "ic_", "_24dp")); + + assertEquals("ic_bar_24dp.png", FileOutput.buildName("foo", "ic_bar_24dp", "ic_", "_24dp")); + } +} diff --git a/src/test/java/org/sterl/svg2png/config/TestFileOutput.java b/core/src/test/java/org/sterl/svg2png/config/TestFileOutput.java similarity index 90% rename from src/test/java/org/sterl/svg2png/config/TestFileOutput.java rename to core/src/test/java/org/sterl/svg2png/config/TestFileOutput.java index 2afcf3a..2b96a25 100644 --- a/src/test/java/org/sterl/svg2png/config/TestFileOutput.java +++ b/core/src/test/java/org/sterl/svg2png/config/TestFileOutput.java @@ -1,49 +1,48 @@ -package org.sterl.svg2png.config; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.sterl.svg2png.TestUtil.assertEndsWith; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; - -import org.junit.jupiter.api.Test; -import org.sterl.svg2png.util.FileUtil; - -public class TestFileOutput { - - @Test - public void testNaming() throws Exception { - Path tmpDirFoooo = Files.createTempDirectory("Foooo"); - tmpDirFoooo.toFile().deleteOnExit(); - - - Path tmpDirBaaaar = Files.createTempDirectory("Baaaar"); - tmpDirBaaaar.toFile().deleteOnExit(); - - OutputConfig cfg = OutputConfig.fromPath(getClass().getResource("/svgfolder/sample.svg").toString()); - assertEquals(1, cfg.getFiles().size()); - - FileOutput outFile = cfg.getFiles().get(0); - - File srcFile = FileUtil.newFile(cfg.getInputFile()); - assertEquals("./sample.png".replace('/', File.separatorChar), outFile.toOutputFile(srcFile, ".", null).toString()); - assertEquals("/tmp/sample.png".replace('/', File.separatorChar), outFile.toOutputFile(srcFile, "/tmp", null).toString()); - System.out.println(outFile.toOutputFile(srcFile, "somesubdir", "hallo.png").toString()); - - outFile.setDirectory(tmpDirFoooo.toAbsolutePath().toString()); - assertEndsWith(outFile.toOutputFile(srcFile, null, null).getAbsolutePath(), "/sample.png".replace('/', File.separatorChar)); - assertTrue(outFile.toOutputFile(srcFile, null, "bar").getAbsolutePath().length() > 12); - assertEndsWith(outFile.toOutputFile(srcFile, null, "bar").getAbsolutePath(), "/bar.png".replace('/', File.separatorChar)); - } - - @Test - public void testCommonName() { - FileOutput fileOutput = new FileOutput(); - fileOutput.setName("ic_launcher.png"); - fileOutput.setDirectory("mipmap-xxhdpi"); - - assertEndsWith(fileOutput.toOutputFile(new File("foo.svg"), null, null).getAbsolutePath(), "mipmap-xxhdpi/ic_launcher.png".replace('/', File.separatorChar)); - } - +package org.sterl.svg2png.config; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.sterl.svg2png.AssertUtil.assertEndsWith; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; +import org.sterl.svg2png.util.FileUtil; + +public class TestFileOutput { + + @Test + public void testNaming() throws Exception { + Path tmpDirFoooo = Files.createTempDirectory("Foooo"); + tmpDirFoooo.toFile().deleteOnExit(); + + + Path tmpDirBaaaar = Files.createTempDirectory("Baaaar"); + tmpDirBaaaar.toFile().deleteOnExit(); + + OutputConfig cfg = OutputConfig.fromPath(getClass().getResource("/svgfolder/sample.svg").toString()); + assertEquals(1, cfg.getFiles().size()); + + FileOutput outFile = cfg.getFiles().get(0); + + File srcFile = FileUtil.newFile(cfg.getInputFile()); + assertEquals("./sample.png".replace('/', File.separatorChar), outFile.toOutputFile(srcFile, ".", null).toString()); + assertEquals("/tmp/sample.png".replace('/', File.separatorChar), outFile.toOutputFile(srcFile, "/tmp", null).toString()); + + outFile.setDirectory(tmpDirFoooo.toAbsolutePath().toString()); + assertEndsWith(outFile.toOutputFile(srcFile, null, null).getAbsolutePath(), "/sample.png".replace('/', File.separatorChar)); + assertTrue(outFile.toOutputFile(srcFile, null, "bar").getAbsolutePath().length() > 12); + assertEndsWith(outFile.toOutputFile(srcFile, null, "bar").getAbsolutePath(), "/bar.png".replace('/', File.separatorChar)); + } + + @Test + public void testCommonName() { + FileOutput fileOutput = new FileOutput(); + fileOutput.setName("ic_launcher.png"); + fileOutput.setDirectory("mipmap-xxhdpi"); + + assertEndsWith(fileOutput.toOutputFile(new File("foo.svg"), null, null).getAbsolutePath(), "mipmap-xxhdpi/ic_launcher.png".replace('/', File.separatorChar)); + } + } \ No newline at end of file diff --git a/core/src/test/resources/svgfolder/sample.svg b/core/src/test/resources/svgfolder/sample.svg new file mode 100644 index 0000000..80a778d --- /dev/null +++ b/core/src/test/resources/svgfolder/sample.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 9f55de3..324ceca 100644 --- a/pom.xml +++ b/pom.xml @@ -5,9 +5,9 @@ 4.0.0 org.sterl.svg2png - svg2png - jar - 1.2.2-SNAPSHOT + svg2png-root + pom + 1.3.0-SNAPSHOT https://github.com/sterlp/svg2png 2015 @@ -23,7 +23,6 @@ https://github.com/sterlp/svg2png scm:git:git@github.com:sterlp/svg2png.git - v1.2.0 @@ -55,88 +54,77 @@ UTF-8 - 1.8 + 11 1.17 + + core + cli + + org.junit junit-bom - 5.9.1 + 5.10.1 pom import - - - - - - org.apache.commons - commons-lang3 - 3.12.0 - - - - org.apache.xmlgraphics - batik-svggen - ${batik.version} - - - org.apache.xmlgraphics - batik-transcoder - ${batik.version} - - - org.apache.xmlgraphics - batik-codec - ${batik.version} - - - org.apache.xmlgraphics - xmlgraphics-commons - 2.8 - + + org.apache.commons + commons-lang3 + 3.14.0 + + + + org.apache.xmlgraphics + batik-svggen + ${batik.version} + + + org.apache.xmlgraphics + batik-transcoder + ${batik.version} + + + org.apache.xmlgraphics + batik-codec + ${batik.version} + + + org.apache.xmlgraphics + xmlgraphics-commons + 2.9 + - - commons-cli - commons-cli - 1.5.0 - + + commons-cli + commons-cli + 1.6.0 + - - com.fasterxml.jackson.core - jackson-databind - 2.14.2 - - - org.projectlombok - lombok - 1.18.26 - provided - - - com.github.romankh3 - image-comparison - 4.4.0 - test - + + com.fasterxml.jackson.core + jackson-databind + 2.16.0 + + + org.projectlombok + lombok + 1.18.30 + provided + + + com.github.romankh3 + image-comparison + 4.4.0 + test + + + - - org.junit.jupiter - junit-jupiter - test - - - - org.junit.jupiter - junit-jupiter-params - test - - @@ -161,7 +149,7 @@ maven-javadoc-plugin 3.6.0 - 8 + ${java.version} @@ -202,70 +190,61 @@ - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.21.0 - - - - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.21.0 - - - true - - true - - - - - check - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - ${java.version} - ${java.version} - - - - org.apache.maven.plugins - maven-shade-plugin - 3.3.0 - - - package - - shade - - - false - false - - - - org.sterl.svg2png.Main - ${java.version} - ${java.version} - - - - + true + + + + + check + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 + + + package + + shade + + + false + false + + + + org.sterl.svg2png.Main + ${java.version} + ${java.version} + + + + - - - - - - - org.skife.maven - really-executable-jar-maven-plugin - 2.1.1 - - + + org.skife.maven + really-executable-jar-maven-plugin + 2.1.1 + + - - -Xmx1G + + -Xmx1G - - - svg2png + + svg2png - - - - - - - + + + + + - + - - - package - - really-executable-jar - - - + + + package + + really-executable-jar + + + + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.21.0 - + \ No newline at end of file diff --git a/readme.md b/readme.md index 382940f..015024a 100644 --- a/readme.md +++ b/readme.md @@ -26,7 +26,10 @@ Batik SVG Toolkit isn't supported by android because of the missing [Java2D API] - zulu - graalvm -> temurin version 8 failed in the ci/cd build. +> temurin version 11 failed in the ci/cd build. + +- 1.2.x => JDK 8 +- 1.3.x => JDK 11 ## Download & Requirements diff --git a/src/main/java/org/sterl/svg2png/util/FileUtil.java b/src/main/java/org/sterl/svg2png/util/FileUtil.java deleted file mode 100644 index 953f04a..0000000 --- a/src/main/java/org/sterl/svg2png/util/FileUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.sterl.svg2png.util; - -import java.io.File; -import java.io.IOException; -import java.net.URI; - -public class FileUtil { - - public static File newFile(String path) { - if (path.startsWith("file:/")) { - return new File(URI.create(path)); - } else { - return new File(path); - } - } - - public static void recreateNewFile(File outputFile) throws IOException { - if (outputFile.exists()) { - outputFile.delete(); - } - outputFile.getParentFile().mkdirs(); - outputFile.createNewFile(); - } -}