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

com.metaeffekt.artifact.analysis.utils.SvgCreator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed 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.metaeffekt.artifact.analysis.utils;

import org.apache.commons.lang3.tuple.Pair;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class SvgCreator {

    private final ArrayList shapes = new ArrayList<>();
    private final ArrayList defs = new ArrayList<>();
    private final ArrayList fonts = new ArrayList<>();
    private int startX = 0, startY = 0, width = 100, height = 100;
    private String svgParameters = "";

    public void setViewBox(int startX, int startY, int width, int height) {
        this.startX = startX;
        this.startY = startY;
        this.width = width;
        this.height = height;
    }

    public void setSvgParameters(String parameters) {
        svgParameters = parameters;
    }

    public void addShape(String identifier, String type, String... parameters) {
        shapes.add(new Shape(identifier, type, parameters));
    }

    public boolean shapeExists(String identifier) {
        return getShape(identifier) != null;
    }

    public boolean setShapeParameter(String identifier, String... parameter) {
        Shape shape = getShape(identifier);
        if (shape == null) return false;
        for (String param : parameter)
            shape.setParameter(param);
        return true;
    }

    public boolean setShapeStyle(String identifier, String... parameter) {
        Shape shape = getShape(identifier);
        if (shape == null) return false;
        for (String param : parameter)
            shape.setStyle(param);
        return true;
    }

    public void createRectangle(String identifier, int x, int y, int width, int height) {
        createRoundedRectangle(identifier, x, y, width, height, -1, -1);
    }

    public void createRoundedRectangle(String identifier, int x, int y, int width, int height, int rx, int ry) {
        Shape shape = new Shape(identifier, SHAPE_RECTANGLE, ATTRIBUTE_X + "=" + x, ATTRIBUTE_Y + "=" + y, ATTRIBUTE_WIDTH + "=" + width, ATTRIBUTE_HEIGHT + "=" + height);
        if (rx != -1) shape.setParameter(ATTRIBUTE_RX + "=" + rx);
        if (ry != -1) shape.setParameter(ATTRIBUTE_RY + "=" + ry);
        shapes.add(shape);
    }

    public void createCircle(String identifier, int cx, int cy, int radius) {
        Shape shape = new Shape(identifier, SHAPE_CIRCLE, ATTRIBUTE_CENTER_X + "=" + cx, ATTRIBUTE_CENTER_Y + "=" + cy, ATTRIBUTE_RADIUS + "=" + radius);
        shapes.add(shape);
    }

    public void createEllipse(String identifier, int cx, int cy, int rx, int ry) {
        Shape shape = new Shape(identifier, SHAPE_ELLIPSE, ATTRIBUTE_CENTER_X + "=" + cx, ATTRIBUTE_CENTER_Y + "=" + cy, ATTRIBUTE_RX + "=" + rx, ATTRIBUTE_RY + "=" + ry);
        shapes.add(shape);
    }

    public void createLine(String identifier, int x1, int y1, int x2, int y2) {
        Shape shape = new Shape(identifier, SHAPE_ELLIPSE, ATTRIBUTE_X1 + "=" + x1, ATTRIBUTE_Y1 + "=" + y1, ATTRIBUTE_X2 + "=" + x2, ATTRIBUTE_Y2 + "=" + y2, ATTRIBUTE_STROKE_COLOR + "=black");
        shapes.add(shape);
    }

    public void createLine(String identifier, int x1, int y1, int x2, int y2, int width, String color) {
        Shape shape = new Shape(identifier, SHAPE_LINE, ATTRIBUTE_X1 + "=" + x1, ATTRIBUTE_Y1 + "=" + y1, ATTRIBUTE_X2 + "=" + x2, ATTRIBUTE_Y2 + "=" + y2, ATTRIBUTE_STROKE_COLOR + "=" + color, ATTRIBUTE_STROKE_WIDTH + "=" + width);
        shapes.add(shape);
    }

    public void createPolyLine(String identifier) {
        Polygon polygon = new Polygon(identifier, SHAPE_POLY_LINE);
        shapes.add(polygon);
    }

    public void createPolygon(String identifier) {
        Polygon polygon = new Polygon(identifier, SHAPE_POLYGON);
        shapes.add(polygon);
    }

    public void addPolyPoint(String identifier, int x, int y) {
        Shape polygon = getShape(identifier);
        if (polygon instanceof Polygon) ((Polygon) polygon).addPoint(x, y);
    }

    public void createText(String identifier, int x, int y, String text, String fontIdentifier) {
        Text shape = new Text(identifier, SHAPE_TEXT, ATTRIBUTE_X + "=" + x, ATTRIBUTE_Y + "=" + y);
        shape.setText(text);
        if (fontIdentifier.length() > 0) shape.setParameter(ATTRIBUTE_CLASS + "=" + fontIdentifier);
        shapes.add(shape);
    }

    public void setShapeBorder(String identifier, int strokeWidth, String color) {
        Shape shape = getShape(identifier);
        shape.setStyle(ATTRIBUTE_STROKE_WIDTH + "=" + strokeWidth);
        shape.setStyle(ATTRIBUTE_STROKE_COLOR + "=" + (color.contains("#") ? color : "#" + color));
    }

    public void setShapeFillColor(String identifier, String color) {
        Shape shape = getShape(identifier);
        shape.setStyle(ATTRIBUTE_FILL_COLOR + "=" + (color.contains("#") ? color : "#" + color));
    }

    public void setShapeGlobalOpacity(String identifier, double opacity) {
        Shape shape = getShape(identifier);
        shape.setParameter(ATTRIBUTE_OPACITY + "=" + opacity);
    }

    public void setShapeFillOpacity(String identifier, double opacity) {
        Shape shape = getShape(identifier);
        shape.setParameter(ATTRIBUTE_FILL_OPACITY + "=" + opacity);
    }

    public void setShapeStrokeOpacity(String identifier, double opacity) {
        Shape shape = getShape(identifier);
        shape.setParameter(ATTRIBUTE_STROKE_OPACITY + "=" + opacity);
    }

    public Shape getShape(String identifier) {
        for (Shape shape : shapes)
            if (shape.getIdentifier().equals(identifier))
                return shape;
        return null;
    }

    public void addDef(String identifier, String type, String... parameter) {
        defs.add(new Def(identifier, type, parameter));
    }

    public void addDefElement(String identifier, String element) {
        for (Def def : defs) {
            if (def.getIdentifier().equals(identifier))
                def.addElement(element);
        }
    }

    public void createDefLinearGradient(String identifier, String gradientTransform, String... steps) {
        Def def = new Def(identifier, GRADIENT_LINEAR);
        def.setParameter(ATTRIBUTE_GRADIENT_TRANSFORM + "=" + gradientTransform);
        for (String step : steps) {
            String[] stepValues = step.split(PARAMETER_SPLITTER_EXPRESSION);
            def.addElement("");
        }
        defs.add(def);
    }

    public void createDefRadialGradient(String identifier, String... steps) {
        Def def = new Def(identifier, GRADIENT_RADIAL);
        for (String step : steps) {
            String[] stepValues = step.split(PARAMETER_SPLITTER_EXPRESSION);
            def.addElement("");
        }
        defs.add(def);
    }

    public void createFont(String identifier, String font, String color) {
        StringBuilder fontBuilder = new StringBuilder();
        fontBuilder.append(".").append(identifier).append(" { font: ").append(font).append(";");
        if (color.length() > 0)
            fontBuilder.append(" fill: ").append(color.contains("#") ? color : "#" + color).append("; }");
        fonts.add(fontBuilder.toString());
    }

    public void generate(File file) throws IOException {
        ArrayList lines = new ArrayList<>();
        lines.add("");

        for (Def def : defs)
            lines.add(def.generate().replace(" \"", "\"").replace(" />", "/>").replace(" >", ">"));
        if (fonts.size() > 0) {
            lines.add("");
        }
        for (Shape shape : shapes)
            lines.add(shape.generate().replace(" \"", "\"").replace(" />", "/>").replace(" >", ">"));

        lines.add("");

        FileUtils.writeLines(file, FileUtils.ENCODING_UTF_8, lines);
    }

    public ArrayList generateSVG() {
        ArrayList lines = new ArrayList<>();
        lines.add("");

        for (Def def : defs)
            lines.add(def.generate().replace(" \"", "\"").replace(" />", "/>").replace(" >", ">"));
        if (fonts.size() > 0) {
            lines.add("");
        }
        for (Shape shape : shapes)
            lines.add(shape.generate().replace(" \"", "\"").replace(" />", "/>").replace(" >", ">"));

        lines.add("");

        return lines;
    }

    private static class Shape {
        private final String identifier, type;
        private final ArrayList> parameters = new ArrayList<>();
        private final ArrayList> style = new ArrayList<>();

        public Shape(String identifier, String type, String... parameters) {
            this.identifier = identifier;
            this.type = type;
            for (String parameter : parameters)
                setParameter(parameter);
        }

        public Shape(String identifier, String type) {
            this.identifier = identifier;
            this.type = type;
        }

        public void setParameter(String parameter) {
            String[] setValues = parameter.split(PARAMETER_SPLITTER_EXPRESSION);
            for (Pair param : parameters) {
                if (param.getLeft().equals(setValues[0]))
                    param.setValue(setValues[1]);
            }
            parameters.add(Pair.of(setValues[0], setValues[1]));
        }

        public void removeParameter(String parameter) {
            for (int i = 0; i < parameters.size(); i++)
                if (parameters.get(i).getLeft().equals(parameter)) {
                    parameters.remove(i);
                    return;
                }
        }

        public void setStyle(String parameter) {
            String[] setValues = parameter.split(PARAMETER_SPLITTER_EXPRESSION);
            for (Pair param : style) {
                if (param.getLeft().equals(setValues[0]))
                    param.setValue(setValues[1]);
            }
            style.add(Pair.of(setValues[0], setValues[1]));
        }

        public void removeStyle(String parameter) {
            for (int i = 0; i < style.size(); i++)
                if (style.get(i).getLeft().equals(parameter)) {
                    style.remove(i);
                    return;
                }
        }

        public String generate() {
            StringBuilder generated = new StringBuilder();
            generated.append("<").append(type).append(" id=\"").append(identifier).append("\" ");
            for (Pair parameter : parameters)
                generated.append(parameter.getLeft()).append("=\"").append(parameter.getRight()).append("\" ");
            if (style.size() > 0) {
                generated.append(ATTRIBUTE_STYLE + "=\"");
                for (Pair parameter : style)
                    generated.append(parameter.getLeft()).append(": ").append(parameter.getRight()).append("; ");
                generated.append("\"");
            }
            generated.append("/>");
            return generated.toString();
        }

        public String getIdentifier() {
            return identifier;
        }
    }

    private static class Polygon extends Shape {
        private final ArrayList points = new ArrayList<>();

        public Polygon(String identifier, String type, String... parameters) {
            super(identifier, type, parameters);
        }

        public void addPoint(int x, int y) {
            points.add(new int[]{x, y});
        }

        @Override
        public String generate() {
            StringBuilder generated = new StringBuilder();
            generated.append("<").append(super.type).append(" id=\"").append(super.identifier).append("\" ");
            for (Pair parameter : super.parameters)
                generated.append(parameter.getLeft()).append("=\"").append(parameter.getRight()).append("\" ");
            if (points.size() > 0) {
                generated.append(ATTRIBUTE_POINTS + "=\"");
                for (int[] point : points)
                    generated.append(point[0]).append(",").append(point[1]).append(" ");
                generated.append("\" ");
            }
            if (super.style.size() > 0) {
                generated.append(ATTRIBUTE_STYLE + "=\"");
                for (Pair parameter : super.style)
                    generated.append(parameter.getLeft()).append(": ").append(parameter.getRight()).append("; ");
                generated.append("\"");
            }
            generated.append("/>");
            return generated.toString();
        }
    }

    private static class Def extends Shape {

        private final ArrayList elements = new ArrayList<>();

        public Def(String identifier, String type, String... parameters) {
            super(identifier, type, parameters);
        }

        public Def(String identifier, String type) {
            super(identifier, type);
        }

        public void addElement(String element) {
            elements.add(element);
        }

        @Override
        public String generate() {
            StringBuilder generated = new StringBuilder();
            generated.append("<").append(super.type).append(" id=\"").append(super.identifier).append("\" ");
            for (Pair parameter : super.parameters)
                generated.append(parameter.getLeft()).append("=\"").append(parameter.getRight()).append("\" ");
            if (super.style.size() > 0) {
                generated.append(ATTRIBUTE_STYLE + "=\"");
                for (Pair parameter : super.style)
                    generated.append(parameter.getLeft()).append(": ").append(parameter.getRight()).append("; ");
                generated.append("\"");
            }
            generated.append(">");
            for (String element : elements)
                generated.append("\n\t").append(element);
            generated.append("\n").append("");
            return generated.toString();
        }
    }

    private static class Text extends Shape {
        private String text;

        public Text(String identifier, String type, String... parameters) {
            super(identifier, type, parameters);
        }

        public Text(String identifier, String type) {
            super(identifier, type);
        }

        public void setText(String text) {
            this.text = text;
        }

        @Override
        public String generate() {
            StringBuilder generated = new StringBuilder();
            generated.append("<").append(super.type).append(" id=\"").append(super.identifier).append("\" ");
            for (Pair parameter : super.parameters)
                generated.append(parameter.getLeft()).append("=\"").append(parameter.getRight()).append("\" ");
            if (super.style.size() > 0) {
                generated.append(ATTRIBUTE_STYLE + "=\"");
                for (Pair parameter : super.style)
                    generated.append(parameter.getLeft()).append(": ").append(parameter.getRight()).append("; ");
                generated.append("\"");
            }
            generated.append(">").append(text).append("");
            return generated.toString();
        }
    }

    public static String colorToLinkedColor(String identifier) {
        return "url('#" + identifier + "')";
    }

    public final static String SHAPE_RECTANGLE = "rect";
    public final static String SHAPE_CIRCLE = "circle";
    public final static String SHAPE_ELLIPSE = "ellipse";
    public final static String SHAPE_LINE = "line";
    public final static String SHAPE_POLYGON = "polygon";
    public final static String SHAPE_POLY_LINE = "polyline";
    public final static String SHAPE_TEXT = "text";

    public final static String ATTRIBUTE_FILL_COLOR = "fill";
    public final static String ATTRIBUTE_FILL_OPACITY = "fill-opacity";
    public final static String ATTRIBUTE_STROKE_OPACITY = "stroke-opacity";
    public final static String ATTRIBUTE_OPACITY = "opacity";
    public final static String ATTRIBUTE_STYLE = "style";
    public final static String ATTRIBUTE_VIEWBOX = "viewbox";
    public final static String ATTRIBUTE_STROKE_WIDTH = "stroke-width";
    public final static String ATTRIBUTE_STROKE_COLOR = "stroke";
    public final static String ATTRIBUTE_X = "x";
    public final static String ATTRIBUTE_Y = "y";
    public final static String ATTRIBUTE_CENTER_X = "cx";
    public final static String ATTRIBUTE_CENTER_Y = "cy";
    public final static String ATTRIBUTE_WIDTH = "width";
    public final static String ATTRIBUTE_HEIGHT = "height";
    public final static String ATTRIBUTE_RX = "rx";
    public final static String ATTRIBUTE_RY = "ry";
    public final static String ATTRIBUTE_RADIUS = "r";
    public final static String ATTRIBUTE_XMLNS = "xmlns";
    public final static String ATTRIBUTE_X1 = "x1";
    public final static String ATTRIBUTE_X2 = "x2";
    public final static String ATTRIBUTE_Y1 = "y1";
    public final static String ATTRIBUTE_Y2 = "y2";
    public final static String ATTRIBUTE_POINTS = "points";
    public final static String ATTRIBUTE_GRADIENT_TRANSFORM = "gradientTransform";
    public final static String ATTRIBUTE_OFFSET = "offset";
    public final static String ATTRIBUTE_STOP_COLOR = "stop-color";
    public final static String ATTRIBUTE_CLASS = "class";
    public final static String ATTRIBUTE_ROTATE = "rotate";
    public final static String ATTRIBUTE_ = "";

    public final static String GRADIENT_LINEAR = "linearGradient";
    public final static String GRADIENT_RADIAL = "radialGradient";
    public final static String GRADIENT_TRANSFORM_TOP_DOWN = "rotate(90)";
    public final static String GRADIENT_TRANSFORM_LEFT_RIGHT = "rotate(360)";

    private final static String PARAMETER_SPLITTER_EXPRESSION = "[=:] ?";
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy