From fb91ff5cbf848d262fbb45cc8498e335ac5a48f1 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 6 Apr 2021 01:10:39 +0200 Subject: [PATCH] [DEBUG] generation is opk, except the gradiant reflect that have some errors. --- src/org/atriasoft/esvg/Base.java | 91 ++++--- src/org/atriasoft/esvg/EsvgDocument.java | 4 +- src/org/atriasoft/esvg/Group.java | 5 +- src/org/atriasoft/esvg/LinearGradient.java | 22 +- src/org/atriasoft/esvg/PaintState.java | 16 ++ src/org/atriasoft/esvg/Path.java | 227 +++++++++++------- src/org/atriasoft/esvg/Polygon.java | 2 +- src/org/atriasoft/esvg/RadialGradient.java | 24 +- src/org/atriasoft/esvg/Renderer.java | 10 +- .../atriasoft/esvg/render/DynamicColor.java | 2 + .../esvg/render/DynamicColorSpecial.java | 4 +- src/org/atriasoft/esvg/render/PathModel.java | 2 +- .../atriasoft/esvg/render/SegmentList.java | 151 ++++++------ test/src/test/atriasoft/esvg/ConfigTest.java | 5 +- .../atriasoft/esvg/TestGradientLinear.java | 54 +++-- test/src/test/atriasoft/esvg/TestStyle.java | 3 +- 16 files changed, 362 insertions(+), 260 deletions(-) diff --git a/src/org/atriasoft/esvg/Base.java b/src/org/atriasoft/esvg/Base.java index 0cc0e29..27b6c30 100644 --- a/src/org/atriasoft/esvg/Base.java +++ b/src/org/atriasoft/esvg/Base.java @@ -67,7 +67,7 @@ public class Base { Base(final PaintState parentPaintState) { // copy the parent painting properties ... - this.paint = parentPaintState; + this.paint = parentPaintState.clone(); } void display(final int spacing) {} @@ -119,14 +119,14 @@ public class Base { Pair localColor = new Pair<>(Color.WHITE, ""); if (inputData.length() > 4 && inputData.charAt(0) == 'u' && inputData.charAt(1) == 'r' && inputData.charAt(2) == 'l' && inputData.charAt(3) == '(') { if (inputData.charAt(4) == '#') { - String color = inputData.substring(5); + String color = inputData.substring(5, inputData.length() - 1); localColor = new Pair<>(Color.NONE, color); } else { Log.error("Problem in parsing the color : '" + inputData + "' == > url(XXX) is not supported now ..."); } } else { try { - localColor = new Pair<>(Color.valueOf(inputData), ""); + localColor = new Pair<>(Color.valueOf256(inputData), ""); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -169,50 +169,48 @@ public class Base { } } - Pair parseLength2(final String dataInput) { - Log.verbose(" lenght : '" + dataInput + "'"); - float n = Float.parseFloat(dataInput); - String unit = ""; - for (int iii = 0; iii < dataInput.length(); ++iii) { - if ((dataInput.charAt(iii) >= '0' && dataInput.charAt(iii) <= '9') || dataInput.charAt(iii) == '+' || dataInput.charAt(iii) == '-' || dataInput.charAt(iii) == '.') { - continue; - } - unit = dataInput.substring(iii); - break; + Pair parseLength2(String config) { + + Distance type = Distance.PIXEL; + if (config.endsWith("%")) { + type = Distance.POURCENT; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("px")) { + type = Distance.PIXEL; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ft")) { + type = Distance.FOOT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("in")) { + type = Distance.INCH; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("km")) { + type = Distance.KILOMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("mm")) { + type = Distance.MILLIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("cm")) { + type = Distance.CENTIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("m")) { + type = Distance.METER; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("em")) { + type = Distance.ELEMENT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ex")) { + type = Distance.EX; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pt")) { + type = Distance.POINT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pc")) { + type = Distance.PC; + config = config.substring(0, config.length() - 2); } - Log.verbose(" lenght : '" + n + "' => unit=" + unit); - // note : ";" is for the parsing of the style elements ... - if (unit.length() == 0) { - return new Pair<>(n, Distance.PIXEL); - } - if (unit.charAt(0) == '%') { // xxx % - return new Pair<>(n, Distance.POURCENT); - } - if (unit.charAt(0) == 'e' && unit.charAt(1) == 'm') { // xxx em - return new Pair<>(n, Distance.ELEMENT); - } - if (unit.charAt(0) == 'e' && unit.charAt(1) == 'x') { // xxx ex - return new Pair<>(n, Distance.EX); - } - if (unit.charAt(0) == 'p' && unit.charAt(1) == 'x') { // xxx px - return new Pair<>(n, Distance.PIXEL); - } - if (unit.charAt(0) == 'p' && unit.charAt(1) == 't') { // xxx pt - return new Pair<>(n, Distance.POINT); - } - if (unit.charAt(0) == 'p' && unit.charAt(1) == 'c') { // xxx pc - return new Pair<>(n, Distance.PC); - } - if (unit.charAt(0) == 'm' && unit.charAt(1) == 'm') { // xxx mm - return new Pair<>(n, Distance.MILLIMETER); - } - if (unit.charAt(0) == 'c' && unit.charAt(1) == 'm') { // xxx cm - return new Pair<>(n, Distance.CENTIMETER); - } - if (unit.charAt(0) == 'i' && unit.charAt(1) == 'n') { // xxx in - return new Pair<>(n, Distance.INCH); - } - return new Pair<>(0.0f, Distance.PIXEL); + final float tmp = Float.parseFloat(config); + return new Pair<>(tmp, type); } /** @@ -237,6 +235,7 @@ public class Base { } else { if (content.length() != 0) { this.paint.stroke = parseColor(content); + Log.error("Parse color : " + this.paint.stroke); } content = element.getAttribute("stroke-width", ""); if (content.length() != 0) { diff --git a/src/org/atriasoft/esvg/EsvgDocument.java b/src/org/atriasoft/esvg/EsvgDocument.java index c4f43fb..bd6a7f9 100644 --- a/src/org/atriasoft/esvg/EsvgDocument.java +++ b/src/org/atriasoft/esvg/EsvgDocument.java @@ -133,7 +133,7 @@ public class EsvgDocument extends Base { } public Base getReference(final String name) { - if (name == "") { + if (name.isEmpty()) { Log.error("request a reference with no name ... "); return null; } @@ -141,7 +141,7 @@ public class EsvgDocument extends Base { if (it == null) { continue; } - if (it.getId() == name) { + if (it.getId().equals(name)) { return it; } } diff --git a/src/org/atriasoft/esvg/Group.java b/src/org/atriasoft/esvg/Group.java index 1418a49..2ce780d 100644 --- a/src/org/atriasoft/esvg/Group.java +++ b/src/org/atriasoft/esvg/Group.java @@ -1,5 +1,6 @@ package org.atriasoft.esvg; +import java.util.ArrayList; import java.util.List; import org.atriasoft.esvg.internal.Log; @@ -15,7 +16,7 @@ import org.atriasoft.exml.model.XmlNode; * @license MPL v2.0 (see license file) */ public class Group extends Base { - private List subElementList; //!< sub elements ... + private final List subElementList = new ArrayList<>(); //!< sub elements ... public Group(final PaintState parentPaintState) { super(parentPaintState); @@ -25,7 +26,7 @@ public class Group extends Base { public void display(final int spacing) { Log.debug(spacingDist(spacing) + "Group (START) fill=" + this.paint.fill.first + "/" + this.paint.fill.second + " stroke=" + this.paint.stroke.first + "/" + this.paint.stroke.second + " stroke-width=" + this.paint.strokeWidth); - for (Base it : this.subElementList) { + for (final Base it : this.subElementList) { if (it != null) { it.display(spacing + 1); } diff --git a/src/org/atriasoft/esvg/LinearGradient.java b/src/org/atriasoft/esvg/LinearGradient.java index 2576a26..5cda7ed 100644 --- a/src/org/atriasoft/esvg/LinearGradient.java +++ b/src/org/atriasoft/esvg/LinearGradient.java @@ -50,7 +50,7 @@ public class LinearGradient extends Base { } public List> getColors(final EsvgDocument document) { - if (this.href == "") { + if (this.href.isEmpty()) { return this.data; } if (document == null) { @@ -99,16 +99,16 @@ public class LinearGradient extends Base { String contentX = element.getAttribute("x1", ""); String contentY = element.getAttribute("y1", ""); - if (contentX != "" && contentY != "") { - this.pos1 = new Dimension(new Vector2f(Float.parseFloat(contentX), Float.parseFloat(contentY))); + if (!contentX.isEmpty() && !contentY.isEmpty()) { + this.pos1 = Dimension.valueOf(contentX, contentY); } contentX = element.getAttribute("x2", ""); contentY = element.getAttribute("y2", ""); - if (contentX != "" && contentY != "") { - this.pos2 = new Dimension(new Vector2f(Float.parseFloat(contentX), Float.parseFloat(contentY))); + if (!contentX.isEmpty() && !contentY.isEmpty()) { + this.pos2 = Dimension.valueOf(contentX, contentY); } contentX = element.getAttribute("gradientUnits", ""); - if (contentX == "userSpaceOnUse") { + if (contentX.equals("userSpaceOnUse")) { this.unit = GradientUnits.gradientUnitsuserSpaceOnUse; } else { this.unit = GradientUnits.gradientUnitsobjectBoundingBox; @@ -117,13 +117,13 @@ public class LinearGradient extends Base { } } contentX = element.getAttribute("spreadMethod", ""); - if (contentX == "reflect") { + if (contentX.equals("reflect")) { this.spread = SpreadMethod.REFLECT; - } else if (contentX == "repeat") { + } else if (contentX.equals("repeat")) { this.spread = SpreadMethod.REPEAT; } else { this.spread = SpreadMethod.PAD; - if (contentX.length() != 0 && contentX != "pad") { + if (contentX.length() != 0 && !contentX.equals("pad")) { Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad"); } } @@ -135,7 +135,7 @@ public class LinearGradient extends Base { // parse all sub node : for (XmlNode it : element.getNodes()) { if (it instanceof XmlElement child) { - if (child.getValue() == "stop") { + if (child.getValue().equals("stop")) { float offset = 100; Color stopColor = Color.NONE; String content = child.getAttribute("offset", ""); @@ -169,7 +169,7 @@ public class LinearGradient extends Base { } } if (this.data.size() != 0) { - if (this.href != "") { + if (!this.href.isEmpty()) { Log.error(" node can not have an xlink:href element with sub node named: stop ==> removing href"); this.href = ""; } diff --git a/src/org/atriasoft/esvg/PaintState.java b/src/org/atriasoft/esvg/PaintState.java index 53cac1e..3fcd809 100644 --- a/src/org/atriasoft/esvg/PaintState.java +++ b/src/org/atriasoft/esvg/PaintState.java @@ -29,4 +29,20 @@ public class PaintState { this.miterLimit = 4.0f; this.opacity = 1.0f; } + + @Override + protected PaintState clone() { + PaintState out = new PaintState(); + out.fill = this.fill; + out.stroke = this.stroke; + out.strokeWidth = this.strokeWidth; + out.viewPort = this.viewPort; + out.flagEvenOdd = this.flagEvenOdd; + out.lineJoin = this.lineJoin; + out.lineCap = this.lineCap; + out.miterLimit = this.miterLimit; + out.opacity = this.opacity; + return out; + } + } diff --git a/src/org/atriasoft/esvg/Path.java b/src/org/atriasoft/esvg/Path.java index bd4319b..c54e817 100644 --- a/src/org/atriasoft/esvg/Path.java +++ b/src/org/atriasoft/esvg/Path.java @@ -12,6 +12,7 @@ import org.atriasoft.esvg.render.DynamicColor; import org.atriasoft.esvg.render.SegmentList; import org.atriasoft.etk.math.Matrix2x3f; import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector2i; import org.atriasoft.etk.util.Dynamic; import org.atriasoft.exml.model.XmlElement; import org.atriasoft.exml.parser.Tools; @@ -24,11 +25,11 @@ import org.atriasoft.exml.parser.Tools; public class Path extends Base { private record Command( char cmd, - float[] listDot, + String[] listElem, int offset) { - Command(final char cmd, final float[] listDot, final int offset) { + Command(final char cmd, final String[] listElem, final int offset) { this.cmd = cmd; - this.listDot = listDot; + this.listElem = listElem; this.offset = offset; } @@ -42,7 +43,7 @@ public class Path extends Base { StringBuilder out = new StringBuilder(input.length()); boolean haveSpace = false; for (char it : input.toCharArray()) { - if (it == ' ' || it == '\t' || it == '\t' || it == '\r') { + if (it == ' ' || it == '\t' || it == '\r') { haveSpace = true; } else { if (haveSpace) { @@ -56,52 +57,48 @@ public class Path extends Base { } //return the next char position ... (after 'X' or NULL) - private static Command extractCmd(final char[] input, final int offset) { - if (input[offset] == '\0') { + private static Command extractCmd(final List input, final int offset) { + if (input.size() <= offset) { + // Log.warning("parse command : END"); return null; } - char cmd = '\0'; - if (!((input[offset] <= 'Z' && input[offset] >= 'A') || (input[offset] <= 'z' && input[offset] >= 'a'))) { - Log.error("Error in the SVG Path : '" + input + "' [" + offset); + // Log.warning("parse command : (rest) " + offset); + // for (int iii = offset; iii < input.size(); iii++) { + // Log.warning(" -[" + iii + "] '" + input.get(iii) + "'"); + // } + if (input.get(offset).length() != 1) { + Log.error("Error in the SVG Path : '" + input.get(offset) + "' [" + offset); return null; } - cmd = input[0]; - Log.verbose("Find command : " + cmd); - if (input[offset + 1] == '\0') { + char cmd = input.get(offset).charAt(0); + if (!((cmd <= 'Z' && cmd >= 'A') || (cmd <= 'z' && cmd >= 'a'))) { + Log.error("Error in the SVG Path : '" + cmd + "' [" + offset); + return null; + } + //Log.verbose("Find command : " + cmd); + if (input.size() == offset) { return new Command(cmd, offset + 1); } - - StringBuilder tmpData = new StringBuilder(); - List elements = new ArrayList<>(); int iii; - for (iii = offset; iii < input.length; iii++) { - if (Tools.checkNumber(input[iii], iii == offset)) { - tmpData.append(input[iii]); - continue; + for (iii = offset + 1; iii < input.size(); iii++) { + char startElem = input.get(iii).charAt(0); + if ((startElem <= 'Z' && startElem >= 'A') || (startElem <= 'z' && startElem >= 'a')) { + // find end of elements + break; } - elements.add(tmpData.toString()); - tmpData.setLength(0); - if (input[iii] == ' ' || input[iii] == '\t' || input[iii] == '\n' || input[iii] == '\r' || input[iii] == ',' || input[iii] == ';') { - continue; - } - break; } - float[] outputList = new float[elements.size()]; - int jjj = 0; - for (String ekems : elements) { - outputList[jjj++] = Float.parseFloat(ekems); + int length = iii - (offset + 1); + if (length == 0) { + return new Command(cmd, null, iii + 1); } - // remove after white space... - for (; iii < input.length; iii++) { - if (input[iii] == ' ' || input[iii] == '\t' || input[iii] == '\n' || input[iii] == '\r') { - continue; - } - break; + String[] outputList = new String[length]; + for (int jjj = 0; jjj < length; jjj++) { + outputList[jjj] = input.get(offset + 1 + jjj); } - return new Command(cmd, outputList, offset + 1); + return new Command(cmd, outputList, iii); } - public PathModel listElement; + public PathModel listElement = new PathModel(); public Path(final PaintState parentPaintState) { super(parentPaintState); @@ -190,41 +187,47 @@ public class Path extends Base { return false; } Log.verbose("Parse Path : \"" + elementXML1 + "\""); - - float[] listDot = null; - elementXML1 = Path.cleanBadSpaces(elementXML1); - char[] elementXML = elementXML1.toCharArray(); + List commandsSplited = splitCommand(elementXML1); + String[] listDot = null; // TODO REWORK this, can be done with a simple split and search in a list... - for (Command sss = Path.extractCmd(elementXML, 0); sss != null; sss = Path.extractCmd(elementXML, sss.offset())) { + for (Command sss = Path.extractCmd(commandsSplited, 0); sss != null; sss = Path.extractCmd(commandsSplited, sss.offset())) { boolean relative = false; - listDot = sss.listDot(); + listDot = sss.listElem(); + + Log.error("Find new command : '" + sss.cmd + "'"); + if (listDot != null) { + for (int jjj = 0; jjj < listDot.length; jjj++) { + Log.error(" -> '" + listDot[jjj] + "'"); + } + } else { + Log.error(" -> no elements"); + } switch (sss.cmd) { case 'm': // Move to (relative) relative = true; case 'M': // Move to (absolute) - // 2 Elements ... - if (listDot.length % 2 != 0) { - Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); break; } - if (listDot.length >= 2) { - this.listElement.moveTo(relative, new Vector2f(listDot[0], listDot[1])); + // 2 Elements ... + if (listDot.length >= 1) { + this.listElement.moveTo(relative, Vector2f.valueOf(listDot[0])); } - for (int iii = 2; iii < listDot.length; iii += 2) { - this.listElement.lineTo(relative, new Vector2f(listDot[iii], listDot[iii + 1])); + for (int iii = 1; iii < listDot.length; iii++) { + this.listElement.lineTo(relative, Vector2f.valueOf(listDot[iii])); } break; case 'l': // Line to (relative) relative = true; case 'L': // Line to (absolute) - // 2 Elements ... - if (listDot.length % 2 != 0) { - Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); break; } - for (int iii = 0; iii < listDot.length; iii += 2) { - this.listElement.lineTo(relative, new Vector2f(listDot[iii], listDot[iii + 1])); + for (int iii = 0; iii < listDot.length; iii++) { + this.listElement.lineTo(relative, Vector2f.valueOf(listDot[iii])); } break; @@ -232,12 +235,12 @@ public class Path extends Base { relative = true; case 'V': // Vertical Line to (absolute) // 1 Element ... - if (listDot.length == 0) { - Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); break; } - for (int iii = 0; iii < listDot.length; iii += 1) { - this.listElement.lineToV(relative, listDot[iii]); + for (int iii = 0; iii < listDot.length; iii++) { + this.listElement.lineToV(relative, Float.parseFloat(listDot[iii])); } break; @@ -245,25 +248,29 @@ public class Path extends Base { relative = true; case 'H': // Horizantal Line to (absolute) // 1 Element ... - if (listDot.length == 0) { - Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); break; } - for (int iii = 0; iii < listDot.length; iii += 1) { - this.listElement.lineToH(relative, listDot[iii]); + for (int iii = 0; iii < listDot.length; iii++) { + this.listElement.lineToH(relative, Float.parseFloat(listDot[iii])); } break; case 'q': // Quadratic Bezier curve (relative) relative = true; case 'Q': // Quadratic Bezier curve (absolute) + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); + break; + } // 4 Elements ... - if (listDot.length % 4 != 0) { + if (listDot.length % 2 != 0) { Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); break; } - for (int iii = 0; iii < listDot.length; iii += 4) { - this.listElement.bezierCurveTo(relative, new Vector2f(listDot[iii], listDot[iii + 1]), new Vector2f(listDot[iii + 2], listDot[iii + 3])); + for (int iii = 0; iii < listDot.length; iii += 2) { + this.listElement.bezierCurveTo(relative, Vector2f.valueOf(listDot[iii]), Vector2f.valueOf(listDot[iii + 1])); } break; @@ -271,68 +278,75 @@ public class Path extends Base { relative = true; case 'T': // smooth quadratic Bezier curve to (absolute) // 2 Elements ... - if (listDot.length % 2 != 0) { - Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); - break; - } - for (int iii = 0; iii < listDot.length; iii += 2) { - this.listElement.bezierSmoothCurveTo(relative, new Vector2f(listDot[iii], listDot[iii + 1])); + for (int iii = 0; iii < listDot.length; iii++) { + this.listElement.bezierSmoothCurveTo(relative, Vector2f.valueOf(listDot[iii])); } break; case 'c': // curve to (relative) relative = true; case 'C': // curve to (absolute) + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); + break; + } // 6 Elements ... - if (listDot.length % 6 != 0) { + if (listDot.length % 3 != 0) { Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); break; } - for (int iii = 0; iii < listDot.length; iii += 6) { - this.listElement.curveTo(relative, new Vector2f(listDot[iii], listDot[iii + 1]), new Vector2f(listDot[iii + 2], listDot[iii + 3]), - new Vector2f(listDot[iii + 4], listDot[iii + 5])); + for (int iii = 0; iii < listDot.length; iii += 3) { + this.listElement.curveTo(relative, Vector2f.valueOf(listDot[iii]), Vector2f.valueOf(listDot[iii + 1]), Vector2f.valueOf(listDot[iii + 2])); } break; case 's': // smooth curve to (relative) relative = true; case 'S': // smooth curve to (absolute) + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); + break; + } // 4 Elements ... - if (listDot.length % 4 != 0) { + if (listDot.length % 2 != 0) { Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); break; } - for (int iii = 0; iii < listDot.length; iii += 4) { - this.listElement.smoothCurveTo(relative, new Vector2f(listDot[iii], listDot[iii + 1]), new Vector2f(listDot[iii + 2], listDot[iii + 3])); + for (int iii = 0; iii < listDot.length; iii += 2) { + this.listElement.smoothCurveTo(relative, Vector2f.valueOf(listDot[iii]), Vector2f.valueOf(listDot[iii + 1])); } break; case 'a': // elliptical Arc (relative) relative = true; case 'A': // elliptical Arc (absolute) - // 7 Elements ... - if (listDot.length % 7 != 0) { + if (listDot == null) { + Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot); + break; + } + // 4 element ff,ff f i,i ff,ff Elements ... + if (listDot.length % 4 != 0) { Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); break; } for (int iii = 0; iii < listDot.length; iii += 7) { boolean largeArcFlag = true; boolean sweepFlag = true; - if (listDot[iii + 3] == 0.0f) { + Vector2i tmp = Vector2i.valueOf(listDot[iii + 2]); + if (tmp.x() == 0) { largeArcFlag = false; } - if (listDot[iii + 4] == 0.0f) { + if (tmp.y() == 0) { sweepFlag = false; } - this.listElement.ellipticTo(relative, new Vector2f(listDot[iii], listDot[iii + 1]), listDot[iii + 2], largeArcFlag, sweepFlag, - new Vector2f(listDot[iii + 5], listDot[iii + 6])); + this.listElement.ellipticTo(relative, Vector2f.valueOf(listDot[iii]), Float.parseFloat(listDot[iii + 1]), largeArcFlag, sweepFlag, Vector2f.valueOf(listDot[iii + 3])); } break; case 'z': // closepath (relative) relative = true; case 'Z': // closepath (absolute) // 0 Element ... - if (listDot.length != 0) { + if (listDot != null) { Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length); break; } @@ -346,4 +360,45 @@ public class Path extends Base { return true; } + List splitCommand(final String data) { + List out = new ArrayList<>(); + StringBuilder tmpString = new StringBuilder(20); + boolean isText = false; + boolean isNumber = false; + for (char it : data.toCharArray()) { + if (it == ' ' || it == '\t' || it == '\r') { + String elements = tmpString.toString(); + if (!elements.isEmpty()) { + out.add(elements); + } + tmpString.setLength(0); + isText = false; + isNumber = false; + } else if (Tools.checkNumber(it, true) || it == ',' || it == '.') { + if (isText) { + out.add(tmpString.toString()); + tmpString.setLength(0); + } + isText = false; + isNumber = true; + tmpString.append(it); + } else if ((it <= 'Z' && it >= 'A') || (it <= 'z' && it >= 'a')) { + if (isNumber) { + out.add(tmpString.toString()); + tmpString.setLength(0); + } + isText = true; + isNumber = false; + tmpString.append(it); + } else { + Log.error("Can not parse path : '" + it + "'"); + } + } + String elements = tmpString.toString(); + if (!elements.isEmpty()) { + out.add(elements); + } + return out; + } + } diff --git a/src/org/atriasoft/esvg/Polygon.java b/src/org/atriasoft/esvg/Polygon.java index 9ed3ebd..f0f2524 100644 --- a/src/org/atriasoft/esvg/Polygon.java +++ b/src/org/atriasoft/esvg/Polygon.java @@ -23,7 +23,7 @@ import org.atriasoft.esvg.internal.Log; */ public class Polygon extends Base { - private List listPoint; //!< list of all point of the polygone + private final List listPoint = new ArrayList<>(); //!< list of all point of the polygone public Polygon(final PaintState parentPaintState) { super(parentPaintState); diff --git a/src/org/atriasoft/esvg/RadialGradient.java b/src/org/atriasoft/esvg/RadialGradient.java index 2a6de19..2bf7260 100644 --- a/src/org/atriasoft/esvg/RadialGradient.java +++ b/src/org/atriasoft/esvg/RadialGradient.java @@ -52,7 +52,7 @@ public class RadialGradient extends Base { } public List> getColors(final EsvgDocument document) { - if (this.href == "") { + if (this.href.isEmpty()) { return this.data; } if (document == null) { @@ -100,20 +100,20 @@ public class RadialGradient extends Base { String contentX = element.getAttribute("cx", ""); String contentY = element.getAttribute("cy", ""); - if (contentX != "" && contentY != "") { - this.center = new Dimension(new Vector2f(Float.parseFloat(contentX), Float.parseFloat(contentY))); + if (!contentX.isEmpty() && !contentY.isEmpty()) { + this.center = Dimension.valueOf(contentX, contentY); } contentX = element.getAttribute("r", ""); if (contentX != "") { - this.radius = new Dimension1D(Float.parseFloat(contentX)); + this.radius = Dimension1D.valueOf(contentX); } contentX = element.getAttribute("fx", ""); contentY = element.getAttribute("fy", ""); - if (contentX != "" && contentY != "") { - this.focal = new Dimension(new Vector2f(Float.parseFloat(contentX), Float.parseFloat(contentY))); + if (!contentX.isEmpty() && !contentY.isEmpty()) { + this.focal = Dimension.valueOf(contentX, contentY); } contentX = element.getAttribute("gradientUnits", ""); - if (contentX == "userSpaceOnUse") { + if (contentX.equals("userSpaceOnUse")) { this.unit = GradientUnits.gradientUnitsuserSpaceOnUse; } else { this.unit = GradientUnits.gradientUnitsobjectBoundingBox; @@ -122,13 +122,13 @@ public class RadialGradient extends Base { } } contentX = element.getAttribute("spreadMethod", ""); - if (contentX == "reflect") { + if (contentX.equals("reflect")) { this.spread = SpreadMethod.REFLECT; - } else if (contentX == "repeat") { + } else if (contentX.equals("repeat")) { this.spread = SpreadMethod.REPEAT; } else { this.spread = SpreadMethod.PAD; - if (contentX.length() != 0 && contentX != "pad") { + if (contentX.length() != 0 && !contentX.equals("pad")) { Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad"); } } @@ -140,7 +140,7 @@ public class RadialGradient extends Base { // parse all sub node : for (XmlNode it : element.getNodes()) { if (it instanceof XmlElement child) { - if (child.getValue() == "stop") { + if (child.getValue().equals("stop")) { float offset = 100; Color stopColor = Color.NONE; String content = child.getAttribute("offset", ""); @@ -174,7 +174,7 @@ public class RadialGradient extends Base { } } if (this.data.size() != 0) { - if (this.href != "") { + if (!this.href.isEmpty()) { Log.error("node can not have an xlink:href element with sub node named: stop ==> removing href"); this.href = ""; } diff --git a/src/org/atriasoft/esvg/Renderer.java b/src/org/atriasoft/esvg/Renderer.java index 4c18c54..abb3341 100644 --- a/src/org/atriasoft/esvg/Renderer.java +++ b/src/org/atriasoft/esvg/Renderer.java @@ -22,7 +22,7 @@ import org.atriasoft.etk.util.ArraysTools; */ public class Renderer { - private static final boolean DEBUG_MODE = true; + private static final boolean DEBUG_MODE = false; protected Color[][] buffer; // for debug protected EsvgDocument document; // for debug @@ -205,8 +205,8 @@ public class Renderer { Color intermediateColor = mergeColor(intermediateColorFill, intermediateColorStroke); intermediateColor = intermediateColor.withA(intermediateColor.a() * opacity); if (Renderer.DEBUG_MODE) { - for (int deltaY = 0; deltaY < this.factor; ++deltaY) { - for (int deltaX = 0; deltaX < this.factor; ++deltaX) { + for (int deltaY = 0; deltaY < this.factor; deltaY++) { + for (int deltaX = 0; deltaX < this.factor; deltaX++) { int idx = xxx * this.factor + deltaX; int idy = yyy * this.factor + deltaY; this.buffer[idy][idx] = mergeColor(this.buffer[idy][idx], intermediateColor); @@ -257,9 +257,9 @@ public class Renderer { public void setSize(final Vector2i size) { this.size = size; if (Renderer.DEBUG_MODE) { - this.buffer = new Color[this.size.x()][this.size.y()]; + this.buffer = new Color[this.size.y()][this.size.x()]; } else { - this.buffer = new Color[this.size.x() * this.factor][this.size.y() * this.factor]; + this.buffer = new Color[this.size.y() * this.factor][this.size.x() * this.factor]; } ArraysTools.fill2(this.buffer, Color.NONE); } diff --git a/src/org/atriasoft/esvg/render/DynamicColor.java b/src/org/atriasoft/esvg/render/DynamicColor.java index 429c088..8b4f440 100644 --- a/src/org/atriasoft/esvg/render/DynamicColor.java +++ b/src/org/atriasoft/esvg/render/DynamicColor.java @@ -5,6 +5,7 @@ import org.atriasoft.etk.util.Pair; import org.atriasoft.etk.math.Matrix2x3f; import org.atriasoft.etk.math.Vector2f; import org.atriasoft.esvg.EsvgDocument; +import org.atriasoft.esvg.internal.Log; import org.atriasoft.etk.Color; /** @file @@ -20,6 +21,7 @@ public interface DynamicColor { return null; } if (color.second.isEmpty()) { + Log.error("use stroke color :" + color); return new DynamicColorUni(color.first); } return new DynamicColorSpecial(color.second, mtx); diff --git a/src/org/atriasoft/esvg/render/DynamicColorSpecial.java b/src/org/atriasoft/esvg/render/DynamicColorSpecial.java index e827740..2683f6a 100644 --- a/src/org/atriasoft/esvg/render/DynamicColorSpecial.java +++ b/src/org/atriasoft/esvg/render/DynamicColorSpecial.java @@ -65,7 +65,7 @@ public class DynamicColorSpecial implements DynamicColor { distToIntersection = FMath.sqrt(radius * radius - distToCenter * distToCenter); } // normalize... - v1.safeNormalize(); + v1 = v1.safeNormalize(); v1 = v1.multiply(distToIntersection); return new Pair<>(midpt.add(v1), midpt.less(v1)); } @@ -396,7 +396,7 @@ public class DynamicColorSpecial implements DynamicColor { // nothing to do ... break; case REFLECT: - ratio -= ((int) (ratio) >> 1) + 1; + ratio -= (((int) (ratio)) >> 1) + 1; if (ratio > 1.0f) { ratio = 2.0f - ratio; } diff --git a/src/org/atriasoft/esvg/render/PathModel.java b/src/org/atriasoft/esvg/render/PathModel.java index 0f14ad1..6b42bb8 100644 --- a/src/org/atriasoft/esvg/render/PathModel.java +++ b/src/org/atriasoft/esvg/render/PathModel.java @@ -149,8 +149,8 @@ public class PathModel { // Remove the last point if it is the same position... Vector2f delta = (tmpListPoint.get(0).pos.less(tmpListPoint.get(tmpListPoint.size() - 1).pos)).abs(); if (delta.x() <= 0.00001 && delta.y() <= 0.00001) { - tmpListPoint.remove(tmpListPoint.size() - 1); Log.verbose(" Remove point Z property : " + tmpListPoint.get(tmpListPoint.size() - 1).pos + " with delta=" + delta); + tmpListPoint.remove(tmpListPoint.size() - 1); } out.addList(tmpListPoint); tmpListPoint = new ArrayList<>(); diff --git a/src/org/atriasoft/esvg/render/SegmentList.java b/src/org/atriasoft/esvg/render/SegmentList.java index 9a0e3c1..431df19 100644 --- a/src/org/atriasoft/esvg/render/SegmentList.java +++ b/src/org/atriasoft/esvg/render/SegmentList.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.util.Dynamic; import org.atriasoft.etk.util.Pair; import org.atriasoft.etk.math.FMath; import org.atriasoft.etk.math.Matrix2x3f; @@ -50,8 +51,10 @@ public class SegmentList { this.data.add(new Segment(pos0.pos, pos1.pos)); } - // TODO is it really needed... void addSegment(final Vector2f pos0, final Vector2f pos1) { + if (pos0.y() == pos1.y()) { + return; + } this.data.add(new Segment(pos0, pos1)); } @@ -77,7 +80,7 @@ public class SegmentList { // normal edge * end path // (mitter) * | * * * * * * * * * * * * * * // * |<--*----this | * - // * | * this -.| * + // * | * this -->| * // * * * | * // * . | . * . . . . . . . . * * // * . | . * | * @@ -103,32 +106,32 @@ public class SegmentList { //Log.debug("JOIN : val : prev/curr/next : " + itListPoint.get(idPevious).pos + "/" + itListPoint.get(idCurrent).pos + "/" + itListPoint.get(idNext).pos); Vector2f vecA = itListPoint.get(idCurrent).pos.less(itListPoint.get(idPevious).pos); //Log.debug("JOIN : vecA : " + vecA); - vecA.safeNormalize(); + vecA = vecA.safeNormalize(); Vector2f vecB = itListPoint.get(idNext).pos.less(itListPoint.get(idCurrent).pos); //Log.debug("JOIN : vecB : " + vecB); - vecB.safeNormalize(); + vecB = vecB.safeNormalize(); Vector2f vecC = vecA.less(vecB); //Log.debug("JOIN : vecC : " + vecC); if (vecC.isZero()) { // special case: 1 line ... itListPoint.get(idCurrent).miterAxe = new Vector2f(vecA.y(), vecA.x()); } else { - vecC.safeNormalize(); + vecC = vecC.safeNormalize(); itListPoint.get(idCurrent).miterAxe = vecC; } itListPoint.get(idCurrent).posPrevious = itListPoint.get(idPevious).pos; itListPoint.get(idCurrent).posNext = itListPoint.get(idNext).pos; vecB = itListPoint.get(idNext).pos.less(itListPoint.get(idCurrent).pos); - vecB.safeNormalize(); + vecB = vecB.safeNormalize(); itListPoint.get(idCurrent).orthoAxeNext = new Vector2f(vecB.y(), -vecB.x()); vecB = itListPoint.get(idCurrent).pos.less(itListPoint.get(idPevious).pos); - vecB.safeNormalize(); + vecB = vecB.safeNormalize(); itListPoint.get(idCurrent).orthoAxePrevious = new Vector2f(vecB.y(), -vecB.x()); //Log.debug("JOIN : miterAxe " + itListPoint.get(idCurrent).miterAxe); } else if (itListPoint.get(idCurrent).type == PointType.start) { itListPoint.get(idCurrent).posNext = itListPoint.get(idNext).pos; Vector2f vecB = itListPoint.get(idNext).pos.less(itListPoint.get(idCurrent).pos); - vecB.safeNormalize(); + vecB = vecB.safeNormalize(); itListPoint.get(idCurrent).miterAxe = new Vector2f(vecB.y(), -vecB.x()); itListPoint.get(idCurrent).orthoAxePrevious = itListPoint.get(idCurrent).miterAxe; itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe; @@ -139,7 +142,7 @@ public class SegmentList { } itListPoint.get(idCurrent).posPrevious = itListPoint.get(idPevious).pos; Vector2f vecA = itListPoint.get(idCurrent).pos.less(itListPoint.get(idPevious).pos); - vecA.safeNormalize(); + vecA = vecA.safeNormalize(); itListPoint.get(idCurrent).miterAxe = new Vector2f(vecA.y(), -vecA.x()); itListPoint.get(idCurrent).orthoAxePrevious = itListPoint.get(idCurrent).miterAxe; itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe; @@ -150,35 +153,35 @@ public class SegmentList { // create segment list: boolean haveStartLine = false; - Vector2f leftPoint = Vector2f.ZERO; + Dynamic leftPoint = new Dynamic(Vector2f.ZERO); - Vector2f rightPoint = Vector2f.ZERO; + Dynamic rightPoint = new Dynamic(Vector2f.ZERO); if (itListPoint.size() > 0) { if (itListPoint.get(0).type == PointType.join) { Point it = itListPoint.get(itListPoint.size() - 1); - // Calculate the perpendiculary axis ... - leftPoint = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f)); - rightPoint = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f)); + // Calculate the perpendicular axis ... + leftPoint.value = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f)); + rightPoint.value = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f)); // cyclic path... if (it.type == PointType.interpolation) { - leftPoint = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - rightPoint = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + leftPoint.value = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + rightPoint.value = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); } else if (it.type == PointType.join) { - // Calculate the perpendiculary axis ... - leftPoint = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f)); - rightPoint = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f)); + // Calculate the perpendicular axis ... + leftPoint.value = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f)); + rightPoint.value = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f)); // project on the miter Axis ... switch (join) { case MITER: { - Vector2f left = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - Vector2f right = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f left = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f right = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); // Check the miter limit: float limitRight = (left.less(it.pos)).length() / width * 2.0f; float limitLeft = (right.less(it.pos)).length() / width * 2.0f; Log.verbose(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit); if (limitRight <= miterLimit && limitLeft <= miterLimit) { - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; break; } } @@ -188,11 +191,11 @@ public class SegmentList { Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize(); float cross = axePrevious.cross(axeNext); if (cross > 0.0f) { - rightPoint = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - leftPoint = it.pos.add(it.orthoAxeNext.multiply(width * 0.5f)); + rightPoint.value = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + leftPoint.value = it.pos.add(it.orthoAxeNext.multiply(width * 0.5f)); } else { - leftPoint = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - rightPoint = it.pos.less(it.orthoAxeNext.multiply(width * 0.5f)); + leftPoint.value = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + rightPoint.value = it.pos.less(it.orthoAxeNext.multiply(width * 0.5f)); } break; } @@ -215,7 +218,7 @@ public class SegmentList { if (haveStartLine) { // close previous : Log.warning(" find a non close path ..."); - addSegment(leftPoint, rightPoint); + addSegment(leftPoint.value, rightPoint.value); } haveStartLine = true; startStopPoint(leftPoint, rightPoint, it, cap, width, true); @@ -231,35 +234,35 @@ public class SegmentList { break; case interpolation: { Log.verbose("Find interpolation " + it.pos); - Vector2f left = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - Vector2f right = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f left = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f right = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); //Draw from previous point: - addSegment(leftPoint, left); + addSegment(leftPoint.value, left); Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right, rightPoint); + addSegment(right, rightPoint.value); Log.verbose(" segment :" + right + " . " + rightPoint); - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; } break; case join: Log.verbose("Find join " + it.pos); switch (join) { case MITER: { - Vector2f left = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); - Vector2f right = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f left = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f right = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); // Check the miter limit: float limitRight = left.less(it.pos).length() / width * 2.0f; float limitLeft = right.less(it.pos).length() / width * 2.0f; Log.verbose(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit); if (limitRight <= miterLimit && limitLeft <= miterLimit) { //Draw from previous point: - addSegment(leftPoint, left); + addSegment(leftPoint.value, left); Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right, rightPoint); + addSegment(right, rightPoint.value); Log.verbose(" segment :" + right + " . " + rightPoint); - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; break; } Log.verbose(" Find miter Limit ... ==> create BEVEL"); @@ -270,11 +273,11 @@ public class SegmentList { Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize(); float cross = axePrevious.cross(axeNext); if (cross > 0.0f) { - Vector2f right = SegmentList.getIntersect(rightPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f right = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); Vector2f left1 = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f)); Vector2f left2 = it.pos.add(it.orthoAxeNext.multiply(width * 0.5f)); //Draw from previous point: - addSegment(leftPoint, left1); + addSegment(leftPoint.value, left1); Log.verbose(" segment :" + leftPoint + " . " + left1); if (join != JoinMode.ROUND) { // Miter and bevel: @@ -283,18 +286,18 @@ public class SegmentList { } else { createSegmentListStroke(left1, left2, it.pos, width, false); } - addSegment(right, rightPoint); + addSegment(right, rightPoint.value); Log.verbose(" segment :" + right + " . " + rightPoint); - leftPoint = left2; - rightPoint = right; + leftPoint.value = left2; + rightPoint.value = right; } else { - Vector2f left = SegmentList.getIntersect(leftPoint, it.pos.less(it.posPrevious), it.pos, it.miterAxe); + Vector2f left = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious), it.pos, it.miterAxe); Vector2f right1 = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f)); Vector2f right2 = it.pos.less(it.orthoAxeNext.multiply(width * 0.5f)); //Draw from previous point: - addSegment(leftPoint, left); + addSegment(leftPoint.value, left); Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right1, rightPoint); + addSegment(right1, rightPoint.value); Log.verbose(" segment :" + right1 + " . " + rightPoint); if (join != JoinMode.ROUND) { // Miter and bevel: @@ -303,8 +306,8 @@ public class SegmentList { } else { createSegmentListStroke(right1, right2, it.pos, width, true); } - leftPoint = left; - rightPoint = right2; + leftPoint.value = left; + rightPoint.value = right2; } } break; @@ -369,26 +372,26 @@ public class SegmentList { return out; } - private void startStopPoint(Vector2f leftPoint, Vector2f rightPoint, final Point point, final CapMode cap, final float width, final boolean isStart) { + private void startStopPoint(final Dynamic leftPoint, final Dynamic rightPoint, final Point point, final CapMode cap, final float width, final boolean isStart) { switch (cap) { case BUTT: { Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f)); Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f)); if (!isStart) { //Draw from previous point: - addSegment(leftPoint, left); + addSegment(leftPoint.value, left); Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right, rightPoint); + addSegment(right, rightPoint.value); Log.verbose(" segment :" + right + " . " + rightPoint); } - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; } if (!isStart) { - addSegment(leftPoint, rightPoint); + addSegment(leftPoint.value, rightPoint.value); Log.verbose(" segment :" + leftPoint + " . " + rightPoint); } else { - addSegment(rightPoint, leftPoint); + addSegment(rightPoint.value, leftPoint.value); Log.verbose(" segment :" + rightPoint + " . " + leftPoint); } break; @@ -398,21 +401,21 @@ public class SegmentList { Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f)); if (!isStart) { //Draw from previous point: - addSegment(leftPoint, left); + addSegment(leftPoint.value, left); Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right, rightPoint); + addSegment(right, rightPoint.value); Log.verbose(" segment :" + right + " . " + rightPoint); } - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; } int nbDot = (int) width; if (nbDot <= 2) { nbDot = 2; } - leftPoint = point.pos.add(point.miterAxe.multiply(width * 0.5f)); - rightPoint = point.pos.less(point.miterAxe.multiply(width * 0.5f)); - createSegmentListStroke(leftPoint, rightPoint, point.pos, width, isStart); + leftPoint.value = point.pos.add(point.miterAxe.multiply(width * 0.5f)); + rightPoint.value = point.pos.less(point.miterAxe.multiply(width * 0.5f)); + createSegmentListStroke(leftPoint.value, rightPoint.value, point.pos, width, isStart); } break; case SQUARE: { @@ -428,21 +431,19 @@ public class SegmentList { left = tmpMat.multiply(left); right = tmpMat.multiply(right); if (!isStart) { - if (!isStart) { - //Draw from previous point: - addSegment(leftPoint, left); - Log.verbose(" segment :" + leftPoint + " . " + left); - addSegment(right, rightPoint); - Log.verbose(" segment :" + right + " . " + rightPoint); - } + //Draw from previous point: + addSegment(leftPoint.value, left); + Log.verbose(" segment :" + leftPoint + " . " + left); + addSegment(right, rightPoint.value); + Log.verbose(" segment :" + right + " . " + rightPoint); } - leftPoint = left; - rightPoint = right; + leftPoint.value = left; + rightPoint.value = right; if (!isStart) { - addSegment(leftPoint, rightPoint); + addSegment(leftPoint.value, rightPoint.value); Log.verbose(" segment :" + leftPoint + " . " + rightPoint); } else { - addSegment(rightPoint, leftPoint); + addSegment(rightPoint.value, leftPoint.value); Log.verbose(" segment :" + rightPoint + " . " + leftPoint); } Log.verbose(" segment :" + leftPoint + " . " + rightPoint); diff --git a/test/src/test/atriasoft/esvg/ConfigTest.java b/test/src/test/atriasoft/esvg/ConfigTest.java index b8b8e61..966198e 100644 --- a/test/src/test/atriasoft/esvg/ConfigTest.java +++ b/test/src/test/atriasoft/esvg/ConfigTest.java @@ -10,11 +10,14 @@ import org.atriasoft.etk.Uri; import com.pngencoder.PngEncoder; public class ConfigTest { - public static final String BASE_PATH = "./";//"~/dev/workspace-game/atriasoft/esvg/"; + public static final String BASE_PATH = "./testResult/";//"~/dev/workspace-game/atriasoft/esvg/"; public static final boolean VISUAL_DEBUG = true; public static void generateAnImage(final EsvgDocument doc, final Uri uri) { Color[][] data = doc.renderImageFloatRGBA(null, ConfigTest.VISUAL_DEBUG); + if (data.length == 0) { + Log.critical("No data generated ..."); + } BufferedImage bufferedImage = new BufferedImage(data[0].length, data.length, BufferedImage.TYPE_INT_ARGB); for (int yyy = 0; yyy < data.length; yyy++) { for (int xxx = 0; xxx < data[yyy].length; xxx++) { diff --git a/test/src/test/atriasoft/esvg/TestGradientLinear.java b/test/src/test/atriasoft/esvg/TestGradientLinear.java index 8547f9c..5c79c31 100644 --- a/test/src/test/atriasoft/esvg/TestGradientLinear.java +++ b/test/src/test/atriasoft/esvg/TestGradientLinear.java @@ -7,11 +7,20 @@ import org.junit.jupiter.api.Test; class TestGradientLinear { @Test public void testTestGradientLinearDiag1() { - String data = "\n" + "\n" + " \n" - + " \n" + " \n" - + " \n" + " \n" - + " \n" + " \n" + " \n" - + " \n" + "\n"; + //@formatter:off + String data = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on EsvgDocument doc = new EsvgDocument(); doc.parse(data); Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1.svg"), data.replace("'", "\"")); @@ -20,10 +29,18 @@ class TestGradientLinear { @Test public void testTestGradientLinearDiag1Partiel() { - String data = "\n" + "\n" + " \n" - + " \n" + " \n" - + " \n" + " \n" + " \n" - + " \n" + "\n"; + //@formatter:off + String data = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on EsvgDocument doc = new EsvgDocument(); doc.parse(data); Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1Partiel.svg"), data.replace("'", "\"")); @@ -97,11 +114,20 @@ class TestGradientLinear { @Test public void testTestGradientLinearHorizontal() { - String data = "\n" + "\n" + " \n" - + " \n" + " \n" - + " \n" + " \n" - + " \n" + " \n" + " \n" - + " \n" + "\n"; + //@formatter:off + String data = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + //@formatter:on EsvgDocument doc = new EsvgDocument(); doc.parse(data); Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.svg"), data.replace("'", "\"")); diff --git a/test/src/test/atriasoft/esvg/TestStyle.java b/test/src/test/atriasoft/esvg/TestStyle.java index 9f18ad3..9e36cf7 100644 --- a/test/src/test/atriasoft/esvg/TestStyle.java +++ b/test/src/test/atriasoft/esvg/TestStyle.java @@ -2,10 +2,9 @@ package test.atriasoft.esvg; import org.atriasoft.esvg.EsvgDocument; import org.atriasoft.etk.Uri; -import org.junit.jupiter.api.Test; class TestStyle { - @Test + public void testTestExternWorddown() { String data = "\n" + "