Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// THIS FILE HAS BEEN GENERATED BY A PREPROCESSOR.
/* +=======================================================================
* |
* | PlantUML : a free UML diagram generator
* |
* +=======================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/liberapay (only 1€ per month!)
* https://plantuml.com/paypal
*
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the Eclipse Public License.
*
* THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
* LICENSE ("AGREEMENT"). [Eclipse Public License - v 1.0]
*
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
*
* You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* 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.
*
* PlantUML can occasionally display sponsored or advertising messages. Those
* messages are usually generated on welcome or error images and never on
* functional diagrams.
* See https://plantuml.com/professional if you want to remove them
*
* Images (whatever their format : PNG, SVG, EPS...) generated by running PlantUML
* are owned by the author of their corresponding sources code (that is, their
* textual description in PlantUML language). Those images are not covered by
* this EPL license.
*
* The generated images can then be used without any reference to the EPL license.
* It is not even necessary to stipulate that they have been generated with PlantUML,
* although this will be appreciated by the PlantUML team.
*
* There is an exception : if the textual description in PlantUML language is also covered
* by any license, then the generated images are logically covered
* by the very same license.
*
* This is the IGY distribution (Install GraphViz by Yourself).
* You have to install GraphViz and to setup the GRAPHVIZ_DOT environment variable
* (see https://plantuml.com/graphviz-dot )
*
* Icons provided by OpenIconic : https://useiconic.com/open
* Archimate sprites provided by Archi : http://www.archimatetool.com
* Stdlib AWS provided by https://github.com/milo-minderbinder/AWS-PlantUML
* Stdlib Icons provided https://github.com/tupadr3/plantuml-icon-font-sprites
* ASCIIMathML (c) Peter Jipsen http://www.chapman.edu/~jipsen
* ASCIIMathML (c) David Lippman http://www.pierce.ctc.edu/dlippman
* CafeUndZopfli ported by Eugene Klyuchnikov https://github.com/eustas/CafeUndZopfli
* Brotli (c) by the Brotli Authors https://github.com/google/brotli
* Themes (c) by Brett Schwarz https://github.com/bschwarz/puml-themes
* Twemoji (c) by Twitter at https://twemoji.twitter.com/
*
*/
package net.sourceforge.plantuml.klimt.drawing.svg;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import net.sourceforge.plantuml.FileUtils;
import net.sourceforge.plantuml.code.TranscoderUtil;
import net.sourceforge.plantuml.klimt.UGroupType;
import net.sourceforge.plantuml.klimt.UPath;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColorGradient;
import net.sourceforge.plantuml.klimt.geom.USegment;
import net.sourceforge.plantuml.klimt.geom.USegmentType;
import net.sourceforge.plantuml.klimt.geom.XDimension2D;
import net.sourceforge.plantuml.klimt.shape.UImageSvg;
import net.sourceforge.plantuml.log.Logme;
import net.sourceforge.plantuml.security.SImageIO;
import net.sourceforge.plantuml.security.SecurityProfile;
import net.sourceforge.plantuml.security.SecurityUtils;
import net.sourceforge.plantuml.utils.Base64Coder;
import net.sourceforge.plantuml.utils.Log;
import net.sourceforge.plantuml.xml.XmlFactories;
public class SvgGraphics {
// ::remove file when __HAXE__
// http://tutorials.jenkov.com/svg/index.html
// http://www.svgbasics.com/
// http://apike.ca/prog_svg_text.html
// http://www.w3.org/TR/SVG11/shapes.html
// http://en.wikipedia.org/wiki/Scalable_Vector_Graphics
// Animation:
// http://srufaculty.sru.edu/david.dailey/svg/
// Shadow:
// http://www.svgbasics.com/filters3.html
// http://www.w3schools.com/svg/svg_feoffset.asp
// http://www.adobe.com/svg/demos/samples.html
private static final String XLINK_TITLE1 = "title";
private static final String XLINK_TITLE2 = "xlink:title";
private static final String XLINK_HREF1 = "href";
private static final String XLINK_HREF2 = "xlink:href";
final private Document document;
final private Element root;
final private Element defs;
final private Element gRoot;
private String fill = "black";
private String stroke = "black";
private String strokeWidth;
private String strokeDasharray = null;
private final String backcolorString;
private int maxX = 10;
private int maxY = 10;
private final String filterUid;
private final String shadowId;
private final String gradientId;
private final SvgOption option;
private Element pendingBackground;
private boolean robotoAdded = false;
final protected void ensureVisible(double x, double y) {
if (x > maxX)
maxX = (int) (x + 1);
if (y > maxY)
maxY = (int) (y + 1);
}
public SvgGraphics(long seed, SvgOption option) {
try {
this.document = getDocument();
this.option = option;
final XDimension2D minDim = option.getMinDim();
ensureVisible(minDim.getWidth(), minDim.getHeight());
this.root = getRootNode();
// Create a node named defs, which will be the parent
// for a pair of linear gradient definitions.
defs = simpleElement("defs");
gRoot = simpleElement("g");
strokeWidth = "" + option.getScale();
this.filterUid = "b" + getSeed(seed);
this.shadowId = "f" + getSeed(seed);
this.gradientId = "g" + getSeed(seed);
if (option.getHover() != null)
defs.appendChild(getPathHover(option.getHover()));
if (option.isInteractive()) {
final Element styles = getStylesForInteractiveMode();
if (styles != null)
defs.appendChild(styles);
final Element script = getScriptForInteractiveMode();
if (script != null)
defs.appendChild(script);
}
final HColor backcolor = option.getBackcolor();
if (backcolor instanceof HColorGradient) {
this.backcolorString = null;
HColorGradient gr = (HColorGradient) backcolor;
final String id = this.createSvgGradient(gr.getColor1().toRGB(option.getColorMapper()),
gr.getColor2().toRGB(option.getColorMapper()), gr.getPolicy());
this.paintBackcolor("url(#" + id + ")");
} else if (backcolor == null) {
this.backcolorString = null;
} else {
this.backcolorString = backcolor.toSvg(option.getColorMapper());
final String color = backcolor.toSvg(option.getColorMapper());
if (color.equals("#00000000") == false && color.equals("#000000") == false
&& color.equals("#FFFFFF") == false)
this.paintBackcolor(color);
}
} catch (ParserConfigurationException e) {
Logme.error(e);
throw new IllegalStateException(e);
}
}
private void addRoboto() {
if (robotoAdded)
return;
// https://stackoverflow.com/questions/36253961/using-google-fonts-with-svg-object
final Element style = document.createElement("style");
style.setAttribute("type", "text/css");
style.setTextContent(
"@import url('https://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic');");
defs.appendChild(style);
robotoAdded = true;
}
private void paintBackcolor(String back) {
setFillColor(back);
setStrokeColor(null);
pendingBackground = createRectangleInternal(0, 0, 0, 0);
getG().appendChild(pendingBackground);
}
private Element getStylesForInteractiveMode() {
final Element style = simpleElement("style");
final String text = getData("default.css");
if (text == null)
return null;
final CDATASection cdata = document.createCDATASection(text);
style.setAttribute("type", "text/css");
style.appendChild(cdata);
return style;
}
// private Element getStylesForDarkness() {
// final Element style = simpleElement("style");
// final StringBuilder text1 = new StringBuilder();
// final StringBuilder text2 = new StringBuilder("@media (prefers-color-scheme:dark) {");
// final Pattern p = Pattern.compile("^(\\w)_(\\w+)_(\\w+)$");
// for (String s : this.classesForDarkness) {
// final Matcher m = p.matcher(s);
// if (m.matches() == false)
// throw new IllegalStateException();
// final String color1 = m.group(2);
// final String color2 = m.group(3);
// final String type = m.group(1);
// if ("f".equals(type)) {
// text1.append("*." + s + " {fill:#" + color1 + ";}");
// text2.append("*." + s + " {fill:#" + color2 + ";}");
// } else if ("s".equals(type)) {
// text1.append("*." + s + " {stroke:#" + color1 + ";}");
// text2.append("*." + s + " {stroke:#" + color2 + ";}");
// } else
// throw new IllegalStateException();
// }
// text2.append("}");
// final CDATASection cdata = document.createCDATASection(text1.toString() + text2.toString());
// style.setAttribute("type", "text/css");
// style.appendChild(cdata);
// return style;
// }
private Element getScriptForInteractiveMode() {
final Element script = document.createElement("script");
final String text = getData("default.js");
if (text == null)
return null;
script.setTextContent(text);
return script;
}
private static String getData(final String name) {
try {
final InputStream is = SvgGraphics.class.getResourceAsStream("/svg/" + name);
if (is == null)
Log.error("Cannot retrieve " + name);
else
return FileUtils.readText(is);
} catch (IOException e) {
Logme.error(e);
}
return null;
}
private Element getPathHover(String hover) {
final Element style = simpleElement("style");
final CDATASection cdata = document.createCDATASection("path:hover { stroke: " + hover + " !important;}");
style.setAttribute("type", "text/css");
style.appendChild(cdata);
return style;
}
private static String getSeed(final long seed) {
return Long.toString(Math.abs(seed), 36);
}
// This method returns a reference to a simple XML
// element node that has no attributes.
private Element simpleElement(String type) {
final Element theElement = (Element) document.createElement(type);
root.appendChild(theElement);
return theElement;
}
private Document getDocument() throws ParserConfigurationException {
final DocumentBuilder builder = XmlFactories.newDocumentBuilder();
final Document document = builder.newDocument();
document.setXmlStandalone(true);
return document;
}
// This method returns a reference to a root node that
// has already been appended to the document.
private Element getRootNode() {
// Create the root node named svg and append it to
// the document.
final Element svg = (Element) document.createElement("svg");
document.appendChild(svg);
// Set some attributes on the root node that are
// required for proper rendering. Note that the
// approach used here is somewhat different from the
// approach used in the earlier program named Svg01,
// particularly with regard to the style.
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
svg.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
svg.setAttribute("version", "1.1");
if (option.getTitle() != null) {
// Create a title element and set its text
final Element title = (Element) document.createElement("title");
title.setTextContent(option.getTitle());
svg.appendChild(title);
}
return svg;
}
public void svgEllipse(double x, double y, double xRadius, double yRadius, double deltaShadow) {
manageShadow(deltaShadow);
if (hidden == false) {
final Element elt = (Element) document.createElement("ellipse");
elt.setAttribute("cx", format(x));
elt.setAttribute("cy", format(y));
elt.setAttribute("rx", format(xRadius));
elt.setAttribute("ry", format(yRadius));
fillMe(elt);
elt.setAttribute("style", getStyle());
addFilterShadowId(elt, deltaShadow);
getG().appendChild(elt);
}
ensureVisible(x + xRadius + deltaShadow * 2, y + yRadius + deltaShadow * 2);
}
public void svgArcEllipse(double rx, double ry, double x1, double y1, double x2, double y2) {
if (hidden == false) {
final String path = "M" + format(x1) + "," + format(y1) + " A" + format(rx) + "," + format(ry) + " 0 0 0 "
+ format(x2) + " " + format(y2);
final Element elt = (Element) document.createElement("path");
elt.setAttribute("d", path);
fillMe(elt);
elt.setAttribute("style", getStyle());
getG().appendChild(elt);
}
ensureVisible(x1, y1);
ensureVisible(x2, y2);
}
private Map, String> gradients = new HashMap, String>();
public String createSvgGradient(String color1, String color2, char policy) {
final List