[DEBUG] generation is opk, except the gradiant reflect that have some errors.
This commit is contained in:
parent
9a8e73d883
commit
fb91ff5cbf
@ -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<Color, String> 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<Float, Distance> 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<Float, Distance> 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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Base> subElementList; //!< sub elements ...
|
||||
private final List<Base> 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);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class LinearGradient extends Base {
|
||||
}
|
||||
|
||||
public List<Pair<Float, Color>> 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 = "";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<String> 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<String> 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<String> 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<String> splitCommand(final String data) {
|
||||
List<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import org.atriasoft.esvg.internal.Log;
|
||||
*/
|
||||
|
||||
public class Polygon extends Base {
|
||||
private List<Vector2f> listPoint; //!< list of all point of the polygone
|
||||
private final List<Vector2f> listPoint = new ArrayList<>(); //!< list of all point of the polygone
|
||||
|
||||
public Polygon(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
|
@ -52,7 +52,7 @@ public class RadialGradient extends Base {
|
||||
}
|
||||
|
||||
public List<Pair<Float, Color>> 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 = "";
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<>();
|
||||
|
@ -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<Vector2f> leftPoint = new Dynamic<Vector2f>(Vector2f.ZERO);
|
||||
|
||||
Vector2f rightPoint = Vector2f.ZERO;
|
||||
Dynamic<Vector2f> rightPoint = new Dynamic<Vector2f>(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<Vector2f> leftPoint, final Dynamic<Vector2f> 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);
|
||||
|
@ -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++) {
|
||||
|
@ -7,11 +7,20 @@ import org.junit.jupiter.api.Test;
|
||||
class TestGradientLinear {
|
||||
@Test
|
||||
public void testTestGradientLinearDiag1() {
|
||||
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
|
||||
+ " <linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='100%'>\n" + " <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n" + " </linearGradient>\n" + " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
|
||||
//@formatter:off
|
||||
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
+ "<svg height='100' width='100'>\n"
|
||||
+ " <defs>\n"
|
||||
+ " <linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='100%'>\n"
|
||||
+ " <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
+ " </linearGradient>\n"
|
||||
+ " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
+ "</svg>\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 = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
|
||||
+ " <linearGradient id='grad2' x1='40%' y1='40%' x2='70%' y2='70%'>\n" + " <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n" + " </linearGradient>\n" + " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
|
||||
//@formatter:off
|
||||
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
+ "<svg height='100' width='100'>\n"
|
||||
+ " <defs>\n"
|
||||
+ " <linearGradient id='grad2' x1='40%' y1='40%' x2='70%' y2='70%'>\n"
|
||||
+ " <stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
+ " </linearGradient>\n"
|
||||
+ " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n"
|
||||
+ "</svg>\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 = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
|
||||
+ " <linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'>\n" + " <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n" + " </linearGradient>\n" + " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
|
||||
//@formatter:off
|
||||
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
|
||||
+ "<svg height='100' width='100'>\n"
|
||||
+ " <defs>\n"
|
||||
+ " <linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'>\n"
|
||||
+ " <stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />\n"
|
||||
+ " <stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />\n"
|
||||
+ " <stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />\n"
|
||||
+ " </linearGradient>\n"
|
||||
+ " </defs>\n"
|
||||
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n"
|
||||
+ "</svg>\n";
|
||||
//@formatter:on
|
||||
EsvgDocument doc = new EsvgDocument();
|
||||
doc.parse(data);
|
||||
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.svg"), data.replace("'", "\""));
|
||||
|
@ -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 = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<!-- Created with Inkscape (http://www.inkscape.org/) -.\n" + "\n" + "<svg\n"
|
||||
+ " xmlns:dc='http://purl.org/dc/elements/1.1/'\n" + " xmlns:cc='http://creativecommons.org/ns#'\n" + " xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user