All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jfoenix.svg.SVGGlyphLoader Maven / Gradle / Ivy

There is a newer version: 9.0.10
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.jfoenix.svg;

import javafx.beans.binding.Bindings;
import javafx.scene.paint.Color;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Set;

/**
 * will load icomoon svg font file, it will create a map of the
 * available svg glyphs. the user can retrieve the svg glyph using its name.
 *
 * @author Shadi Shaheen
 * @version 1.0
 * @since 2016-03-09
 */
public class SVGGlyphLoader {

    private static final HashMap glyphsMap = new HashMap<>();


    public static SVGGlyph getGlyph(String glyphName) {
        return glyphsMap.get(glyphName).build();
    }

    /**
     * will retrieve icons from the glyphs map for a certain glyphName
     *
     * @param glyphName the glyph name
     * @return SVGGlyph node
     */
    public static SVGGlyph getIcoMoonGlyph(String glyphName) throws Exception{
        SVGGlyphBuilder builder = glyphsMap.get(glyphName);
        if(builder == null) throw new Exception("Glyph '" + glyphName + "' not found!");
        SVGGlyph glyph = builder.build();
        // we need to apply transformation to correct the icon since
        // its being inverted after importing from icomoon
        glyph.getTransforms().add(new Scale(1, -1));
        Translate height = new Translate();
        height.yProperty().bind(Bindings.createDoubleBinding(() -> -glyph.getHeight(), glyph.heightProperty()));
        glyph.getTransforms().add(height);
        return glyph;
    }

    /**
     * @return a set of all loaded svg IDs (names)
     */
    public static Set getAllGlyphsIDs() {
        return glyphsMap.keySet();
    }

    /**
     * will load SVG icons from icomoon font file (e.g font.svg)
     *
     * @param url of the svg font file
     * @throws IOException
     */
    public static void loadGlyphsFont(URL url) throws IOException {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            docBuilder.setEntityResolver((publicId, systemId) -> {
                // disable dtd entites at runtime
                return new InputSource(new StringReader(""));
            });

            File svgFontFile = new File(url.toURI());
            Document doc = docBuilder.parse(svgFontFile);
            doc.getDocumentElement().normalize();

            NodeList glyphsList = doc.getElementsByTagName("glyph");
            for (int i = 0; i < glyphsList.getLength(); i++) {
                Node glyph = glyphsList.item(i);
                Node glyphName = glyph.getAttributes().getNamedItem("glyph-name");
                if (glyphName == null) {
                    continue;
                }

                String glyphId = glyphName.getNodeValue();
                SVGGlyphBuilder glyphPane = new SVGGlyphBuilder(i,
                    glyphId,
                    glyph.getAttributes()
                        .getNamedItem("d")
                        .getNodeValue());
                glyphsMap.put(svgFontFile.getName() + "." + glyphId, glyphPane);
            }
        } catch (ParserConfigurationException | SAXException | URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * will load SVG icons from input stream
     *
     * @param stream    input stream of svg font file
     * @param keyPrefix will be used as a prefix when storing SVG icons in the map
     * @throws IOException
     */
    public static void loadGlyphsFont(InputStream stream, String keyPrefix) throws IOException {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            docBuilder.setEntityResolver((publicId, systemId) -> {
                // disable dtd entites at runtime
                return new InputSource(new StringReader(""));
            });

            Document doc = docBuilder.parse(stream);
            doc.getDocumentElement().normalize();

            NodeList glyphsList = doc.getElementsByTagName("glyph");
            for (int i = 0; i < glyphsList.getLength(); i++) {
                Node glyph = glyphsList.item(i);
                Node glyphName = glyph.getAttributes().getNamedItem("glyph-name");
                if (glyphName == null) {
                    continue;
                }

                String glyphId = glyphName.getNodeValue();
                SVGGlyphBuilder glyphPane = new SVGGlyphBuilder(i,
                    glyphId,
                    glyph.getAttributes()
                        .getNamedItem("d")
                        .getNodeValue());
                glyphsMap.put(keyPrefix + "." + glyphId, glyphPane);
            }
            stream.close();
        } catch (ParserConfigurationException | SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * load a single svg icon from a file
     *
     * @param url of the svg icon
     * @return SVGGLyph node
     * @throws IOException
     */
    public static SVGGlyph loadGlyph(URL url) throws IOException {
        String urlString = url.toString();
        String filename = urlString.substring(urlString.lastIndexOf('/') + 1);

        int startPos = 0;
        int endPos = 0;
        while (endPos < filename.length() && filename.charAt(endPos) != '-') {
            endPos++;
        }
        int id = Integer.parseInt(filename.substring(startPos, endPos));
        startPos = endPos + 1;

        while (endPos < filename.length() && filename.charAt(endPos) != '.') {
            endPos++;
        }
        String name = filename.substring(startPos, endPos);

        return new SVGGlyph(id, name, extractSvgPath(getStringFromInputStream(url.openStream())), Color.BLACK);
    }

    /**
     * clear all loaded svg icons
     */
    public static void clear() {
        glyphsMap.clear();
    }

    private static String extractSvgPath(String svgString) {
        return svgString.replaceFirst(".*d=\"", "").replaceFirst("\".*", "");
    }

    private static String getStringFromInputStream(InputStream is) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();

        String line;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    private static final class SVGGlyphBuilder {
        private int glyphId;
        private String name;
        private String svgPathContent;

        SVGGlyphBuilder(int glyphId, String name, String svgPathContent) {
            this.glyphId = glyphId;
            this.name = name;
            this.svgPathContent = svgPathContent;
        }

        SVGGlyph build() {
            return new SVGGlyph(glyphId, name, svgPathContent, Color.BLACK);
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy