Compare commits

..

No commits in common. "dev" and "main" have entirely different histories.
dev ... main

92 changed files with 2639 additions and 3449 deletions

51
.classpath Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="resources"/>
<classpathentry including="**/*.java" kind="src" output="out/eclipse/classes-test" path="test/src">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/atriasoft-etk">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/scenarium-logger">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/atriasoft-exml">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/atriasoft-egami">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/atriasoft-png-encoder">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="out/eclipse/classes"/>
</classpath>

3
.gitignore vendored
View File

@ -1,5 +1,3 @@
/__pycache__/
/bin/
/Operator/
/DrawerProperties/
@ -17,4 +15,3 @@ build.number
/.settings/
/junit/
/target/
/testResult/

24
.project Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>atriasoft-esvg</name>
<comment></comment>
<projects>
<project>atriasoft-esvg</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>

11
esvg.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,105 +0,0 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.tools as tools
import realog.debug as debug
import lutin.image as image
import os
import lutin.multiprocess as lutinMultiprocess
def get_type():
return "LIBRARY_DYNAMIC"
def get_desc():
return "Ewol Tool Kit"
def get_licence():
return "MPL-2"
def get_compagny_type():
return "org"
def get_compagny_name():
return "atria-soft"
#def get_maintainer():
# return "authors.txt"
#def get_version():
# return "version.txt"
def configure(target, my_module):
my_module.add_src_file([
'src/module-info.java',
'src/org/atriasoft/esvg/LinearGradient.java',
'src/org/atriasoft/esvg/Circle.java',
'src/org/atriasoft/esvg/Group.java',
'src/org/atriasoft/esvg/Base.java',
'src/org/atriasoft/esvg/Text.java',
'src/org/atriasoft/esvg/RadialGradient.java',
'src/org/atriasoft/esvg/internal/LOGGER.java',
'src/org/atriasoft/esvg/font/Kerning.java',
'src/org/atriasoft/esvg/font/Glyph.java',
'src/org/atriasoft/esvg/Renderer.java',
'src/org/atriasoft/esvg/EsvgFont.java',
'src/org/atriasoft/esvg/FontCache.java',
'src/org/atriasoft/esvg/Ellipse.java',
'src/org/atriasoft/esvg/Esvg.java',
'src/org/atriasoft/esvg/render/ElementLineToH.java',
'src/org/atriasoft/esvg/render/DynamicColor.java',
'src/org/atriasoft/esvg/render/Point.java',
'src/org/atriasoft/esvg/render/Scanline.java',
'src/org/atriasoft/esvg/render/PathType.java',
'src/org/atriasoft/esvg/render/ElementLineToV.java',
'src/org/atriasoft/esvg/render/PointList.java',
'src/org/atriasoft/esvg/render/ElementMoveTo.java',
'src/org/atriasoft/esvg/render/SegmentList.java',
'src/org/atriasoft/esvg/render/Segment.java',
'src/org/atriasoft/esvg/render/ElementElliptic.java',
'src/org/atriasoft/esvg/render/ElementStop.java',
'src/org/atriasoft/esvg/render/Weight.java',
'src/org/atriasoft/esvg/render/ElementBezierSmoothCurveTo.java',
'src/org/atriasoft/esvg/render/DynamicColorSpecial.java',
'src/org/atriasoft/esvg/render/PathModel.java',
'src/org/atriasoft/esvg/render/ElementBezierCurveTo.java',
'src/org/atriasoft/esvg/render/RenderingConfig.java',
'src/org/atriasoft/esvg/render/ElementLineTo.java',
'src/org/atriasoft/esvg/render/PointType.java',
'src/org/atriasoft/esvg/render/ElementCurveTo.java',
'src/org/atriasoft/esvg/render/ElementClose.java',
'src/org/atriasoft/esvg/render/DynamicColorUni.java',
'src/org/atriasoft/esvg/render/Element.java',
'src/org/atriasoft/esvg/render/ElementSmoothCurveTo.java',
'src/org/atriasoft/esvg/PaintState.java',
'src/org/atriasoft/esvg/PaintMode.java',
'src/org/atriasoft/esvg/CapMode.java',
'src/org/atriasoft/esvg/Path.java',
'src/org/atriasoft/esvg/Polygon.java',
'src/org/atriasoft/esvg/Rectangle.java',
'src/org/atriasoft/esvg/JoinMode.java',
'src/org/atriasoft/esvg/SpreadMethod.java',
'src/org/atriasoft/esvg/EsvgDocument.java',
'src/org/atriasoft/esvg/Line.java',
'src/org/atriasoft/esvg/GraphicContext.java',
'src/org/atriasoft/esvg/GradientUnits.java',
'src/org/atriasoft/esvg/Polyline.java',
])
my_module.add_path('src/', type='java')
my_module.add_depend([
'org-atriasoft-exml',
'org-atriasoft-pngencoder',
'org-atriasoft-egami',
])
#my_module.add_path([
# 'lib/spotbugs-annotations-4.2.2.jar'
# ],
# type='java',
# export=True
#);
my_module.add_flag('java', "RELEASE_15_PREVIEW");
return True

160
pom.xml
View File

@ -1,160 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.atriasoft</groupId>
<artifactId>esvg</artifactId>
<version>0.1.0</version>
<licenses>
<license>
<name>Mozilla Public License 2.0</name>
<url>https://opensource.org/licenses/MPL-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>dev1</id>
<name>Edouard DUPIN</name>
<email>edouard.dupin@proton.me</email>
<roles>
<role>Lead Developer</role>
</roles>
</developer>
</developers>
<repositories>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/org.atriasoft/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/org.atriasoft/maven</url>
</repository>
<snapshotRepository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/org.atriasoft/maven</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>org.atriasoft</groupId>
<artifactId>exml</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.atriasoft</groupId>
<artifactId>png-encoder</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.atriasoft</groupId>
<artifactId>egami</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.1.0-alpha1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.atriasoft</groupId>
<artifactId>aknot</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main</sourceDirectory>
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
<testSourceDirectory>src/test</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
<!-- Create the source bundle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- junit results -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- Java-doc generation for stand-alone site -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
</configuration>
</plugin>
</plugins>
</build>
<!-- Generate Java-docs As Part Of Project Reports -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<show>public</show>
</configuration>
</plugin>
</plugins>
</reporting>
</project>

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 697 KiB

After

Width:  |  Height:  |  Size: 697 KiB

View File

Before

Width:  |  Height:  |  Size: 737 KiB

After

Width:  |  Height:  |  Size: 737 KiB

View File

Before

Width:  |  Height:  |  Size: 897 KiB

After

Width:  |  Height:  |  Size: 897 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

Before

Width:  |  Height:  |  Size: 795 KiB

After

Width:  |  Height:  |  Size: 795 KiB

View File

Before

Width:  |  Height:  |  Size: 791 KiB

After

Width:  |  Height:  |  Size: 791 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 4.9 MiB

After

Width:  |  Height:  |  Size: 4.9 MiB

16
src/module-info.java Normal file
View File

@ -0,0 +1,16 @@
/** Basic module interface.
*
* @author Edouard DUPIN */
open module org.atriasoft.esvg {
exports org.atriasoft.esvg;
exports org.atriasoft.esvg.font;
exports org.atriasoft.esvg.render;
requires transitive io.scenarium.logger;
requires transitive org.atriasoft.etk;
requires transitive org.atriasoft.exml;
requires org.atriasoft.pngencoder;
requires java.desktop;
requires org.atriasoft.egami;
}

View File

@ -2,6 +2,7 @@ package org.atriasoft.esvg;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Distance;
import org.atriasoft.etk.math.FMath;
@ -10,8 +11,6 @@ import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -20,7 +19,6 @@ import org.slf4j.LoggerFactory;
*/
public class Base {
static final Logger LOGGER = LoggerFactory.getLogger(Base.class);
public static float kappa90 = 0.5522847493f; //!< proportional lenght to the radius of a bezier handle for 90° arcs.
@ -32,7 +30,7 @@ public class Base {
}
posStart += base.length();
if (value.length() < posStart + 2) {
LOGGER.error("Not enought spece in the String to have transform value for ' (' or '()' in '" + value + "'");
Log.error("Not enought spece in the String to have transform value for ' (' or '()' in '" + value + "'");
return "";
}
if (value.charAt(posStart) == '(') {
@ -41,19 +39,19 @@ public class Base {
} else if (value.charAt(posStart) == ' ' && value.charAt(posStart + 1) == '(') {
posStart += 2;
} else {
LOGGER.error("Can not indexOf ' (' or '(' in '" + value.substring(posStart) + "' for '" + value + "'");
Log.error("Can not indexOf ' (' or '(' in '" + value.substring(posStart) + "' for '" + value + "'");
return "";
}
if (value.length() < posStart + 1) {
LOGGER.error("Not enought spece in the String to have transform value for ')' in '" + value + "'");
Log.error("Not enought spece in the String to have transform value for ')' in '" + value + "'");
return "";
}
final int posEnd = value.indexOf(')', posStart);
int posEnd = value.indexOf(')', posStart);
if (posEnd == -1) {
LOGGER.error("Missing element ')' in '" + value + "' for " + base);
Log.error("Missing element ')' in '" + value + "' for " + base);
return "";
}
LOGGER.trace("indexOf : '" + value.substring(posStart, posEnd) + "' for " + base);
Log.verbose("indexOf : '" + value.substring(posStart, posEnd) + "' for " + base);
return value.substring(posStart, posEnd);
}
@ -85,14 +83,10 @@ public class Base {
* @param level Level of the tree
*/
void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.warn(spacingDist(level) + "DRAW esvg::Base ... ==> No drawing availlable");
Log.warning(spacingDist(level) + "DRAW esvg::Base ... ==> No drawing availlable");
}
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans) {
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans) {
drawShapePoints(out, recurtionMax, threshold, basicTrans, 1);
}
@ -104,12 +98,7 @@ public class Base {
* @param basicTrans Parant transformation of the environement
* @param level Level of the tree
*/
void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
}
@ -128,24 +117,22 @@ public class Base {
*/
Pair<Color, String> parseColor(final String inputData) {
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.length() > 4 && inputData.charAt(0) == 'u' && inputData.charAt(1) == 'r' && inputData.charAt(2) == 'l' && inputData.charAt(3) == '(') {
if (inputData.charAt(4) == '#') {
final String color = inputData.substring(5, inputData.length() - 1);
String color = inputData.substring(5, inputData.length() - 1);
localColor = new Pair<>(Color.NONE, color);
} else {
LOGGER.error(
"Problem in parsing the color : '" + inputData + "' == > url(XXX) is not supported now ...");
Log.error("Problem in parsing the color : '" + inputData + "' == > url(XXX) is not supported now ...");
}
} else {
try {
localColor = new Pair<>(Color.valueOf256(inputData), "");
} catch (final Exception e) {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
LOGGER.trace("Parse color : \"" + inputData + "\" == > " + localColor.first + " " + localColor.second);
Log.verbose("Parse color : \"" + inputData + "\" == > " + localColor.first + " " + localColor.second);
return localColor;
}
@ -155,21 +142,31 @@ public class Base {
* @return standard number of pixels
*/
float parseLength(final String dataInput) {
final Pair<Float, Distance> value = parseLength2(dataInput);
LOGGER.trace(" lenght : '" + value.first + "' => unit=" + value.second);
final float fontsize = 20.0f;
return switch (value.second) {
case POURCENT -> value.first; // / 100.0 * this.paint.viewPort.x();
case ELEMENT -> value.first * fontsize;
case EX -> value.first / 2.0f * fontsize;
case PIXEL -> value.first;
case POINT -> value.first * 1.25f;
case PC -> value.first * 15.0f;
case MILLIMETER -> value.first * 3.543307f;
case CENTIMETER -> value.first * 35.43307f;
case INCH -> value.first * 90.0f;
default -> 0.0f;
};
Pair<Float, Distance> value = parseLength2(dataInput);
Log.verbose(" lenght : '" + value.first + "' => unit=" + value.second);
float fontsize = 20.0f;
switch (value.second) {
case POURCENT:
return value.first;// / 100.0 * this.paint.viewPort.x();
case ELEMENT:
return value.first * fontsize;
case EX:
return value.first / 2.0f * fontsize;
case PIXEL:
return value.first;
case POINT:
return value.first * 1.25f;
case PC:
return value.first * 15.0f;
case MILLIMETER:
return value.first * 3.543307f;
case CENTIMETER:
return value.first * 35.43307f;
case INCH:
return value.first * 90.0f;
default:
return 0.0f;
}
}
Pair<Float, Distance> parseLength2(String config) {
@ -238,7 +235,7 @@ public class Base {
} else {
if (content.length() != 0) {
this.paint.stroke = parseColor(content);
//LOGGER.trace("Parse color : " + this.paint.stroke);
Log.error("Parse color : " + this.paint.stroke);
}
content = element.getAttribute("stroke-width", "");
if (content.length() != 0) {
@ -256,7 +253,7 @@ public class Base {
if (content.equals("none")) {
// OK, Nothing to do ...
} else {
LOGGER.info("TODO 'stroke-dasharray' not implemented ...");
Log.todo(" 'stroke-dasharray' not implemented ...");
}
}
content = element.getAttribute("stroke-linecap", "");
@ -269,7 +266,7 @@ public class Base {
this.paint.lineCap = CapMode.SQUARE;
} else {
this.paint.lineCap = CapMode.BUTT;
LOGGER.error("not know stroke-linecap value : '" + content + "', not in [butt,round,square]");
Log.error("not know stroke-linecap value : '" + content + "', not in [butt,round,square]");
}
}
content = element.getAttribute("stroke-linejoin", "");
@ -282,12 +279,12 @@ public class Base {
this.paint.lineJoin = JoinMode.BEVEL;
} else {
this.paint.lineJoin = JoinMode.MITER;
LOGGER.error("not know stroke-linejoin value : '" + content + "', not in [miter,round,bevel]");
Log.error("not know stroke-linejoin value : '" + content + "', not in [miter,round,bevel]");
}
}
content = element.getAttribute("stroke-miterlimit", "");
if (content.length() != 0) {
final float tmp = parseLength(content);
float tmp = parseLength(content);
this.paint.miterLimit = FMath.max(0.0f, tmp);
}
}
@ -312,7 +309,7 @@ public class Base {
} else if (content.equals("evenodd")) {
this.paint.flagEvenOdd = true;
} else {
LOGGER.error("not know fill-rule value : \"" + content + "\", not in [nonzero,evenodd]");
Log.error("not know fill-rule value : \"" + content + "\", not in [nonzero,evenodd]");
}
}
// ---------------- opacity ----------------
@ -332,56 +329,51 @@ public class Base {
if (inputString.length() == 0) {
return;
}
//LOGGER.trace("indexOf transform : '" + inputString + "'");
Log.verbose("indexOf transform : '" + inputString + "'");
inputString = inputString.replace(',', ' ');
//LOGGER.trace("indexOf transform : '" + inputString + "'");
Log.verbose("indexOf transform : '" + inputString + "'");
// need to indexOf elements in order ...
String data = Base.extractTransformData(inputString, "matrix");
if (data.length() != 0) {
final double[] matrix = FMath.getTableDouble(data, " ", 6);
double[] matrix = FMath.getTableDouble(data, " ", 6);
if (matrix != null) {
this.transformMatrix = new Matrix2x3f(matrix);
// indexOf a matrix : simply exit ...
return;
}
LOGGER.error("Parsing matrix() with wrong data ... '" + data + "'");
Log.error("Parsing matrix() with wrong data ... '" + data + "'");
}
data = Base.extractTransformData(inputString, "translate");
if (data.length() != 0) {
final float[] elements = FMath.getTableFloat(data, " ", 2);
float[] elements = FMath.getTableFloat(data, " ", 2);
if (elements != null) {
this.transformMatrix = this.transformMatrix
.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[0], elements[1])));
//LOGGER.trace("Translate : " + elements[0] + ", " + elements[1]);
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[0], elements[1])));
Log.verbose("Translate : " + elements[0] + ", " + elements[1]);
} else {
final float elem = Float.parseFloat(data);
float elem = Float.parseFloat(data);
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(elem, 0)));
}
}
data = Base.extractTransformData(inputString, "scale");
if (data.length() != 0) {
final float[] elements = FMath.getTableFloat(data, " ", 2);
float[] elements = FMath.getTableFloat(data, " ", 2);
if (elements != null) {
this.transformMatrix = this.transformMatrix
.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
//LOGGER.trace("Translate : " + elements[0] + ", " + elements[1]);
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
Log.verbose("Translate : " + elements[0] + ", " + elements[1]);
} else {
final float elem = Float.parseFloat(data);
float elem = Float.parseFloat(data);
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createScale(elem));
}
}
data = Base.extractTransformData(inputString, "rotate");
if (data.length() != 0) {
final float[] elements = FMath.getTableFloat(data, " ", 3);
float[] elements = FMath.getTableFloat(data, " ", 3);
if (elements != null) {
final float angle = (float) Math.toRadians(elements[0]);
this.transformMatrix = this.transformMatrix
.multiply(Matrix2x3f.createTranslate(new Vector2f(-elements[1], -elements[2])));
float angle = (float) Math.toRadians(elements[0]);
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(-elements[1], -elements[2])));
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createRotate(angle));
this.transformMatrix = this.transformMatrix
.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[1], elements[2])));
this.transformMatrix = this.transformMatrix
.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[1], elements[2])));
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
} else {
float elem = Float.parseFloat(data);
elem = (float) Math.toRadians(elem);
@ -463,7 +455,7 @@ public class Base {
}
protected String spacingDist(final int spacing) {
final StringBuilder out = new StringBuilder();
StringBuilder out = new StringBuilder();
for (int iii = 0; iii < spacing; iii++) {
out.append(" ");
}

View File

@ -3,6 +3,7 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
@ -13,8 +14,6 @@ import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -23,7 +22,6 @@ import org.slf4j.LoggerFactory;
*/
public class Circle extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Circle.class);
private Vector2f position; //!< Position of the Circle
private float radius; //!< Radius of the Circle
@ -38,46 +36,41 @@ public class Circle extends Base {
}
private PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.moveTo(false, this.position.addX(this.radius));
out.curveTo(false, this.position.add(this.radius, this.radius * Base.kappa90),
this.position.add(this.radius * Base.kappa90, this.radius), this.position.addY(this.radius));
out.curveTo(false, this.position.add(-this.radius * Base.kappa90, this.radius),
this.position.add(-this.radius, this.radius * Base.kappa90), this.position.lessX(this.radius));
out.curveTo(false, this.position.add(-this.radius, -this.radius * Base.kappa90),
this.position.add(-this.radius * Base.kappa90, -this.radius), this.position.lessY(this.radius));
out.curveTo(false, this.position.add(this.radius * Base.kappa90, -this.radius),
this.position.add(this.radius, -this.radius * Base.kappa90), this.position.addX(this.radius));
out.curveTo(false, this.position.add(this.radius, this.radius * Base.kappa90), this.position.add(this.radius * Base.kappa90, this.radius), this.position.addY(this.radius));
out.curveTo(false, this.position.add(-this.radius * Base.kappa90, this.radius), this.position.add(-this.radius, this.radius * Base.kappa90), this.position.lessX(this.radius));
out.curveTo(false, this.position.add(-this.radius, -this.radius * Base.kappa90), this.position.add(-this.radius * Base.kappa90, -this.radius), this.position.lessY(this.radius));
out.curveTo(false, this.position.add(this.radius * Base.kappa90, -this.radius), this.position.add(this.radius, -this.radius * Base.kappa90), this.position.addX(this.radius));
out.close();
return out;
}
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Circle " + this.position + " radius=" + this.radius);
Log.debug(spacingDist(spacing) + "Circle " + this.position + " radius=" + this.radius);
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Circle");
Log.verbose(spacingDist(level) + "DRAW esvg::Circle");
if (this.radius <= 0.0f) {
LOGGER.trace(spacingDist(level + 1) + "Too small radius" + this.radius);
Log.verbose(spacingDist(level + 1) + "Too small radius" + this.radius);
return;
}
final PathModel listElement = createPath();
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -92,8 +85,7 @@ public class Circle extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -106,22 +98,17 @@ public class Circle extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Circle");
final PathModel listElement = createPath();
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Circle");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -151,13 +138,13 @@ public class Circle extends Base {
}
content = element.getAttribute("r", "");
if (content.length() == 0) {
LOGGER.error("Circle \"r\" is not present");
Log.error("Circle \"r\" is not present");
return false;
}
this.radius = parseLength(content);
if (0 > this.radius) {
this.radius = 0;
LOGGER.error("Circle \"r\" is negative");
Log.error("Circle \"r\" is negative");
return false;
}
sizeMax.value = new Vector2f(this.position.x() + this.radius, this.position.y() + this.radius);

View File

@ -2,7 +2,7 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
@ -13,8 +13,6 @@ import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -23,7 +21,6 @@ import org.slf4j.LoggerFactory;
*/
public class Ellipse extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Ellipse.class);
private Vector2f c; //!< Center property of the ellipse
private Vector2f r; //!< Radius property of the ellipse
@ -38,46 +35,41 @@ public class Ellipse extends Base {
}
PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.moveTo(false, this.c.add(this.r.x(), 0.0f));
out.curveTo(false, this.c.add(this.r.x(), this.r.y() * Base.kappa90),
this.c.add(this.r.x() * Base.kappa90, this.r.y()), this.c.add(0.0f, this.r.y()));
out.curveTo(false, this.c.add(-this.r.x() * Base.kappa90, this.r.y()),
this.c.add(-this.r.x(), this.r.y() * Base.kappa90), this.c.add(-this.r.x(), 0.0f));
out.curveTo(false, this.c.add(-this.r.x(), -this.r.y() * Base.kappa90),
this.c.add(-this.r.x() * Base.kappa90, -this.r.y()), this.c.add(0.0f, -this.r.y()));
out.curveTo(false, this.c.add(this.r.x() * Base.kappa90, -this.r.y()),
this.c.add(this.r.x(), -this.r.y() * Base.kappa90), this.c.add(this.r.x(), 0.0f));
out.curveTo(false, this.c.add(this.r.x(), this.r.y() * Base.kappa90), this.c.add(this.r.x() * Base.kappa90, this.r.y()), this.c.add(0.0f, this.r.y()));
out.curveTo(false, this.c.add(-this.r.x() * Base.kappa90, this.r.y()), this.c.add(-this.r.x(), this.r.y() * Base.kappa90), this.c.add(-this.r.x(), 0.0f));
out.curveTo(false, this.c.add(-this.r.x(), -this.r.y() * Base.kappa90), this.c.add(-this.r.x() * Base.kappa90, -this.r.y()), this.c.add(0.0f, -this.r.y()));
out.curveTo(false, this.c.add(this.r.x() * Base.kappa90, -this.r.y()), this.c.add(this.r.x(), -this.r.y() * Base.kappa90), this.c.add(this.r.x(), 0.0f));
out.close();
return out;
}
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Ellipse c=" + this.c + " r=" + this.r);
Log.debug(spacingDist(spacing) + "Ellipse c=" + this.c + " r=" + this.r);
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Ellipse");
Log.verbose(spacingDist(level) + "DRAW esvg::Ellipse");
if (this.r.x() <= 0.0f || this.r.y() <= 0.0f) {
LOGGER.trace(spacingDist(level + 1) + "Too small radius" + this.r);
Log.verbose(spacingDist(level + 1) + "Too small radius" + this.r);
return;
}
final PathModel listElement = createPath();
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -92,8 +84,7 @@ public class Ellipse extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -106,22 +97,17 @@ public class Ellipse extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Ellipse");
final PathModel listElement = createPath();
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Ellipse");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -152,13 +138,13 @@ public class Ellipse extends Base {
}
content = element.getAttribute("rx", "");
if (content.length() == 0) {
LOGGER.error("Ellipse \"rx\" is not present");
Log.error("Ellipse \"rx\" is not present");
return false;
}
this.r = this.r.withX(parseLength(content));
content = element.getAttribute("ry", "");
if (content.length() == 0) {
LOGGER.error("Ellipse \"ry\" is not present");
Log.error("Ellipse \"ry\" is not present");
return false;
}
this.r = this.r.withY(parseLength(content));

View File

@ -3,23 +3,20 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.egami.ImageFloatRGBA;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Uri;
import org.atriasoft.etk.util.Dynamic;
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.Exml;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EsvgDocument extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(EsvgDocument.class);
private boolean loadOK = false;
private final List<Base> refList = new ArrayList<>();
private Vector2f size = Vector2f.ZERO;
@ -27,7 +24,6 @@ public class EsvgDocument extends Base {
private String title = ""; //!< sub-element list
private Uri uri = null; //!< reference elements ...
private String version = "0.0";
private static final boolean envDisplayRefs = "true".equals(System.getenv("ESQG_DISPLAY_REFS"));
public EsvgDocument() {
@ -46,19 +42,19 @@ public class EsvgDocument extends Base {
*/
public boolean cleanStyleProperty(final XmlElement root) {
// for each nodes:
for (final XmlNode it : root.getNodes()) {
if (!(it instanceof final XmlElement child)) {
for (XmlNode it : root.getNodes()) {
if (!(it instanceof XmlElement child)) {
continue;
}
// get attribute style:
if (child.existAttribute("style")) {
final String content = child.getAttribute("style", "");
String content = child.getAttribute("style", "");
if (content.length() != 0) {
final String[] listStyle = content.split(";");
for (final String it1 : listStyle) {
final String[] value = it1.split(":");
String[] listStyle = content.split(";");
for (String it1 : listStyle) {
String[] value = it1.split(":");
if (value.length != 2) {
LOGGER.error("parsing style with a wrong patern : " + it1 + " missing ':'");
Log.error("parsing style with a wrong patern : " + it1 + " missing ':'");
continue;
}
// TODO Check if the attibute already exist ...
@ -86,39 +82,34 @@ public class EsvgDocument extends Base {
* Display all the node in the svg file.
*/
public void displayDebug() {
LOGGER.debug("Main SVG: size=" + this.size);
LOGGER.debug(" refs:");
for (final Base element : this.refList) {
if (element != null) {
element.display(2);
Log.debug("Main SVG: size=" + this.size);
Log.debug(" refs:");
for (int iii = 0; iii < this.refList.size(); iii++) {
if (this.refList.get(iii) != null) {
this.refList.get(iii).display(2);
}
}
LOGGER.debug(" Nodes:");
for (final Base element : this.subElementList) {
if (element != null) {
element.display(2);
Log.debug(" Nodes:");
for (int iii = 0; iii < this.subElementList.size(); iii++) {
if (this.subElementList.get(iii) != null) {
this.subElementList.get(iii).display(2);
}
}
}
@Override
protected void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
for (final Base element : this.subElementList) {
if (element != null) {
element.draw(myRenderer, basicTrans);
for (int iii = 0; iii < this.subElementList.size(); iii++) {
if (this.subElementList.get(iii) != null) {
this.subElementList.get(iii).draw(myRenderer, basicTrans);
}
}
}
@Override
protected void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW shape EsvgDocument");
for (final Base it : this.subElementList) {
protected void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW shape EsvgDocument");
for (Base it : this.subElementList) {
if (it != null) {
it.drawShapePoints(out, recurtionMax, threshold, basicTrans, level + 1);
}
@ -135,27 +126,26 @@ public class EsvgDocument extends Base {
}
public List<List<Vector2f>> getLines(Vector2f size) {
final List<List<Vector2f>> out = new ArrayList<>();
List<List<Vector2f>> out = new ArrayList<>();
if (size.x() <= 0) {
size = size.withX(this.size.x());
}
if (size.y() <= 0) {
size = size.withY(this.size.y());
}
LOGGER.debug("lineification size " + size);
Log.debug("lineification size " + size);
// create the first element matrix modification ...
final Matrix2x3f basicTrans = Matrix2x3f.IDENTITY
.multiply(Matrix2x3f.createScale(new Vector2f(size.x() / this.size.x(), size.y() / this.size.y())));
Matrix2x3f basicTrans = Matrix2x3f.IDENTITY.multiply(Matrix2x3f.createScale(new Vector2f(size.x() / this.size.x(), size.y() / this.size.y())));
drawShapePoints(out, 10, 0.25f, basicTrans);
return out;
}
public Base getReference(final String name) {
if (name.isEmpty()) {
LOGGER.error("request a reference with no name ... ");
Log.error("request a reference with no name ... ");
return null;
}
for (final Base it : this.refList) {
for (Base it : this.refList) {
if (it == null) {
continue;
}
@ -163,7 +153,7 @@ public class EsvgDocument extends Base {
return it;
}
}
LOGGER.error("Can not find reference name : '" + name + "'");
Log.error("Can not find reference name : '" + name + "'");
return null;
}
@ -220,18 +210,18 @@ public class EsvgDocument extends Base {
XmlNode doc = null;
try {
doc = Exml.parse(uri);
} catch (final ExmlException | AknotException e) {
} catch (ExmlBuilderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
if (doc instanceof final XmlElement elem && elem.existNode("svg")) {
if (doc instanceof XmlElement elem && elem.existNode("svg")) {
try {
if (elem.getNode("svg") instanceof final XmlElement rootElement) {
if (elem.getNode("svg") instanceof XmlElement rootElement) {
cleanStyleProperty(rootElement);
this.loadOK = parseXMLData(rootElement);
}
} catch (final ExmlNodeDoesNotExist e) {
} catch (ExmlNodeDoesNotExist e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
@ -252,18 +242,18 @@ public class EsvgDocument extends Base {
XmlNode doc = null;
try {
doc = Exml.parse(data);
} catch (final ExmlException | AknotException e) {
} catch (ExmlBuilderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
if (doc instanceof final XmlElement elem && elem.existNode("svg")) {
if (doc instanceof XmlElement elem && elem.existNode("svg")) {
try {
if (elem.getNode("svg") instanceof final XmlElement rootElement) {
if (elem.getNode("svg") instanceof XmlElement rootElement) {
cleanStyleProperty(rootElement);
this.loadOK = parseXMLData(rootElement);
}
} catch (final ExmlNodeDoesNotExist e) {
} catch (ExmlNodeDoesNotExist e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
@ -286,16 +276,16 @@ public class EsvgDocument extends Base {
pos = parseXmlPosition(root);
this.size = parseXmlSize(root);
parsePaintAttr(root);
LOGGER.trace("parsed .ROOT trans: " + this.transformMatrix);
Log.verbose("parsed .ROOT trans: " + this.transformMatrix);
} else {
LOGGER.trace("Parse Reference section ... (no attibute)");
Log.verbose("Parse Reference section ... (no attibute)");
}
Vector2f maxSize = Vector2f.ZERO;
final Dynamic<Vector2f> size = new Dynamic<>(Vector2f.ZERO);
Dynamic<Vector2f> size = new Dynamic<>(Vector2f.ZERO);
// parse all sub node:
for (final XmlNode it : root.getNodes()) {
if (!(it instanceof final XmlElement child)) {
for (XmlNode it : root.getNodes()) {
if (!(it instanceof XmlElement child)) {
// comment can be here...
continue;
}
@ -303,7 +293,7 @@ public class EsvgDocument extends Base {
if (child.getValue().equals("g")) {
elementParser = new Group(this.paint);
} else if (child.getValue().equals("a")) {
LOGGER.info("Note : 'a' balise is parsed like a g balise ...");
Log.info("Note : 'a' balise is parsed like a g balise ...");
elementParser = new Group(this.paint);
} else if (child.getValue().equals("title")) {
this.title = "TODO : set the title here ...";
@ -326,22 +316,22 @@ public class EsvgDocument extends Base {
elementParser = new Text(this.paint);
} else if (child.getValue().equals("radialGradient")) {
if (!isReference) {
LOGGER.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
Log.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
continue;
}
elementParser = new RadialGradient(this.paint);
} else if (child.getValue().equals("linearGradient")) {
if (!isReference) {
LOGGER.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
Log.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
continue;
}
elementParser = new LinearGradient(this.paint);
} else if (child.getValue().equals("defs")) {
if (isReference) {
LOGGER.error("'" + child.getValue() + "' node must not be defined in a defs Section");
Log.error("'" + child.getValue() + "' node must not be defined in a defs Section");
continue;
}
final boolean retRefs = parseXMLData(child, true);
boolean retRefs = parseXMLData(child, true);
// TODO Use retRefs ...
continue;
} else if (child.getValue().equals("sodipodi:namedview")) {
@ -351,15 +341,14 @@ public class EsvgDocument extends Base {
// Node ignore : generaly inkscape data
continue;
} else {
LOGGER.error("node not suported : '" + child.getValue()
+ "' must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
Log.error("node not suported : '" + child.getValue() + "' must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
}
if (elementParser == null) {
LOGGER.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
Log.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
continue;
}
if (!elementParser.parseXML(child, this.transformMatrix, size)) {
LOGGER.error("error on node: '" + child.getValue() + "' Sub Parsing ERROR");
Log.error("error on node: '" + child.getValue() + "' Sub Parsing ERROR");
elementParser = null;
continue;
}
@ -381,7 +370,7 @@ public class EsvgDocument extends Base {
} else {
this.size = Vector2f.clipInt(this.size);
}
if (envDisplayRefs && !isReference) {
if (!isReference) {
displayDebug();
}
return true;
@ -403,7 +392,7 @@ public class EsvgDocument extends Base {
size = size.withY((int) this.size.y());
}
}
LOGGER.debug("Generate size " + size);
Log.debug("Generate size " + size);
Renderer renderedElement = new Renderer(size, this, visualDebug);
// create the first element matrix modification ...
Matrix2x3f basicTrans = Matrix2x3f.IDENTITY.multiply(Matrix2x3f.createScale(new Vector2f(size.x() / this.size.x(), size.y() / this.size.y())));
@ -427,23 +416,16 @@ public class EsvgDocument extends Base {
size = new Vector2i((int) this.size.x(), (int) this.size.y());
} else {
if (size.x() <= 0) {
size = size.withX((int) Math.abs(this.size.x()));
size = size.withX((int) this.size.x());
}
if (size.y() <= 0) {
size = size.withY((int) Math.abs(this.size.y()));
size = size.withY((int) this.size.y());
}
}
if (size.x() <= 0) {
LOGGER.error("Generate size " + size);
}
if (size.y() <= 0) {
LOGGER.error("Generate size " + size);
}
LOGGER.trace("Generate size " + size);
final Renderer renderedElement = new Renderer(size, this, visualDebug);
Log.debug("Generate size " + size);
Renderer renderedElement = new Renderer(size, this, visualDebug);
// create the first element matrix modification ...
final Matrix2x3f basicTrans = Matrix2x3f.IDENTITY
.multiply(Matrix2x3f.createScale(new Vector2f(size.x() / this.size.x(), size.y() / this.size.y())));
Matrix2x3f basicTrans = Matrix2x3f.IDENTITY.multiply(Matrix2x3f.createScale(new Vector2f(size.x() / this.size.x(), size.y() / this.size.y())));
draw(renderedElement, basicTrans);
// direct return the generated data ...

View File

@ -1,13 +1,13 @@
package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.esvg.font.Glyph;
import org.atriasoft.esvg.font.Kerning;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.RenderingConfig;
import org.atriasoft.esvg.render.Weight;
@ -17,11 +17,9 @@ import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// https://www.w3.org/TR/SVGTiny12/fonts.html
@ -78,7 +76,6 @@ import org.slf4j.LoggerFactory;
*/
public class EsvgFont {
static final Logger LOGGER = LoggerFactory.getLogger(EsvgFont.class);
/**
* Load the file that might contain the svg
@ -87,43 +84,38 @@ public class EsvgFont {
* @return true : Parsing is OK
*/
public static EsvgFont load(final Uri uri) {
final EsvgFont font = new EsvgFont();
EsvgFont font = new EsvgFont();
XmlNode doc = null;
try {
doc = Exml.parse(uri);
} catch (final ExmlException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
} catch (final AknotException e) {
} catch (ExmlBuilderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
if (!(doc instanceof final XmlElement root)) {
LOGGER.error("can not load the SVG font ==> wrong root node");
if (!(doc instanceof XmlElement root)) {
Log.error("can not load the SVG font ==> wrong root node");
return null;
}
if (!root.existNode("svg") || !(root.getNodeNoExcept("svg") instanceof final XmlElement svgNode)) {
LOGGER.error("can not load Node <svg> in svg document");
if (!root.existNode("svg") || !(root.getNodeNoExcept("svg") instanceof XmlElement svgNode)) {
Log.error("can not load Node <svg> in svg document");
return null;
}
if (!svgNode.existNode("defs") || !(svgNode.getNodeNoExcept("defs") instanceof final XmlElement defsNode)) {
LOGGER.error("can not load Node <defs> in svg document");
if (!svgNode.existNode("defs") || !(svgNode.getNodeNoExcept("defs") instanceof XmlElement defsNode)) {
Log.error("can not load Node <defs> in svg document");
return null;
}
if (!defsNode.existNode("font")
|| !(defsNode.getNodeNoExcept("font") instanceof final XmlElement fontElement)) {
LOGGER.error("can not load Node <font> in svg document");
if (!defsNode.existNode("font") || !(defsNode.getNodeNoExcept("font") instanceof XmlElement fontElement)) {
Log.error("can not load Node <font> in svg document");
return null;
}
font.horizAdvX = Integer.parseInt(fontElement.getAttribute("horiz-adv-x", "100"));
int nbGlyph = 0;
for (final XmlNode values : fontElement.getNodes()) {
for (XmlNode values : fontElement.getNodes()) {
if (values.getValue().equals("font-face")) {
if (values instanceof final XmlElement fontFace) {
if (values instanceof XmlElement fontFace) {
font.fontFamily = fontFace.getAttribute("font-family", "unknown");
font.fontStretch = fontFace.getAttribute("font-stretch", "normal");
font.fontWeight = Integer.parseInt(fontFace.getAttribute("font-weight", "400"));
@ -151,17 +143,17 @@ public class EsvgFont {
//unicode-range="U+0020-1F093"
tmp = fontFace.getAttribute("unicode-range", null);
tmpSplit = tmp.split("-");
final int start = Integer.parseInt(tmpSplit[0].substring(2), 16);
final int stop = Integer.parseInt(tmpSplit[1], 16);
int start = Integer.parseInt(tmpSplit[0].substring(2), 16);
int stop = Integer.parseInt(tmpSplit[1], 16);
font.unicodeRange = new Pair<>(start, stop);
}
}
}
for (final XmlNode values : fontElement.getNodes()) {
for (XmlNode values : fontElement.getNodes()) {
if (values.getValue().equals("glyph")) {
nbGlyph++;
//LOGGER.info("find flyph: " + nbGlyph);
final Glyph tmp = Glyph.valueOf(values.toElement(), font);
//Log.info("find flyph: " + nbGlyph);
Glyph tmp = Glyph.valueOf(values.toElement(), font);
if (tmp != null) {
font.glyphs.put(tmp.getUnicodeValue(), tmp);
}
@ -172,37 +164,37 @@ public class EsvgFont {
} else if (values.getValue().equals("font-face")) {
// already done ...
} else {
LOGGER.warn("unsupported node name :" + values.getValue());
Log.warning("unsupported node name :" + values.getValue());
}
}
for (final XmlNode values : fontElement.getNodes()) {
for (XmlNode values : fontElement.getNodes()) {
if (values.getValue().equals("hkern")) {
if (values instanceof final XmlElement kernElem) {
final String g1 = kernElem.getAttribute("g1", null);
final String g2 = kernElem.getAttribute("g2", null);
if (values instanceof XmlElement kernElem) {
String g1 = kernElem.getAttribute("g1", null);
String g2 = kernElem.getAttribute("g2", null);
if (g1 == null || g2 == null) {
continue;
}
final float offset = Float.parseFloat(kernElem.getAttribute("k", "0"));
float offset = Float.parseFloat(kernElem.getAttribute("k", "0"));
if (offset == 0.0f) {
continue;
}
final String[] g1Splited = g1.split(",");
final String[] g2Splited = g2.split(",");
String[] g1Splited = g1.split(",");
String[] g2Splited = g2.split(",");
// create the list of kerning of the next elements
final List<Kerning> elementsKerning = new ArrayList<>();
for (final String element : g2Splited) {
for (final Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
if (entry.getValue().getName().equals(element)) {
List<Kerning> elementsKerning = new ArrayList<>();
for (int iii = 0; iii < g2Splited.length; iii++) {
for (Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
if (entry.getValue().getName().equals(g2Splited[iii])) {
elementsKerning.add(new Kerning(offset, entry.getKey()));
break;
}
}
}
// add it on the
for (final String element : g1Splited) {
for (final Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
if (entry.getValue().getName().equals(element)) {
for (int iii = 0; iii < g1Splited.length; iii++) {
for (Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
if (entry.getValue().getName().equals(g1Splited[iii])) {
entry.getValue().addKerning(elementsKerning);
font.hasKerning = true;
break;
@ -254,53 +246,23 @@ public class EsvgFont {
}
public Vector2f calculateRenderOffset(final int fontSize) {
final int realSize = calculateFontRealHeight(fontSize);
final float deltaY = realSize * this.ascent / this.unitsPerEm;
int realSize = calculateFontRealHeight(fontSize);
float deltaY = realSize * this.ascent / this.unitsPerEm;
return new Vector2f(0, deltaY);
}
public float calculateSclaleFactor(final int fontSize) {
final int realSize = calculateFontRealHeight(fontSize);
int realSize = calculateFontRealHeight(fontSize);
return (float) realSize / (float) this.unitsPerEm;
}
public Vector2i calculateTextSize(final int fontSize, final String data) {
final boolean withKerning = true;
final int widthOut = calculateWidth(data, fontSize, withKerning);
final int realSize = calculateFontRealHeight(fontSize);
return new Vector2i(widthOut, realSize);
/*
float scale = (float) realSize / (float) this.unitsPerEm;
int offsetWriting = 0;
int lastValue = 0;
for (char uVal : data.toCharArray()) {
Glyph glyph = getGlyph(uVal);
if (glyph == null) {
lastValue = uVal;
continue;
}
if (withKerning) {
offsetWriting -= glyph.getKerning(lastValue) * scale;
lastValue = uVal;
}
float advenceXLocal = glyph.getHorizAdvX() * scale;
// No generation of output ...
offsetWriting += advenceXLocal;
}
return new Vector2i(offsetWriting, realSize);
*/
}
public int calculateWidth(final int uVal, final int fontSize) {
final Glyph glyph = getGlyph(uVal);
Glyph glyph = getGlyph(uVal);
if (glyph == null) {
return 0;
}
final int realSize = calculateFontRealHeight(fontSize);
final float scale = (float) realSize / (float) this.unitsPerEm;
int realSize = calculateFontRealHeight(fontSize);
float scale = (float) realSize / (float) this.unitsPerEm;
return (int) (glyph.getHorizAdvX() * scale);
}
@ -309,27 +271,23 @@ public class EsvgFont {
}
public int calculateWidth(final String data, final int fontSize, final boolean withKerning) {
final int realSize = calculateFontRealHeight(fontSize);
final float scale = (float) realSize / (float) this.unitsPerEm;
//LOGGER.error("scale =" + scale+ " font size = " + fontSize + " realSize=" + realSize);
float offsetWriting = 0;
int realSize = calculateFontRealHeight(fontSize);
float scale = (float) realSize / (float) this.unitsPerEm;
int out = 0;
int lastValue = 0;
for (final char uVal : data.toCharArray()) {
final Glyph glyph = getGlyph(uVal);
for (char uVal : data.toCharArray()) {
Glyph glyph = getGlyph(uVal);
if (glyph == null) {
lastValue = uVal;
continue;
}
if (withKerning) {
offsetWriting -= glyph.getKerning(lastValue) * scale;
out -= glyph.getKerning(lastValue) * scale;
lastValue = uVal;
}
final float advenceXLocal = glyph.getHorizAdvX() * scale;
offsetWriting += advenceXLocal;
//LOGGER.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
out += glyph.getHorizAdvX() * scale;
}
return (int) offsetWriting;
return out;
}
/**
@ -347,7 +305,7 @@ public class EsvgFont {
}
public Glyph getGlyph(final int glyphIndex) {
final Glyph out = this.glyphs.get(glyphIndex);
Glyph out = this.glyphs.get(glyphIndex);
if (out == null) {
return this.missingGlyph;
}
@ -355,7 +313,7 @@ public class EsvgFont {
}
public Glyph getGlyphNullIfMissing(final int glyphIndex) {
final Glyph out = this.glyphs.get(glyphIndex);
Glyph out = this.glyphs.get(glyphIndex);
if (out == null) {
return null;
}
@ -387,20 +345,19 @@ public class EsvgFont {
}
public Weight render(final int uVal, final int fontSize) {
final int realSize = calculateFontRealHeight(fontSize);
final Glyph glyph = getGlyph(uVal);
int realSize = calculateFontRealHeight(fontSize);
Glyph glyph = getGlyph(uVal);
if (glyph == null) {
return null;
}
final float scale = (float) realSize / (float) this.unitsPerEm;
final RenderingConfig config = new RenderingConfig(10, 0.25f, 8);
final Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent))
.multiply(Matrix2x3f.createScale(scale));
final PathModel model = glyph.getModel();
float scale = (float) realSize / (float) this.unitsPerEm;
RenderingConfig config = new RenderingConfig(10, 0.25f, 8);
Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent)).multiply(Matrix2x3f.createScale(scale));
PathModel model = glyph.getModel();
if (model == null) {
return null;
}
final Weight data = glyph.getModel().drawFill(calculateWidthRendering(uVal, fontSize), transform, 8, config);
Weight data = glyph.getModel().drawFill(calculateWidthRendering(uVal, fontSize), transform, 8, config);
return data;
}
@ -409,37 +366,35 @@ public class EsvgFont {
}
public Weight render(final String data, final int fontSize, final boolean withKerning) {
final int widthOut = calculateWidth(data, fontSize, withKerning);
int widthOut = calculateWidth(data, fontSize, withKerning);
final int realSize = calculateFontRealHeight(fontSize);
final float scale = (float) realSize / (float) this.unitsPerEm;
int realSize = calculateFontRealHeight(fontSize);
float scale = (float) realSize / (float) this.unitsPerEm;
final Weight weight = new Weight(new Vector2i(widthOut, realSize));
Weight weight = new Weight(new Vector2i(widthOut, realSize));
float offsetWriting = 0;
int offsetWriting = 0;
int lastValue = 0;
for (final char uVal : data.toCharArray()) {
final Glyph glyph = getGlyph(uVal);
for (char uVal : data.toCharArray()) {
Glyph glyph = getGlyph(uVal);
if (glyph == null) {
lastValue = uVal;
continue;
}
if (withKerning) {
offsetWriting -= glyph.getKerning(lastValue) * scale;
LOGGER.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
lastValue = uVal;
}
final float advenceXLocal = glyph.getHorizAdvX() * scale;
float advenceXLocal = glyph.getHorizAdvX() * scale;
final RenderingConfig config = new RenderingConfig(10, 0.25f, 8);
final Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent))
.multiply(Matrix2x3f.createScale(scale));
final PathModel model = glyph.getModel();
RenderingConfig config = new RenderingConfig(10, 0.25f, 8);
Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent)).multiply(Matrix2x3f.createScale(scale));
PathModel model = glyph.getModel();
if (model != null) {
final Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8,
config);
weight.fusion(redered, (int) offsetWriting, 0);
Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8, config);
weight.fusion(redered, offsetWriting, 0);
}
offsetWriting += advenceXLocal;

View File

@ -0,0 +1,255 @@
package org.atriasoft.esvg;
import org.atriasoft.egami.ImageByteRGBA;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
/**
* Graphic context is used to manage dynamic
* @author heero
*
*/
public class GraphicContext {
private EsvgDocument document;
PaintState paintState;
private PathModel path = null;
private Vector2i size = Vector2i.VALUE_32;
public GraphicContext() {
clear();
}
public void circle(final Vector2f position, final float radius) {
this.document.addElement(new Circle(position, radius, this.paintState.clone()));
}
public void clear() {
this.document = new EsvgDocument(this.size);
this.paintState = new PaintState();
}
/**
* Clear the fill color (disable fill ==> better that set it transparent)
*/
public void clearColorFill() {
this.paintState.fill = null;
}
/**
* Clear the Stroke color (disable stroke)
*/
public void clearColorStroke() {
this.paintState.clearStroke();
}
public void ellipse(final Vector2f center, final Vector2f radius) {
this.document.addElement(new Ellipse(center, radius, this.paintState.clone()));
}
/**
* Get the fill color.
* @return fill color.
*/
public Color getColorFill() {
return this.paintState.getFill();
}
/**
* Get the stroke color.
* @return Stroke color.
*/
public Color getColorStroke() {
return this.paintState.getStroke();
}
public CapMode getLineCap() {
return this.paintState.getLineCap();
}
public JoinMode getLineJoin() {
return this.paintState.getLineJoin();
}
public float getMiterLimit() {
return this.paintState.getMiterLimit();
}
public float getOpacity() {
return this.paintState.getOpacity();
}
public float getStrokeWidth() {
return this.paintState.getStrokeWidth();
}
public void line(final Vector2f origin, final Vector2f destination) {
this.document.addElement(new Line(origin, destination, this.paintState.clone()));
}
public void lineRel(final Vector2f origin, final Vector2f relativeDestination) {
this.document.addElement(new Line(origin, origin.add(relativeDestination), this.paintState.clone()));
}
public void pathLine(final Vector2f pos) {
if (this.path == null) {
Log.error("Empty path... Need call pathStart() before");
return;
}
this.path.lineTo(false, pos);
}
public void pathLineTo(final Vector2f pos) {
if (this.path == null) {
Log.error("Empty path... Need call pathStart() before");
return;
}
this.path.lineTo(true, pos);
}
public void pathMove(final Vector2f pos) {
if (this.path == null) {
Log.error("Empty path... Need call pathStart() before");
return;
}
this.path.moveTo(false, pos);
}
public void pathMoveTo(final Vector2f pos) {
if (this.path == null) {
Log.error("Empty path... Need call pathStart() before");
return;
}
this.path.moveTo(true, pos);
}
public void pathStart() {
pathStop();
this.path = new PathModel();
}
public void pathStop() {
if (this.path == null) {
return;
}
this.path.close(false);
this.document.addElement(new Path(this.path, this.paintState.clone()));
this.path = null;
}
public void pathStopLinked() {
if (this.path == null) {
return;
}
this.path.close(true);
this.document.addElement(new Path(this.path, this.paintState.clone()));
this.path = null;
}
public void rectangle(final Vector2f position, final Vector2f destination) {
if (this.path != null) {
Log.error("Path not empty ... Need call pathStart() before");
pathStop();
}
this.document.addElement(new Rectangle(position, destination.less(position), this.paintState.clone()));
}
public void rectangleRounded(final Vector2f position, final Vector2f destination, final Vector2f ruound) {
if (this.path != null) {
Log.error("Path not empty ... Need call pathStart() before");
pathStop();
}
this.document.addElement(new Rectangle(position, destination.less(position), ruound, this.paintState.clone()));
}
public void rectangleRoundedWidth(final Vector2f position, final Vector2f width, final Vector2f ruound) {
if (this.path != null) {
Log.error("Path not empty ... Need call pathStart() before");
pathStop();
}
this.document.addElement(new Rectangle(position, width, ruound, this.paintState.clone()));
}
public void rectangleWidth(final Vector2f position, final Vector2f width) {
if (this.path != null) {
Log.error("Path not empty ... Need call pathStart() before");
pathStop();
}
this.document.addElement(new Rectangle(position, width, this.paintState.clone()));
}
public ImageByteRGBA render() {
return null;
}
public String renderSvg() {
return null;
}
/**
* set the fill color
* @param color Color to set on fill
* @apiNote use clearFill() if you want to remove drawing of fill
*/
public void setColorFill(final Color color) {
this.paintState.setFill(color);
}
/**
* set the stroke color
* @param color Color to set on stroke
* @apiNote use clearStroke() if you want to remove drawing of stroke
*/
public void setColorStroke(final Color color) {
this.paintState.setStroke(color);
}
public void setLineCap(final CapMode lineCap) {
this.paintState.setLineCap(lineCap);
}
public void setLineJoin(final JoinMode lineJoin) {
this.paintState.setLineJoin(lineJoin);
}
public void setMiterLimit(final float miterLimit) {
this.paintState.setMiterLimit(miterLimit);
}
public void setOpacity(final float opacity) {
this.paintState.setOpacity(opacity);
}
/**
* Set global size of the Graphic context (output render size)
* @param xxx Width of the image
* @param yyy Height of the image
* @apiNote It will clear the current context.
*/
public void setSize(final int xxx, final int yyy) {
setSize(new Vector2i(xxx, yyy));
}
/**
* Set global size of the Graphic contexct (output render size)
* @param vector2i New size of the image
* @apiNote It will clear the current context.
*/
private void setSize(final Vector2i size) {
this.size = size;
clear();
}
public void setStrokeWidth(final float strokeWidth) {
this.paintState.setStrokeWidth(strokeWidth);
}
public void text(final Vector2f position, final float height, final String data) {
this.document.addElement(new Text(position, height, data, this.paintState.clone()));
}
}

View File

@ -3,13 +3,12 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -17,7 +16,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Group extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Group.class);
private final List<Base> subElementList = new ArrayList<>(); //!< sub elements ...
public Group(final PaintState parentPaintState) {
@ -26,21 +24,20 @@ public class Group extends Base {
@Override
public void display(final int spacing) {
LOGGER.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);
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 (final Base it : this.subElementList) {
if (it != null) {
it.display(spacing + 1);
}
}
LOGGER.debug(spacingDist(spacing) + "Group (STOP)");
Log.debug(spacingDist(spacing) + "Group (STOP)");
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::group");
for (final Base it : this.subElementList) {
Log.verbose(spacingDist(level) + "DRAW esvg::group");
for (Base it : this.subElementList) {
if (it != null) {
it.draw(myRenderer, basicTrans, level + 1);
}
@ -48,14 +45,9 @@ public class Group extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW shape esvg::group");
for (final Base it : this.subElementList) {
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW shape esvg::group");
for (Base it : this.subElementList) {
if (it != null) {
it.drawShapePoints(out, recurtionMax, threshold, basicTrans, level + 1);
}
@ -74,18 +66,18 @@ public class Group extends Base {
pos = parseXmlPosition(element);
size = parseXmlSize(element);
parsePaintAttr(element);
LOGGER.trace("parsed G1. trans : " + this.transformMatrix);
Log.verbose("parsed G1. trans : " + this.transformMatrix);
// add the property of the parrent modifications ...
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
LOGGER.trace("parsed G2. trans : " + this.transformMatrix);
Log.verbose("parsed G2. trans : " + this.transformMatrix);
sizeMax.value = Vector2f.ZERO;
final Dynamic<Vector2f> tmpPos = new Dynamic<>(Vector2f.ZERO);
Dynamic<Vector2f> tmpPos = new Dynamic<Vector2f>(Vector2f.ZERO);
// parse all sub node :
for (final XmlNode it : element.getNodes()) {
if (!(it instanceof final XmlElement child)) {
for (XmlNode it : element.getNodes()) {
if (!(it instanceof XmlElement child)) {
// can be a comment ...
continue;
}
@ -111,15 +103,14 @@ public class Group extends Base {
} else if (child.getValue().equals("text")) {
elementParser = new Text(this.paint);
} else {
LOGGER.error("node not suported : '" + child.getValue()
+ "' must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
Log.error("node not suported : '" + child.getValue() + "' must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
}
if (elementParser == null) {
LOGGER.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
Log.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
continue;
}
if (!elementParser.parseXML(child, this.transformMatrix, tmpPos)) {
LOGGER.error(" error on node: '" + child.getValue() + "' Sub Parsing ERROR");
Log.error(" error on node: '" + child.getValue() + "' Sub Parsing ERROR");
elementParser = null;
continue;
}

View File

@ -3,6 +3,7 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
@ -13,8 +14,6 @@ import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -22,7 +21,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Line extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Line.class);
private Vector2f startPos = Vector2f.ZERO; //!< Start line position
private Vector2f stopPos = Vector2f.ZERO; //!< Stop line position
@ -37,7 +35,7 @@ public class Line extends Base {
}
private PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.clear();
out.moveTo(false, this.startPos);
out.lineTo(false, this.stopPos);
@ -47,24 +45,23 @@ public class Line extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Line " + this.startPos + " to " + this.stopPos);
Log.debug(spacingDist(spacing) + "Line " + this.startPos + " to " + this.stopPos);
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Line");
Log.verbose(spacingDist(level) + "DRAW esvg::Line");
final PathModel listElement = createPath();
PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -73,8 +70,7 @@ public class Line extends Base {
// No background ...
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -85,21 +81,16 @@ public class Line extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Line");
final PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Line");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);

View File

@ -3,8 +3,9 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Dimension2f;
import org.atriasoft.etk.Dimension;
import org.atriasoft.etk.Distance;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
@ -13,8 +14,6 @@ import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -23,11 +22,10 @@ import org.slf4j.LoggerFactory;
*/
public class LinearGradient extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(LinearGradient.class);
private final List<Pair<Float, Color>> data = new ArrayList<>(); //!< gradient position x1 y1
private String href = ""; //!< gradient position x2 y2
private Dimension2f pos1 = new Dimension2f(new Vector2f(50, 50), Distance.POURCENT);
private Dimension2f pos2 = new Dimension2f(new Vector2f(50, 50), Distance.POURCENT);
private Dimension pos1 = new Dimension(new Vector2f(50, 50), Distance.POURCENT);
private Dimension pos2 = new Dimension(new Vector2f(50, 50), Distance.POURCENT);
public SpreadMethod spread = SpreadMethod.PAD; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
@ -40,15 +38,15 @@ public class LinearGradient extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "LinearGradient " + this.pos1 + " to " + this.pos2);
for (final Pair<Float, Color> it : this.data) {
LOGGER.debug(spacingDist(spacing + 1) + "STOP: offset=" + it.first + " color=" + it.second);
Log.debug(spacingDist(spacing) + "LinearGradient " + this.pos1 + " to " + this.pos2);
for (Pair<Float, Color> it : this.data) {
Log.debug(spacingDist(spacing + 1) + "STOP: offset=" + it.first + " color=" + it.second);
}
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::LinearGradient");
Log.verbose(spacingDist(level) + "DRAW esvg::LinearGradient");
}
public List<Pair<Float, Color>> getColors(final EsvgDocument document) {
@ -56,28 +54,28 @@ public class LinearGradient extends Base {
return this.data;
}
if (document == null) {
LOGGER.error("Get null input for document");
Log.error("Get null input for document");
return this.data;
}
final Base base = document.getReference(this.href);
Base base = document.getReference(this.href);
if (base == null) {
LOGGER.error("Can not get base : '" + this.href + "'");
Log.error("Can not get base : '" + this.href + "'");
return this.data;
}
if (base instanceof final RadialGradient gradientR) {
if (base instanceof RadialGradient gradientR) {
return gradientR.getColors(document);
}
if (base instanceof final LinearGradient gradientL) {
if (base instanceof LinearGradient gradientL) {
return gradientL.getColors(document);
}
return this.data;
}
public Dimension2f getPosition1() {
public Dimension getPosition1() {
return this.pos1;
}
public Dimension2f getPosition2() {
public Dimension getPosition2() {
return this.pos2;
}
@ -102,12 +100,12 @@ public class LinearGradient extends Base {
String contentX = element.getAttribute("x1", "");
String contentY = element.getAttribute("y1", "");
if (!contentX.isEmpty() && !contentY.isEmpty()) {
this.pos1 = Dimension2f.valueOf(contentX, contentY);
this.pos1 = Dimension.valueOf(contentX, contentY);
}
contentX = element.getAttribute("x2", "");
contentY = element.getAttribute("y2", "");
if (!contentX.isEmpty() && !contentY.isEmpty()) {
this.pos2 = Dimension2f.valueOf(contentX, contentY);
this.pos2 = Dimension.valueOf(contentX, contentY);
}
contentX = element.getAttribute("gradientUnits", "");
if (contentX.equals("userSpaceOnUse")) {
@ -115,8 +113,7 @@ public class LinearGradient extends Base {
} else {
this.unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
if (contentX.length() != 0 && contentX != "objectBoundingBox") {
LOGGER.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX
+ "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX + "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
}
}
contentX = element.getAttribute("spreadMethod", "");
@ -127,8 +124,7 @@ public class LinearGradient extends Base {
} else {
this.spread = SpreadMethod.PAD;
if (contentX.length() != 0 && !contentX.equals("pad")) {
LOGGER.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX
+ "' not in : {reflect/repeate/pad} use pad");
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad");
}
}
// note: xlink:href is incompatible with subNode "stop"
@ -137,20 +133,19 @@ public class LinearGradient extends Base {
this.href = this.href.substring(1);
}
// parse all sub node :
for (final XmlNode it : element.getNodes()) {
if (it instanceof final XmlElement child) {
for (XmlNode it : element.getNodes()) {
if (it instanceof XmlElement child) {
if (child.getValue().equals("stop")) {
float offset = 100;
Color stopColor = Color.NONE;
String content = child.getAttribute("offset", "");
if (content.length() != 0) {
final Pair<Float, Distance> tmp = parseLength2(content);
Pair<Float, Distance> tmp = parseLength2(content);
if (tmp.second == Distance.PIXEL) {
// special case ==> all time % then no type define ==> % in [0.0 .. 1.0]
offset = tmp.first * 100.0f;
} else if (tmp.second != Distance.POURCENT) {
LOGGER.error("offset : " + content + " res=" + tmp.first + "," + tmp.second
+ " Not support other than pourcent %");
Log.error("offset : " + content + " res=" + tmp.first + "," + tmp.second + " Not support other than pourcent %");
} else {
offset = tmp.first;
}
@ -158,25 +153,24 @@ public class LinearGradient extends Base {
content = child.getAttribute("stop-color", "");
if (content.length() != 0) {
stopColor = parseColor(content).first;
LOGGER.trace(" color : '" + content + "' == > " + stopColor);
Log.verbose(" color : '" + content + "' == > " + stopColor);
}
content = child.getAttribute("stop-opacity", "");
if (content.length() != 0) {
float opacity = parseLength(content);
opacity = FMath.avg(0.0f, opacity, 1.0f);
stopColor = stopColor.withA(opacity);
LOGGER.trace(" opacity : '" + content + "' == > " + stopColor);
Log.verbose(" opacity : '" + content + "' == > " + stopColor);
}
this.data.add(new Pair<>(offset, stopColor));
this.data.add(new Pair<Float, Color>(offset, stopColor));
} else {
LOGGER.error(" node not suported : '" + child.getValue() + "' must be [stop]");
Log.error(" node not suported : '" + child.getValue() + "' must be [stop]");
}
}
}
if (this.data.size() != 0) {
if (!this.href.isEmpty()) {
LOGGER.error(
" node can not have an xlink:href element with sub node named: stop ==> removing href");
Log.error(" node can not have an xlink:href element with sub node named: stop ==> removing href");
this.href = "";
}
}

View File

@ -3,19 +3,18 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
import org.atriasoft.esvg.render.PointList;
import org.atriasoft.esvg.render.SegmentList;
import org.atriasoft.esvg.render.Weight;
import org.atriasoft.etk.Tools;
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.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.atriasoft.exml.parser.Tools;
/** @file
* @author Edouard DUPIN
@ -23,8 +22,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Path extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Path.class);
private record Command(
char cmd,
String[] listElem,
@ -42,35 +39,34 @@ public class Path extends Base {
}
public static PathModel createPathModel(final String d) {
final PathModel out = new PathModel();
LOGGER.trace("Parse Path : \"" + d + "\"");
final List<String> commandsSplited = Path.splitCommand(d);
PathModel out = new PathModel();
Log.verbose("Parse Path : \"" + d + "\"");
List<String> commandsSplited = Path.splitCommand(d);
String[] listDot = null;
// TODO REWORK this, can be done with a simple split and search in a list...
for (Command sss = Path.extractCmd(commandsSplited, 0); sss != null;
sss = Path.extractCmd(commandsSplited, sss.offset())) {
for (Command sss = Path.extractCmd(commandsSplited, 0); sss != null; sss = Path.extractCmd(commandsSplited, sss.offset())) {
boolean relative = false;
listDot = sss.listElem();
// LOGGER.trace("Find new command : '" + sss.cmd + "'");
// Log.verbose("Find new command : '" + sss.cmd + "'");
// if (listDot != null) {
// for (int jjj = 0; jjj < listDot.length; jjj++) {
// LOGGER.trace(" -> '" + listDot[jjj] + "'");
// Log.verbose(" -> '" + listDot[jjj] + "'");
// }
// } else {
// LOGGER.trace(" -> no elements");
// Log.verbose(" -> no elements");
// }
switch (sss.cmd) {
case 'm': // Move to (relative)
relative = true;
case 'M': // Move to (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
if (listDot.length % 2 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " must be a multiple of 2");
Log.warning("the PATH command " + sss.cmd + " must be a multiple of 2");
break;
}
// 2 Elements ...
@ -78,24 +74,22 @@ public class Path extends Base {
out.moveTo(relative, new Vector2f(Float.parseFloat(listDot[0]), Float.parseFloat(listDot[1])));
}
for (int iii = 2; iii < listDot.length; iii += 2) {
out.lineTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
out.lineTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
}
break;
case 'l': // Line to (relative)
relative = true;
case 'L': // Line to (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
if (listDot.length % 2 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " must be a multiple of 2");
Log.warning("the PATH command " + sss.cmd + " must be a multiple of 2");
break;
}
for (int iii = 0; iii < listDot.length; iii += 2) {
out.lineTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
out.lineTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
}
break;
@ -104,11 +98,11 @@ public class Path extends Base {
case 'V': // Vertical Line to (absolute)
// 1 Element ...
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
for (final String element : listDot) {
out.lineToV(relative, Float.parseFloat(element));
for (int iii = 0; iii < listDot.length; iii++) {
out.lineToV(relative, Float.parseFloat(listDot[iii]));
}
break;
@ -117,11 +111,11 @@ public class Path extends Base {
case 'H': // Horizantal Line to (absolute)
// 1 Element ...
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
for (final String element : listDot) {
out.lineToH(relative, Float.parseFloat(element));
for (int iii = 0; iii < listDot.length; iii++) {
out.lineToH(relative, Float.parseFloat(listDot[iii]));
}
break;
@ -129,18 +123,16 @@ public class Path extends Base {
relative = true;
case 'Q': // Quadratic Bezier curve (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
// 4 Elements ...
if (listDot.length % 4 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length + " (must have 4 numbers)");
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + " (must have 4 numbers)");
break;
}
for (int iii = 0; iii < listDot.length; iii += 4) {
out.bezierCurveTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
out.bezierCurveTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
new Vector2f(Float.parseFloat(listDot[iii + 2]), Float.parseFloat(listDot[iii + 3])));
}
break;
@ -149,19 +141,17 @@ public class Path extends Base {
relative = true;
case 'T': // smooth quadratic Bezier curve to (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
// 4 Elements ...
if (listDot.length % 2 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length + " (must have 2 numbers)");
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + " (must have 2 numbers)");
break;
}
// 2 Elements ...
for (int iii = 0; iii < listDot.length; iii += 2) {
out.bezierSmoothCurveTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
out.bezierSmoothCurveTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])));
}
break;
@ -169,18 +159,16 @@ public class Path extends Base {
relative = true;
case 'C': // curve to (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
// 6 Elements ...
if (listDot.length % 6 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length + "(Must be a multiple of 6)");
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + "(Must be a multiple of 6)");
break;
}
for (int iii = 0; iii < listDot.length; iii += 6) {
out.curveTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
out.curveTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
new Vector2f(Float.parseFloat(listDot[iii + 2]), Float.parseFloat(listDot[iii + 3])),
new Vector2f(Float.parseFloat(listDot[iii + 4]), Float.parseFloat(listDot[iii + 5])));
}
@ -190,18 +178,16 @@ public class Path extends Base {
relative = true;
case 'S': // smooth curve to (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
break;
}
// 4 Elements ...
if (listDot.length % 4 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length + "(Must be a multiple of 4)");
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + "(Must be a multiple of 4)");
break;
}
for (int iii = 0; iii < listDot.length; iii += 4) {
out.smoothCurveTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
out.smoothCurveTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
new Vector2f(Float.parseFloat(listDot[iii + 2]), Float.parseFloat(listDot[iii + 3])));
}
break;
@ -210,13 +196,12 @@ public class Path extends Base {
relative = true;
case 'A': // elliptical Arc (absolute)
if (listDot == null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
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 % 7 != 0) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length);
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) {
@ -228,9 +213,7 @@ public class Path extends Base {
if (Integer.parseInt(listDot[iii + 4]) == 0) {
sweepFlag = false;
}
out.ellipticTo(relative,
new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])),
Float.parseFloat(listDot[iii + 2]), largeArcFlag, sweepFlag,
out.ellipticTo(relative, new Vector2f(Float.parseFloat(listDot[iii]), Float.parseFloat(listDot[iii + 1])), Float.parseFloat(listDot[iii + 2]), largeArcFlag, sweepFlag,
new Vector2f(Float.parseFloat(listDot[iii + 5]), Float.parseFloat(listDot[iii + 6])));
}
break;
@ -239,14 +222,13 @@ public class Path extends Base {
case 'Z': // closepath (absolute)
// 0 Element ...
if (listDot != null) {
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
+ listDot.length);
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length);
break;
}
out.close(relative);
break;
default:
LOGGER.error("Unknow error : '" + sss.cmd + "'");
Log.error("Unknow error : '" + sss.cmd + "'");
}
}
return out;
@ -255,39 +237,39 @@ public class Path extends Base {
//return the next char position ... (after 'X' or NULL)
private static Command extractCmd(final List<String> input, final int offset) {
if (input.size() <= offset) {
// LOGGER.warn("parse command : END");
// Log.warning("parse command : END");
return null;
}
// LOGGER.warn("parse command : (rest) " + offset);
// Log.warning("parse command : (rest) " + offset);
// for (int iii = offset; iii < input.size(); iii++) {
// LOGGER.warn(" -[" + iii + "] '" + input.get(iii) + "'");
// Log.warning(" -[" + iii + "] '" + input.get(iii) + "'");
// }
if (input.get(offset).length() != 1) {
LOGGER.error("Error in the SVG Path : '" + input.get(offset) + "' [" + Integer.toString(offset));
Log.error("Error in the SVG Path : '" + input.get(offset) + "' [" + Integer.toString(offset));
return null;
}
final char cmd = input.get(offset).charAt(0);
char cmd = input.get(offset).charAt(0);
if (!((cmd <= 'Z' && cmd >= 'A') || (cmd <= 'z' && cmd >= 'a'))) {
LOGGER.error("Error in the SVG Path : '" + cmd + "' [" + Integer.toString(offset));
Log.error("Error in the SVG Path : '" + cmd + "' [" + Integer.toString(offset));
return null;
}
//LOGGER.trace("Find command : " + cmd);
//Log.verbose("Find command : " + cmd);
if (input.size() == offset) {
return new Command(cmd, offset + 1);
}
int iii;
for (iii = offset + 1; iii < input.size(); iii++) {
final char startElem = input.get(iii).charAt(0);
char startElem = input.get(iii).charAt(0);
if ((startElem <= 'Z' && startElem >= 'A') || (startElem <= 'z' && startElem >= 'a')) {
// find end of elements
break;
}
}
final int length = iii - (offset + 1);
int length = iii - (offset + 1);
if (length == 0) {
return new Command(cmd, null, iii);
}
final String[] outputList = new String[length];
String[] outputList = new String[length];
for (int jjj = 0; jjj < length; jjj++) {
outputList[jjj] = input.get(offset + 1 + jjj);
}
@ -295,13 +277,13 @@ public class Path extends Base {
}
static List<String> splitCommand(final String data) {
final List<String> out = new ArrayList<>();
final StringBuilder tmpString = new StringBuilder(20);
List<String> out = new ArrayList<>();
StringBuilder tmpString = new StringBuilder(20);
boolean isNumber = false;
for (final char it : data.toCharArray()) {
for (char it : data.toCharArray()) {
// ',' is here beause some people oprefer the ' ' instead of ','
if (it == ' ' || it == '\t' || it == '\r' || it == '\n' || it == ',') {
final String elements = tmpString.toString();
String elements = tmpString.toString();
if (!elements.isEmpty()) {
out.add(elements);
}
@ -318,10 +300,10 @@ public class Path extends Base {
isNumber = false;
out.add(Character.toString(it));
} else {
LOGGER.error("Can not parse path : '" + it + "'");
Log.error("Can not parse path : '" + it + "'");
}
}
final String elements = tmpString.toString();
String elements = tmpString.toString();
if (!elements.isEmpty()) {
out.add(elements);
}
@ -346,19 +328,18 @@ public class Path extends Base {
@Override
void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Path");
Log.verbose(spacingDist(level) + "DRAW esvg::Path");
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = this.listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = this.listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -373,8 +354,7 @@ public class Path extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -390,22 +370,17 @@ public class Path extends Base {
}
@Override
void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Path");
void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Path");
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = this.listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<Vector2f>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -423,9 +398,9 @@ public class Path extends Base {
// add the property of the parrent modifications ...
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
final String elementXML1 = element.getAttribute("d", "");
String elementXML1 = element.getAttribute("d", "");
if (elementXML1.length() == 0) {
LOGGER.warn("path: missing 'd' attribute or empty");
Log.warning("path: missing 'd' attribute or empty");
return false;
}
this.listElement = Path.createPathModel(elementXML1);

View File

@ -1,8 +1,5 @@
package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
@ -13,8 +10,11 @@ import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
/** @file
* @author Edouard DUPIN
@ -23,7 +23,6 @@ import org.slf4j.LoggerFactory;
*/
public class Polygon extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Polygon.class);
private final List<Vector2f> listPoint = new ArrayList<>(); //!< list of all point of the polygone
public Polygon(final PaintState parentPaintState) {
@ -31,7 +30,7 @@ public class Polygon extends Base {
}
private PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.moveTo(false, this.listPoint.get(0));
for (int iii = 1; iii < this.listPoint.size(); iii++) {
out.lineTo(false, this.listPoint.get(iii));
@ -42,26 +41,25 @@ public class Polygon extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Polygon nbPoint=" + this.listPoint.size());
Log.debug(spacingDist(spacing) + "Polygon nbPoint=" + this.listPoint.size());
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Polygon");
Log.verbose(spacingDist(level) + "DRAW esvg::Polygon");
final PathModel listElement = createPath();
PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -76,8 +74,7 @@ public class Polygon extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -90,21 +87,16 @@ public class Polygon extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Polygon");
final PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Polygon");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -119,24 +111,24 @@ public class Polygon extends Base {
parseTransform(element);
parsePaintAttr(element);
LOGGER.trace("parsed P1. trans: " + this.transformMatrix);
Log.verbose("parsed P1. trans: " + this.transformMatrix);
// add the property of the parrent modifications ...
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
LOGGER.trace("parsed P2. trans: " + this.transformMatrix);
Log.verbose("parsed P2. trans: " + this.transformMatrix);
final String sss1 = element.getAttribute("points", "");
String sss1 = element.getAttribute("points", "");
if (sss1.length() == 0) {
LOGGER.error("(l "/*+element.Pos()*/ + ") polygon: missing points attribute");
Log.error("(l "/*+element.Pos()*/ + ") polygon: missing points attribute");
return false;
}
sizeMax.value = Vector2f.ZERO;
LOGGER.trace("Parse polyline : '" + sss1 + "'");
final String[] elems = sss1.split(" ");
for (final String elem : elems) {
final Vector2f pos = Vector2f.valueOf(elem);
Log.verbose("Parse polyline : '" + sss1 + "'");
String[] elems = sss1.split(" ");
for (String elem : elems) {
Vector2f pos = Vector2f.valueOf(elem);
this.listPoint.add(pos);
sizeMax.value = Vector2f.max(sizeMax.value, pos);
}

View File

@ -1,8 +1,5 @@
package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
@ -13,8 +10,11 @@ import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
/** @file
* @author Edouard DUPIN
@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Polyline extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Polyline.class);
private final List<Vector2f> listPoint = new ArrayList<>(); //!< list of all point of the polyline
public Polyline(final PaintState parentPaintState) {
@ -30,7 +29,7 @@ public class Polyline extends Base {
}
private PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.clear();
out.moveTo(false, this.listPoint.get(0));
for (int iii = 1; iii < this.listPoint.size(); iii++) {
@ -42,26 +41,25 @@ public class Polyline extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Polyline nbPoint=" + this.listPoint.size());
Log.debug(spacingDist(spacing) + "Polyline nbPoint=" + this.listPoint.size());
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Polyline");
Log.verbose(spacingDist(level) + "DRAW esvg::Polyline");
final PathModel listElement = createPath();
PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -76,8 +74,7 @@ public class Polyline extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -90,21 +87,16 @@ public class Polyline extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Polyline");
final PathModel listElement = createPath();
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Polyline");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -124,16 +116,16 @@ public class Polyline extends Base {
// add the property of the parrent modifications ...
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
final String sss1 = element.getAttribute("points", "");
String sss1 = element.getAttribute("points", "");
if (sss1.length() == 0) {
LOGGER.error("polyline: missing points attribute");
Log.error("polyline: missing points attribute");
return false;
}
sizeMax.value = Vector2f.ZERO;
LOGGER.trace("Parse polyline : '" + sss1 + "'");
final String[] elems = sss1.split(" ");
for (final String elem : elems) {
final Vector2f pos = Vector2f.valueOf(elem);
Log.verbose("Parse polyline : '" + sss1 + "'");
String[] elems = sss1.split(" ");
for (String elem : elems) {
Vector2f pos = Vector2f.valueOf(elem);
this.listPoint.add(pos);
sizeMax.value = Vector2f.max(sizeMax.value, pos);
}

View File

@ -3,19 +3,18 @@ package org.atriasoft.esvg;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Dimension1f;
import org.atriasoft.etk.Dimension2f;
import org.atriasoft.etk.Distance;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.atriasoft.etk.Dimension;
import org.atriasoft.etk.Dimension1D;
import org.atriasoft.etk.Distance;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
/** @file
* @author Edouard DUPIN
@ -23,12 +22,11 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class RadialGradient extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(RadialGradient.class);
private Dimension2f center = new Dimension2f(new Vector2f(50, 50), Distance.POURCENT); //!< gradient position cx cy
private Dimension center = new Dimension(new Vector2f(50, 50), Distance.POURCENT); //!< gradient position cx cy
private final List<Pair<Float, Color>> data = new ArrayList<>(); //!< incompatible with href
private Dimension2f focal = new Dimension2f(new Vector2f(50, 50), Distance.POURCENT); //!< gradient Focal fx fy
private Dimension focal = new Dimension(new Vector2f(50, 50), Distance.POURCENT); //!< gradient Focal fx fy
private String href = ""; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
private Dimension1f radius = new Dimension1f(50, Distance.POURCENT); //!< Radius of the gradient
private Dimension1D radius = new Dimension1D(50, Distance.POURCENT); //!< Radius of the gradient
public SpreadMethod spread = SpreadMethod.PAD;
public GradientUnits unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
@ -38,19 +36,18 @@ public class RadialGradient extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "RadialGradient center=" + this.center + " focal=" + this.focal + " radius="
+ this.radius);
for (final Pair<Float, Color> it : this.data) {
LOGGER.debug(spacingDist(spacing + 1) + "STOP: offset=" + it.first + " color=" + it.second);
Log.debug(spacingDist(spacing) + "RadialGradient center=" + this.center + " focal=" + this.focal + " radius=" + this.radius);
for (Pair<Float, Color> it : this.data) {
Log.debug(spacingDist(spacing + 1) + "STOP: offset=" + it.first + " color=" + it.second);
}
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::RadialGradient");
Log.verbose(spacingDist(level) + "DRAW esvg::RadialGradient");
}
public Dimension2f getCenter() {
public Dimension getCenter() {
return this.center;
}
@ -59,28 +56,28 @@ public class RadialGradient extends Base {
return this.data;
}
if (document == null) {
LOGGER.error("Get null input for document");
Log.error("Get null input for document");
return this.data;
}
final Base base = document.getReference(this.href);
Base base = document.getReference(this.href);
if (base == null) {
LOGGER.error("Can not get base : '" + this.href + "'");
Log.error("Can not get base : '" + this.href + "'");
return this.data;
}
if (base instanceof final RadialGradient gradientR) {
if (base instanceof RadialGradient gradientR) {
return gradientR.getColors(document);
}
if (base instanceof final LinearGradient gradientL) {
if (base instanceof LinearGradient gradientL) {
return gradientL.getColors(document);
}
return this.data;
}
public Dimension2f getFocal() {
public Dimension getFocal() {
return this.focal;
}
public Dimension1f getRadius() {
public Dimension1D getRadius() {
return this.radius;
}
@ -104,16 +101,16 @@ public class RadialGradient extends Base {
String contentX = element.getAttribute("cx", "");
String contentY = element.getAttribute("cy", "");
if (!contentX.isEmpty() && !contentY.isEmpty()) {
this.center = Dimension2f.valueOf(contentX, contentY);
this.center = Dimension.valueOf(contentX, contentY);
}
contentX = element.getAttribute("r", "");
if (contentX != "") {
this.radius = Dimension1f.valueOf(contentX);
this.radius = Dimension1D.valueOf(contentX);
}
contentX = element.getAttribute("fx", "");
contentY = element.getAttribute("fy", "");
if (!contentX.isEmpty() && !contentY.isEmpty()) {
this.focal = Dimension2f.valueOf(contentX, contentY);
this.focal = Dimension.valueOf(contentX, contentY);
}
contentX = element.getAttribute("gradientUnits", "");
if (contentX.equals("userSpaceOnUse")) {
@ -121,8 +118,7 @@ public class RadialGradient extends Base {
} else {
this.unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
if (contentX.length() != 0 && contentX != "objectBoundingBox") {
LOGGER.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX
+ "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX + "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
}
}
contentX = element.getAttribute("spreadMethod", "");
@ -133,8 +129,7 @@ public class RadialGradient extends Base {
} else {
this.spread = SpreadMethod.PAD;
if (contentX.length() != 0 && !contentX.equals("pad")) {
LOGGER.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX
+ "' not in : {reflect/repeate/pad} use pad");
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad");
}
}
// note: xlink:href is incompatible with subNode "stop"
@ -143,20 +138,19 @@ public class RadialGradient extends Base {
this.href = this.href.substring(1);
}
// parse all sub node :
for (final XmlNode it : element.getNodes()) {
if (it instanceof final XmlElement child) {
for (XmlNode it : element.getNodes()) {
if (it instanceof XmlElement child) {
if (child.getValue().equals("stop")) {
float offset = 100;
Color stopColor = Color.NONE;
String content = child.getAttribute("offset", "");
if (content.length() != 0) {
final Pair<Float, Distance> tmp = parseLength2(content);
Pair<Float, Distance> tmp = parseLength2(content);
if (tmp.second == Distance.PIXEL) {
// special case ==> all time % then no type define ==> % in [0.0 .. 1.0]
offset = tmp.first * 100.0f;
} else if (tmp.second != Distance.POURCENT) {
LOGGER.error("offset : " + content + " res=" + tmp.first + "," + tmp.second
+ " Not support other than pourcent %");
Log.error("offset : " + content + " res=" + tmp.first + "," + tmp.second + " Not support other than pourcent %");
} else {
offset = tmp.first;
}
@ -164,24 +158,24 @@ public class RadialGradient extends Base {
content = child.getAttribute("stop-color", "");
if (content.length() != 0) {
stopColor = parseColor(content).first;
LOGGER.trace(" color : \"" + content + "\" == > " + stopColor);
Log.verbose(" color : \"" + content + "\" == > " + stopColor);
}
content = child.getAttribute("stop-opacity", "");
if (content.length() != 0) {
float opacity = parseLength(content);
opacity = FMath.avg(0.0f, opacity, 1.0f);
stopColor = stopColor.withA(opacity);
LOGGER.trace(" opacity : '" + content + "' == > " + stopColor);
Log.verbose(" opacity : '" + content + "' == > " + stopColor);
}
this.data.add(new Pair<>(offset, stopColor));
this.data.add(new Pair<Float, Color>(offset, stopColor));
} else {
LOGGER.error("node not suported : '" + child.getValue() + "' must be [stop]");
Log.error("node not suported : '" + child.getValue() + "' must be [stop]");
}
}
}
if (this.data.size() != 0) {
if (!this.href.isEmpty()) {
LOGGER.error("node can not have an xlink:href element with sub node named: stop ==> removing href");
Log.error("node can not have an xlink:href element with sub node named: stop ==> removing href");
this.href = "";
}
}

View File

@ -1,20 +1,20 @@
package org.atriasoft.esvg;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.exml.model.XmlElement;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.Point;
import org.atriasoft.esvg.render.PointList;
import org.atriasoft.esvg.render.SegmentList;
import org.atriasoft.esvg.render.Weight;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Rectangle extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Rectangle.class);
private Vector2f position = Vector2f.ZERO; //!< position of the rectangle
private Vector2f roundedCorner = Vector2f.ZERO; //!< property of the rounded corner
private Vector2f size = Vector2f.ZERO; //!< size of the rectangle
@ -37,8 +36,7 @@ public class Rectangle extends Base {
this.size = size;
}
public Rectangle(final Vector2f position, final Vector2f size, final Vector2f roundedCorner,
final PaintState parentPaintState) {
public Rectangle(final Vector2f position, final Vector2f size, final Vector2f roundedCorner, final PaintState parentPaintState) {
super(parentPaintState);
this.position = position;
this.size = size;
@ -46,7 +44,7 @@ public class Rectangle extends Base {
}
private PathModel createPath() {
final PathModel out = new PathModel();
PathModel out = new PathModel();
out.clear();
if (this.roundedCorner.x() == 0.0f || this.roundedCorner.y() == 0.0f) {
out.moveTo(false, this.position);
@ -57,20 +55,16 @@ public class Rectangle extends Base {
// Rounded rectangle
out.moveTo(false, this.position.add(this.roundedCorner.x(), 0.0f));
out.lineToH(true, this.size.x() - this.roundedCorner.x() * 2.0f);
out.curveTo(true, new Vector2f(this.roundedCorner.x() * Base.kappa90, 0.0f),
new Vector2f(this.roundedCorner.x(), this.roundedCorner.y() * (1.0f - Base.kappa90)),
out.curveTo(true, new Vector2f(this.roundedCorner.x() * Base.kappa90, 0.0f), new Vector2f(this.roundedCorner.x(), this.roundedCorner.y() * (1.0f - Base.kappa90)),
new Vector2f(this.roundedCorner.x(), this.roundedCorner.y()));
out.lineToV(true, this.size.y() - this.roundedCorner.y() * 2.0f);
out.curveTo(true, new Vector2f(0.0f, this.roundedCorner.y() * Base.kappa90),
new Vector2f(-this.roundedCorner.x() * (1.0f - Base.kappa90), this.roundedCorner.y()),
out.curveTo(true, new Vector2f(0.0f, this.roundedCorner.y() * Base.kappa90), new Vector2f(-this.roundedCorner.x() * (1.0f - Base.kappa90), this.roundedCorner.y()),
new Vector2f(-this.roundedCorner.x(), this.roundedCorner.y()));
out.lineToH(true, -(this.size.x() - this.roundedCorner.x() * 2.0f));
out.curveTo(true, new Vector2f(-this.roundedCorner.x() * Base.kappa90, 0.0f),
new Vector2f(-this.roundedCorner.x(), -this.roundedCorner.y() * (1.0f - Base.kappa90)),
out.curveTo(true, new Vector2f(-this.roundedCorner.x() * Base.kappa90, 0.0f), new Vector2f(-this.roundedCorner.x(), -this.roundedCorner.y() * (1.0f - Base.kappa90)),
new Vector2f(-this.roundedCorner.x(), -this.roundedCorner.y()));
out.lineToV(true, -(this.size.y() - this.roundedCorner.y() * 2.0f));
out.curveTo(true, new Vector2f(0.0f, -this.roundedCorner.y() * Base.kappa90),
new Vector2f(this.roundedCorner.x() * (1.0f - Base.kappa90), -this.roundedCorner.y()),
out.curveTo(true, new Vector2f(0.0f, -this.roundedCorner.y() * Base.kappa90), new Vector2f(this.roundedCorner.x() * (1.0f - Base.kappa90), -this.roundedCorner.y()),
new Vector2f(this.roundedCorner.x(), -this.roundedCorner.y()));
}
out.close();
@ -79,28 +73,25 @@ public class Rectangle extends Base {
@Override
public void display(final int spacing) {
LOGGER.debug(spacingDist(spacing) + "Rectangle : pos=" + this.position + " size=" + this.size + " corner="
+ this.roundedCorner);
Log.debug(spacingDist(spacing) + "Rectangle : pos=" + this.position + " size=" + this.size + " corner=" + this.roundedCorner);
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Rectangle: fill=" + this.paint.fill.first + "/"
+ this.paint.fill.second + " stroke=" + this.paint.stroke.first + "/" + this.paint.stroke.second);
final PathModel listElement = createPath();
Log.verbose(spacingDist(level) + "DRAW esvg::Rectangle: fill=" + this.paint.fill.first + "/" + this.paint.fill.second + " stroke=" + this.paint.stroke.first + "/" + this.paint.stroke.second);
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
listElement.display(2);
PointList listPoints = new PointList();
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(),
myRenderer.getInterpolationThreshold());
listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
//listPoints.applyMatrix(mtx);
final SegmentList listSegmentFill = new SegmentList();
final SegmentList listSegmentStroke = new SegmentList();
final Weight tmpFill = new Weight();
final Weight tmpStroke = new Weight();
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentStroke = new SegmentList();
Weight tmpFill = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
@ -115,8 +106,7 @@ public class Rectangle extends Base {
}
// check if we need to display stroke:
if (colorStroke != null) {
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap,
this.paint.lineJoin, this.paint.miterLimit);
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
@ -130,22 +120,17 @@ public class Rectangle extends Base {
}
@Override
public void drawShapePoints(
final List<List<Vector2f>> out,
final int recurtionMax,
final float threshold,
final Matrix2x3f basicTrans,
final int level) {
LOGGER.trace(spacingDist(level) + "DRAW Shape esvg::Rectangle");
final PathModel listElement = createPath();
public void drawShapePoints(final List<List<Vector2f>> out, final int recurtionMax, final float threshold, final Matrix2x3f basicTrans, final int level) {
Log.verbose(spacingDist(level) + "DRAW Shape esvg::Rectangle");
PathModel listElement = createPath();
Matrix2x3f mtx = this.transformMatrix;
mtx = mtx.multiply(basicTrans);
PointList listPoints;
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
listPoints.applyMatrix(mtx);
for (final List<Point> it : listPoints.data) {
final List<Vector2f> listPoint = new ArrayList<>();
for (final Point itDot : it) {
for (List<Point> it : listPoints.data) {
List<Vector2f> listPoint = new ArrayList<>();
for (Point itDot : it) {
listPoint.add(itDot.pos);
}
out.add(listPoint);
@ -178,8 +163,7 @@ public class Rectangle extends Base {
if (content.length() != 0) {
this.roundedCorner = this.roundedCorner.withY(parseLength(content));
}
sizeMax.value = new Vector2f(this.position.x() + this.size.x() + this.paint.strokeWidth,
this.position.y() + this.size.y() + this.paint.strokeWidth);
sizeMax.value = new Vector2f(this.position.x() + this.size.x() + this.paint.strokeWidth, this.position.y() + this.size.y() + this.paint.strokeWidth);
return true;
}
}

View File

@ -14,8 +14,6 @@ import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -23,7 +21,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Renderer {
private static final Logger LOGGER = LoggerFactory.getLogger(Renderer.class);
private static final boolean DEBUG_MODE = false;
protected ImageFloatRGBA buffer; // for debug
protected EsvgDocument document; // for debug
@ -56,33 +53,32 @@ public class Renderer {
if (!this.visualDebug) {
return;
}
final Vector2i dynamicSize = this.size.multiply(this.factor);
Vector2i dynamicSize = this.size.multiply(this.factor);
// for each lines:
for (int yyy = 0; yyy < dynamicSize.y(); ++yyy) {
// Reduce the number of lines in the subsampling parsing:
final List<Segment> availlableSegmentPixel = new ArrayList<>();
for (final Segment it : listSegment.data) {
List<Segment> availlableSegmentPixel = new ArrayList<>();
for (Segment it : listSegment.data) {
if (it.p0.y() * this.factor <= yyy + 1 && it.p1.y() * this.factor >= (yyy)) {
availlableSegmentPixel.add(it);
}
}
//find all the segment that cross the middle of the line of the center of the pixel line:
final float subSamplingCenterPos = yyy + 0.5f;
final List<Segment> availlableSegment = new ArrayList<>();
float subSamplingCenterPos = yyy + 0.5f;
List<Segment> availlableSegment = new ArrayList<>();
// find in the subList ...
for (final Segment it : availlableSegmentPixel) {
if (it.p0.y() * this.factor <= subSamplingCenterPos
&& it.p1.y() * this.factor >= subSamplingCenterPos) {
for (Segment it : availlableSegmentPixel) {
if (it.p0.y() * this.factor <= subSamplingCenterPos && it.p1.y() * this.factor >= subSamplingCenterPos) {
availlableSegment.add(it);
}
}
// x position, angle
for (final Segment it : availlableSegment) {
final Vector2f delta = it.p0.multiply(this.factor).less(it.p1.multiply(this.factor));
for (Segment it : availlableSegment) {
Vector2f delta = it.p0.multiply(this.factor).less(it.p1.multiply(this.factor));
// x = coefficent*y+bbb;
final float coefficient = delta.x() / delta.y();
final float bbb = it.p0.x() * this.factor - coefficient * it.p0.y() * this.factor;
final float xpos = coefficient * subSamplingCenterPos + bbb;
float coefficient = delta.x() / delta.y();
float bbb = it.p0.x() * this.factor - coefficient * it.p0.y() * this.factor;
float xpos = coefficient * subSamplingCenterPos + bbb;
if (xpos >= 0 && xpos < dynamicSize.x() && yyy >= 0 && yyy < dynamicSize.y()) {
if (it.direction == 1.0f) {
this.buffer.setColor((int) xpos, yyy, Color.BLUE);
@ -95,34 +91,32 @@ public class Renderer {
// for each colomn:
for (int xxx = 0; xxx < dynamicSize.x(); ++xxx) {
// Reduce the number of lines in the subsampling parsing:
final List<Segment> availlableSegmentPixel = new ArrayList<>();
for (final Segment it : listSegment.data) {
if ((it.p0.x() * this.factor <= xxx + 1 && it.p1.x() * this.factor >= (xxx))
|| (it.p0.x() * this.factor >= xxx + 1 && it.p1.x() * this.factor <= (xxx))) {
List<Segment> availlableSegmentPixel = new ArrayList<>();
for (Segment it : listSegment.data) {
if ((it.p0.x() * this.factor <= xxx + 1 && it.p1.x() * this.factor >= (xxx)) || (it.p0.x() * this.factor >= xxx + 1 && it.p1.x() * this.factor <= (xxx))) {
availlableSegmentPixel.add(it);
}
}
//find all the segment that cross the middle of the line of the center of the pixel line:
final float subSamplingCenterPos = xxx + 0.5f;
final List<Segment> availlableSegment = new ArrayList<>();
float subSamplingCenterPos = xxx + 0.5f;
List<Segment> availlableSegment = new ArrayList<>();
// find in the subList ...
for (final Segment it : availlableSegmentPixel) {
for (Segment it : availlableSegmentPixel) {
if ((it.p0.x() * this.factor <= subSamplingCenterPos && it.p1.x() * this.factor >= subSamplingCenterPos)
|| (it.p0.x() * this.factor >= subSamplingCenterPos
&& it.p1.x() * this.factor <= subSamplingCenterPos)) {
|| (it.p0.x() * this.factor >= subSamplingCenterPos && it.p1.x() * this.factor <= subSamplingCenterPos)) {
availlableSegment.add(it);
}
}
// x position, angle
for (final Segment it : availlableSegment) {
final Vector2f delta = it.p0.multiply(this.factor).less(it.p1.multiply(this.factor));
for (Segment it : availlableSegment) {
Vector2f delta = it.p0.multiply(this.factor).less(it.p1.multiply(this.factor));
// x = coefficent*y+bbb;
if (delta.x() == 0) {
continue;
}
final float coefficient = delta.y() / delta.x();
final float bbb = it.p0.y() * this.factor - coefficient * it.p0.x() * this.factor;
final float ypos = coefficient * subSamplingCenterPos + bbb;
float coefficient = delta.y() / delta.x();
float bbb = it.p0.y() * this.factor - coefficient * it.p0.x() * this.factor;
float ypos = coefficient * subSamplingCenterPos + bbb;
if (ypos >= 0 && ypos < dynamicSize.y() && xxx >= 0 && xxx < dynamicSize.y()) {
if (it.direction == 1.0f) {
this.buffer.setColor(xxx, (int) ypos, Color.BLUE);
@ -166,7 +160,6 @@ public class Renderer {
base = result;
}
*/
/*
float r = (integration.a() * integration.r() + base.a() * (1.0f - integration.a()) * base.r());
float g = (integration.a() * integration.g() + base.a() * (1.0f - integration.a()) * base.g());
float b = (integration.a() * integration.b() + base.a() * (1.0f - integration.a()) * base.b());
@ -178,27 +171,9 @@ public class Renderer {
b *= reverse;
}
return new Color(r, g, b, a);
*/
final float a1 = integration.a(); // alpha over
final float a0 = base.a(); // alpha under
final float a = a1 + a0 * (1 - a1);
final float aCalc = a != 0 ? 1 / a : 1;
final float r = (integration.r() * a1 + base.r() * a0 * (1 - a1)) * aCalc;
final float g = (integration.g() * a1 + base.g() * a0 * (1 - a1)) * aCalc;
final float b = (integration.b() * a1 + base.b() * a0 * (1 - a1)) * aCalc;
return new Color(r, g, b, a);
}
public void print(
final Weight weightFill,
final DynamicColor colorFill,
final Weight weightStroke,
final DynamicColor colorStroke,
final float opacity) {
final long startTime = System.currentTimeMillis();
public void print(final Weight weightFill, final DynamicColor colorFill, final Weight weightStroke, final DynamicColor colorStroke, final float opacity) {
if (colorFill != null) {
//colorFill.setViewPort(Pair<Vector2f, Vector2f>(new Vector2f(0,0), Vector2f(sizeX, sizeY)));
colorFill.generate(this.document);
@ -209,13 +184,11 @@ public class Renderer {
}
// all together
for (int yyy = 0; yyy < this.size.y(); ++yyy) {
final long stopTime2 = System.currentTimeMillis();
LOGGER.trace("take time to gnerate: " + (stopTime2 - startTime) + " for " + yyy + "/" + this.size.y());
for (int xxx = 0; xxx < this.size.x(); ++xxx) {
final Vector2i pos = new Vector2i(xxx, yyy);
final float valueFill = weightFill.get(pos);
final float valueStroke = weightStroke.get(pos);
Vector2i pos = new Vector2i(xxx, yyy);
float valueFill = weightFill.get(pos);
float valueStroke = weightStroke.get(pos);
// calculate merge of stroke and fill value:
Color intermediateColorFill = Color.NONE;
@ -233,8 +206,8 @@ public class Renderer {
if (Renderer.DEBUG_MODE) {
for (int deltaY = 0; deltaY < this.factor; deltaY++) {
for (int deltaX = 0; deltaX < this.factor; deltaX++) {
final int idx = xxx * this.factor + deltaX;
final int idy = yyy * this.factor + deltaY;
int idx = xxx * this.factor + deltaX;
int idy = yyy * this.factor + deltaY;
this.buffer.mergeColor(idx, idy, intermediateColor);
}
}
@ -247,19 +220,13 @@ public class Renderer {
if (Renderer.DEBUG_MODE) {
// display the gradient position:
if (colorFill instanceof final DynamicColorSpecial tmpColor) {
final SegmentList listSegment = new SegmentList();
if (colorFill instanceof DynamicColorSpecial tmpColor) {
SegmentList listSegment = new SegmentList();
// Display bounding box
listSegment.addSegment(new Point(tmpColor.viewPort.first),
new Point(new Vector2f(tmpColor.viewPort.first.x(), tmpColor.viewPort.second.y())), false);
listSegment.addSegment(
new Point(new Vector2f(tmpColor.viewPort.first.x(), tmpColor.viewPort.second.y())),
new Point(tmpColor.viewPort.second), false);
listSegment.addSegment(new Point(tmpColor.viewPort.second),
new Point(new Vector2f(tmpColor.viewPort.second.x(), tmpColor.viewPort.first.y())), false);
listSegment.addSegment(
new Point(new Vector2f(tmpColor.viewPort.second.x(), tmpColor.viewPort.first.y())),
new Point(tmpColor.viewPort.first), false);
listSegment.addSegment(new Point(tmpColor.viewPort.first), new Point(new Vector2f(tmpColor.viewPort.first.x(), tmpColor.viewPort.second.y())), false);
listSegment.addSegment(new Point(new Vector2f(tmpColor.viewPort.first.x(), tmpColor.viewPort.second.y())), new Point(tmpColor.viewPort.second), false);
listSegment.addSegment(new Point(tmpColor.viewPort.second), new Point(new Vector2f(tmpColor.viewPort.second.x(), tmpColor.viewPort.first.y())), false);
listSegment.addSegment(new Point(new Vector2f(tmpColor.viewPort.second.x(), tmpColor.viewPort.first.y())), new Point(tmpColor.viewPort.first), false);
listSegment.applyMatrix(tmpColor.matrix);
// display the gradient axis
listSegment.addSegment(new Point(tmpColor.pos1), new Point(tmpColor.pos2), false);
@ -272,8 +239,6 @@ public class Renderer {
addDebugSegment(listSegment);
}
}
final long stopTime = System.currentTimeMillis();
LOGGER.trace("take time to generate: " + (stopTime - startTime));
}
public void setInterpolationRecurtionMax(final int value) {

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.font.Glyph;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.DynamicColor;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.esvg.render.PointList;
@ -15,8 +16,6 @@ import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -24,7 +23,6 @@ import org.slf4j.LoggerFactory;
* @license MPL v2.0 (see license file)
*/
public class Text extends Base {
static final Logger LOGGER = LoggerFactory.getLogger(Text.class);
private float fontSize = 42;
private Vector2f position = Vector2f.ZERO;
private final List<TextSpan> texts = new ArrayList<>();
@ -33,79 +31,63 @@ public class Text extends Base {
super(parentPaintState);
}
public Text(final Vector2f position, final float fontSize, final String decoratedText,
final PaintState parentPaintState) {
public Text(final Vector2f position, final float fontSize, final String decoratedText, final PaintState parentPaintState) {
super(parentPaintState);
this.position = position;
this.fontSize = fontSize;
this.texts.add(new TextSpan(position, decoratedText, FontProperty.DEFAULT_FONT.withSize(fontSize),
parentPaintState.clone()));
}
public Text(final Vector2f position, final String fontName, final float fontSize, final String decoratedText,
final PaintState parentPaintState) {
super(parentPaintState);
this.position = position;
this.fontSize = fontSize;
this.texts.add(new TextSpan(position, decoratedText,
FontProperty.DEFAULT_FONT.withSize(fontSize).withFontName(fontName), parentPaintState.clone()));
this.texts.add(new TextSpan(position, decoratedText, FontProperty.DEFAULT_FONT, parentPaintState.clone()));
}
@Override
public void display(final int spacing) {
LOGGER.trace(spacingDist(spacing) + "Text : ");
for (final TextSpan elem : this.texts) {
LOGGER.debug(spacingDist(spacing + 1) + elem.toString());
Log.debug(spacingDist(spacing) + "Text : ");
for (TextSpan elem : this.texts) {
Log.debug(spacingDist(spacing + 1) + elem.toString());
}
}
@Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
LOGGER.trace(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position);
Log.warning(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position);
if (this.texts.size() == 0) {
LOGGER.trace(spacingDist(level + 1) + "No text ...");
Log.verbose(spacingDist(level + 1) + "No text ...");
return;
}
final boolean withKerning = true;
boolean withKerning = true;
for (final TextSpan elem : this.texts) {
for (TextSpan elem : this.texts) {
// get the font or a generic font of the program.
final EsvgFont font = FontCache.getFont(elem.fontState().fontName(), elem.fontState().bold(),
elem.fontState().italic());
EsvgFont font = FontCache.getFont(elem.fontState().fontName(), elem.fontState().bold(), elem.fontState().italic());
if (font == null) {
LOGGER.error("Can not get the font :" + elem.fontState());
Log.error("Can not get the font :" + elem.fontState());
return;
}
final int realSize = font.calculateFontRealHeight((int) elem.fontState().fontSize());
final float scale = realSize / font.getUnitsPerEm();
//LOGGER.warn("elem.fontState() =" + elem.fontState());
//LOGGER.warn("scale =" + scale + " font size = " + elem.fontState().fontSize() + " realSize=" + realSize);
int realSize = font.calculateFontRealHeight((int) elem.fontState().fontSize());
float scale = realSize / font.getUnitsPerEm();
float offsetWriting = 0;
int lastValue = 0;
for (final char uVal : elem.text().toCharArray()) {
LOGGER.trace(
spacingDist(level) + " elem.position = " + elem.position());
final Glyph glyph = font.getGlyph(uVal);
for (char uVal : elem.text().toCharArray()) {
Log.warning(spacingDist(level) + " elem.position = " + elem.position());
Glyph glyph = font.getGlyph(uVal);
if (glyph == null) {
//lastValue = uVal;
lastValue = uVal;
continue;
}
if (withKerning) {
offsetWriting -= glyph.getKerning(lastValue) * scale;
LOGGER.trace(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
//offsetWriting -= glyph.getKerning(lastValue) * scale;
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
lastValue = uVal;
}
final float advenceXLocal = glyph.getHorizAdvX() * scale;
float advenceXLocal = glyph.getHorizAdvX() * scale;
//Matrix2x3f mtx = this.transformMatrix;
final Vector2f tranlate = new Vector2f(elem.position().x() + offsetWriting,
elem.position().y() - font.getDescent() * scale);
LOGGER.trace("translate : " + tranlate);
final Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate);
final Matrix2x3f scaleGlyph = Matrix2x3f.createScale(new Vector2f(scale, -scale));
Vector2f tranlate = new Vector2f(elem.position().x() + offsetWriting, elem.position().y() - font.getDescent() * scale);
Log.warning("translate : " + tranlate);
Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate);
Matrix2x3f scaleGlyph = Matrix2x3f.createScale(new Vector2f(scale, -scale));
//Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate).multiply(Matrix2x3f.createScale(scale));
//mtx = translateGlyph.multiply(this.transformMatrix);
@ -122,18 +104,17 @@ public class Text extends Base {
//Matrix2x3f mtx = this.transformMatrix;
//mtx = mtx.multiply(basicTrans);
final PathModel listElement = glyph.getModel();
PathModel listElement = glyph.getModel();
if (listElement != null) {
//--------------------------------------------------
// -- Generate Fill weight
//--------------------------------------------------
final PointList listPoints = listElement.generateListPoints(level,
myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
final DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
final Weight tmpFill = new Weight();
PointList listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
Weight tmpFill = new Weight();
// Check if we need to display background
if (colorFill != null) {
final SegmentList listSegmentFill = new SegmentList();
SegmentList listSegmentFill = new SegmentList();
listSegmentFill.createSegmentList(listPoints);
colorFill.setViewPort(listSegmentFill.getViewPort());
listSegmentFill.applyMatrix(mtx);
@ -146,29 +127,23 @@ public class Text extends Base {
// -- Generate Stroke weight
//--------------------------------------------------
final Weight tmpStroke = new Weight();
Weight tmpStroke = new Weight();
DynamicColor colorStroke = null;
if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
if (colorStroke == null) {
LOGGER.trace("Color stroke is null: ...");
} else {
// check if we need to display stroke:
final SegmentList listSegmentStroke = new SegmentList();
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth,
this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
SegmentList listSegmentStroke = new SegmentList();
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
colorStroke.setViewPort(listSegmentStroke.getViewPort());
listSegmentStroke.applyMatrix(mtx);
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
tmpStroke.generate(myRenderer.getSize(), myRenderer.getNumberSubScanLine(),
listSegmentStroke);
}
tmpStroke.generate(myRenderer.getSize(), myRenderer.getNumberSubScanLine(), listSegmentStroke);
}
// add on images:
myRenderer.print(tmpFill, colorFill, tmpStroke, colorStroke, this.paint.opacity);
}
offsetWriting += advenceXLocal;
//LOGGER.warn("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
Log.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
}
}
}
@ -187,30 +162,30 @@ public class Text extends Base {
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
boolean italic = false;
final String fontStyle = element.getAttribute("font-style", "normal");
String fontStyle = element.getAttribute("font-style", "normal");
if ("italic".equals(fontStyle)) {
italic = true;
} else if ("normal".equals(fontStyle)) {
italic = false;
} else {
LOGGER.error("can not parse font-style='" + fontStyle + "' support ['normal', 'italic']");
Log.error("can not parse font-style='" + fontStyle + "' support ['normal', 'italic']");
}
boolean bold = false;
final String fontWeight = element.getAttribute("font-weight", "normal");
String fontWeight = element.getAttribute("font-weight", "normal");
if ("bold".equals(fontWeight)) {
bold = true;
} else if ("normal".equals(fontWeight)) {
bold = false;
} else {
LOGGER.error("can not parse font-weight='" + fontWeight + "' support ['normal', 'bold']");
Log.error("can not parse font-weight='" + fontWeight + "' support ['normal', 'bold']");
}
String fontFamily = element.getAttribute("font-family", "FreeSans");
if (fontStyle.contains(";")) {
fontFamily = fontFamily.split(";")[0];
}
LOGGER.info("Get font family: '" + fontFamily + "'");
Log.info("Get font family: '" + fontFamily + "'");
final float fontSize = parseLength(element.getAttribute("font-size", "50"));
float fontSize = parseLength(element.getAttribute("font-size", "50"));
this.position = Vector2f.ZERO;
String content = element.getAttribute("x", "");
@ -223,14 +198,13 @@ public class Text extends Base {
}
// parse all subElement in the Text <TSPAN/>
for (final XmlNode elem : element.getNodes()) {
if (elem instanceof final XmlElement elementSpan && "tspan".equals(elementSpan.getValue())) {
for (XmlNode elem : element.getNodes()) {
if (elem instanceof XmlElement elementSpan && "tspan".equals(elementSpan.getValue())) {
} else if (elem instanceof final XmlText elementText) {
this.texts.add(new TextSpan(this.position, elementText.getValue(),
new FontProperty(fontFamily, fontSize, bold, italic), this.paint.clone()));
} else if (elem instanceof XmlText elementText) {
this.texts.add(new TextSpan(this.position, elementText.getValue(), new FontProperty(fontFamily, fontSize, bold, italic), this.paint.clone()));
} else {
LOGGER.warn("not managed element : " + elem);
Log.warning("not managed element : " + elem);
}
}
@ -257,7 +231,7 @@ public class Text extends Base {
}
if (withKerning) {
offsetWriting -= glyph.getKerning(lastValue) * scale;
LOGGER.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
lastValue = uVal;
}
@ -283,24 +257,7 @@ record FontProperty(
float fontSize,
boolean bold,
boolean italic) {
public static final FontProperty DEFAULT_FONT = new FontProperty("FreeSans", 15, false, false);
public FontProperty withSize(final float fontSize) {
return new FontProperty(this.fontName, fontSize, this.bold, this.italic);
}
public FontProperty withFontName(final String fontName) {
return new FontProperty(fontName, this.fontSize, this.bold, this.italic);
}
public FontProperty withBold(final boolean bold) {
return new FontProperty(this.fontName, this.fontSize, bold, this.italic);
}
public FontProperty withSize(final boolean italic) {
return new FontProperty(this.fontName, this.fontSize, this.bold, italic);
}
}
record TextSpan(

View File

@ -5,14 +5,12 @@ import java.util.List;
import org.atriasoft.esvg.EsvgFont;
import org.atriasoft.esvg.Path;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.PathModel;
import org.atriasoft.exml.model.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Glyph {
private static final boolean LAZY_MODE = true;
static final Logger LOGGER = LoggerFactory.getLogger(Glyph.class);
public static Glyph valueOf(final XmlElement element) {
return Glyph.valueOf(element, null);
@ -22,45 +20,45 @@ public class Glyph {
if (element == null) {
return null;
}
final String name = element.getAttribute("glyph-name", null);
LOGGER.trace("get glyph name = '" + name + "'");
final String tmpValue = element.getAttribute("horiz-adv-x", null);
String name = element.getAttribute("glyph-name", null);
Log.verbose("get glyph name = '" + name + "'");
String tmpValue = element.getAttribute("horiz-adv-x", null);
int horizAdvX = font == null ? 100 : font.getHorizAdvX();
if (tmpValue != null && tmpValue.length() != 0) {
horizAdvX = Integer.parseInt(tmpValue);
}
LOGGER.trace(" horizAdvX= '" + horizAdvX + "'");
final String unicode = element.getAttribute("unicode", null);
LOGGER.trace(" unicode= '" + unicode + "'");
Log.verbose(" horizAdvX= '" + horizAdvX + "'");
String unicode = element.getAttribute("unicode", null);
Log.verbose(" unicode= '" + unicode + "'");
if (unicode == null) {
LOGGER.debug("Not manage glyph : '" + name + "' (missing unicode value)");
Log.debug("Not manage glyph : '" + name + "' (missing unicode value)");
return null;
}
final String d = element.getAttribute("d", null);
LOGGER.trace(" d= '" + d + "'");
String d = element.getAttribute("d", null);
Log.verbose(" d= '" + d + "'");
int unicodeValue = 0;
if (unicode.startsWith("&#x") && unicode.endsWith(";")) {
final String subElement = unicode.substring(3, unicode.length() - 1);
String subElement = unicode.substring(3, unicode.length() - 1);
if (subElement.indexOf("&") != -1) {
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
return null;
}
unicodeValue = Integer.parseInt(subElement, 16);
} else if (unicode.startsWith("&#") && unicode.endsWith(";")) {
final String subElement = unicode.substring(2, unicode.length() - 1);
String subElement = unicode.substring(2, unicode.length() - 1);
if (subElement.indexOf("&") != -1) {
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
return null;
}
unicodeValue = Integer.parseInt(subElement, 16);
} else if (unicode.length() != 1) {
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
return null;
} else {
unicodeValue = unicode.charAt(0);
}
LOGGER.trace(" unicodeValue= '" + unicodeValue + "'");
final Glyph out = new Glyph(horizAdvX, d, name, unicode, unicodeValue);
Log.verbose(" unicodeValue= '" + unicodeValue + "'");
Glyph out = new Glyph(horizAdvX, d, name, unicode, unicodeValue);
if (!Glyph.LAZY_MODE) {
// when not in lazy mode we force the parsing of the model, this permit to check the whole font... otherwise many font is really big > 8000 glyph, then it is a waste of time...
out.getModel();
@ -77,8 +75,7 @@ public class Glyph {
private int unicodeValue;
public Glyph(final int horizAdvX, final PathModel model, final String name, final String unicode,
final int unicodeValue) {
public Glyph(final int horizAdvX, final PathModel model, final String name, final String unicode, final int unicodeValue) {
this.horizAdvX = horizAdvX;
this.model = model;
this.path = null;
@ -87,8 +84,7 @@ public class Glyph {
this.unicodeValue = unicodeValue;
}
public Glyph(final int horizAdvX, final String path, final String name, final String unicode,
final int unicodeValue) {
public Glyph(final int horizAdvX, final String path, final String name, final String unicode, final int unicodeValue) {
this.horizAdvX = horizAdvX;
this.model = null;
this.path = path;
@ -109,10 +105,9 @@ public class Glyph {
if (unicodeValue == 0) {
return 0.0f;
}
for (final Kerning elem : this.kernings) {
for (Kerning elem : this.kernings) {
if (elem.unicode() == unicodeValue) {
LOGGER.trace("Get kerning between : '" + (char) this.unicodeValue + "' and '" + (char) unicodeValue
+ "' => " + elem.offset());
Log.verbose("Get kerning between : '" + (char) this.unicodeValue + "' and '" + (char) unicodeValue + "' => " + elem.offset());
return elem.offset();
}
}

View File

@ -0,0 +1,69 @@
package org.atriasoft.esvg.internal;
import io.scenarium.logger.LogLevel;
import io.scenarium.logger.Logger;
public class Log {
private static final boolean FORCE_ALL = false;
private static final String LIB_NAME = "esvg";
private static final String LIB_NAME_DRAW = Logger.getDrawableName(Log.LIB_NAME);
private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.CRITICAL);
private static final boolean PRINT_DEBUG = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.DEBUG);
private static final boolean PRINT_ERROR = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.ERROR);
private static final boolean PRINT_INFO = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.INFO);
private static final boolean PRINT_PRINT = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.PRINT);
private static final boolean PRINT_TODO = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.TODO);
private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.VERBOSE);
private static final boolean PRINT_WARNING = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.WARNING);
public static void critical(final String data) {
if (Log.PRINT_CRITICAL || Log.FORCE_ALL) {
Logger.critical(Log.LIB_NAME_DRAW, data);
}
}
public static void debug(final String data) {
if (Log.PRINT_DEBUG || Log.FORCE_ALL) {
Logger.debug(Log.LIB_NAME_DRAW, data);
}
}
public static void error(final String data) {
if (Log.PRINT_ERROR || Log.FORCE_ALL) {
Logger.error(Log.LIB_NAME_DRAW, data);
}
}
public static void info(final String data) {
if (Log.PRINT_INFO || Log.FORCE_ALL) {
Logger.info(Log.LIB_NAME_DRAW, data);
}
}
public static void print(final String data) {
if (Log.PRINT_PRINT || Log.FORCE_ALL) {
Logger.print(Log.LIB_NAME_DRAW, data);
}
}
public static void todo(final String data) {
if (Log.PRINT_TODO || Log.FORCE_ALL) {
Logger.todo(Log.LIB_NAME_DRAW, data);
}
}
public static void verbose(final String data) {
if (Log.PRINT_VERBOSE || Log.FORCE_ALL) {
Logger.verbose(Log.LIB_NAME_DRAW, data);
}
}
public static void warning(final String data) {
if (Log.PRINT_WARNING || Log.FORCE_ALL) {
Logger.warning(Log.LIB_NAME_DRAW, data);
}
}
private Log() {}
}

View File

@ -1,13 +1,12 @@
package org.atriasoft.esvg.render;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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
* @author Edouard DUPIN
@ -16,15 +15,13 @@ import org.slf4j.LoggerFactory;
*/
public interface DynamicColor {
static final Logger LOGGER = LoggerFactory.getLogger(DynamicColor.class);
public static DynamicColor createColor(final Pair<Color, String> color, final Matrix2x3f mtx) {
// Check if need to create a color:
if (color.first.a() == 0 && color.second.isEmpty()) {
return null;
}
if (color.second.isEmpty()) {
LOGGER.trace("use stroke color :" + color);
Log.error("use stroke color :" + color);
return new DynamicColorUni(color.first);
}
return new DynamicColorSpecial(color.second, mtx);

View File

@ -2,39 +2,31 @@ package org.atriasoft.esvg.render;
import java.util.List;
import org.atriasoft.esvg.SpreadMethod;
import org.atriasoft.esvg.Base;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.esvg.GradientUnits;
import org.atriasoft.esvg.LinearGradient;
import org.atriasoft.esvg.RadialGradient;
import org.atriasoft.esvg.SpreadMethod;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Dimension1f;
import org.atriasoft.etk.Dimension2f;
import org.atriasoft.etk.Dimension;
import org.atriasoft.etk.Dimension1D;
import org.atriasoft.etk.Distance;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DynamicColorSpecial implements DynamicColor {
static final Logger LOGGER = LoggerFactory.getLogger(DynamicColorSpecial.class);
protected static Vector2f getIntersect(
final Vector2f point1,
final Vector2f vect1,
final Vector2f point2,
final Vector2f vect2) {
final float diviseur = vect1.x() * vect2.y() - vect1.y() * vect2.x();
protected static Vector2f getIntersect(final Vector2f point1, final Vector2f vect1, final Vector2f point2, final Vector2f vect2) {
float diviseur = vect1.x() * vect2.y() - vect1.y() * vect2.x();
if (diviseur != 0.0f) {
final float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x()
+ vect1.y() * point2.x()) / diviseur;
float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x() + vect1.y() * point2.x()) / diviseur;
return point2.add(vect2.multiply(mmm));
}
LOGGER.error("Get divider / 0.0f");
Log.error("Get divider / 0.0f");
return point2;
}
@ -42,18 +34,11 @@ public class DynamicColorSpecial implements DynamicColor {
return DynamicColorSpecial.intersectLineToCircle(pos1, pos2, Vector2f.ZERO);
}
protected static Pair<Vector2f, Vector2f> intersectLineToCircle(
final Vector2f pos1,
final Vector2f pos2,
final Vector2f center) {
protected static Pair<Vector2f, Vector2f> intersectLineToCircle(final Vector2f pos1, final Vector2f pos2, final Vector2f center) {
return DynamicColorSpecial.intersectLineToCircle(pos1, pos2, center, 1.0f);
}
protected static Pair<Vector2f, Vector2f> intersectLineToCircle(
final Vector2f pos1,
final Vector2f pos2,
final Vector2f center,
final float radius) {
protected static Pair<Vector2f, Vector2f> intersectLineToCircle(final Vector2f pos1, final Vector2f pos2, final Vector2f center, final float radius) {
Vector2f v1;
Vector2f v2;
//vector2D from point 1 to point 2
@ -61,9 +46,9 @@ public class DynamicColorSpecial implements DynamicColor {
//vector2D from point 1 to the circle's center
v2 = center.less(pos1);
final float dot = v1.dot(v2);
final Vector2f proj1 = new Vector2f(((dot / (v1.length2())) * v1.x()), ((dot / (v1.length2())) * v1.y()));
final Vector2f midpt = pos1.add(proj1);
float dot = v1.dot(v2);
Vector2f proj1 = new Vector2f(((dot / (v1.length2())) * v1.x()), ((dot / (v1.length2())) * v1.y()));
Vector2f midpt = pos1.add(proj1);
float distToCenter = midpt.less(center).length2();
if (distToCenter > radius * radius) {
@ -117,35 +102,35 @@ public class DynamicColorSpecial implements DynamicColor {
@Override
public void generate(final EsvgDocument document) {
if (document == null) {
LOGGER.error("Get null input for document");
Log.error("Get null input for document");
}
final Base base = document.getReference(this.colorName);
Base base = document.getReference(this.colorName);
if (base == null) {
LOGGER.error("Can not get base : '" + this.colorName + "'");
Log.error("Can not get base : '" + this.colorName + "'");
return;
}
// Now we can know if we use linear or radial gradient ...
if (base instanceof final LinearGradient gradient) {
if (base instanceof LinearGradient gradient) {
this.linear = true;
LOGGER.trace("get for color linear:");
Log.verbose("get for color linear:");
gradient.display(2);
this.unit = gradient.unit;
this.spread = gradient.spread;
LOGGER.trace(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
final Vector2f size = this.viewPort.second.less(this.viewPort.first);
Log.verbose(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
Vector2f size = this.viewPort.second.less(this.viewPort.first);
final Dimension2f dimPos1 = gradient.getPosition1();
Dimension dimPos1 = gradient.getPosition1();
this.pos1 = dimPos1.getPixel(size);
if (dimPos1.getType() == Distance.POURCENT) {
this.pos1 = this.pos1.add(this.viewPort.first);
}
final Dimension2f dimPos2 = gradient.getPosition2();
Dimension dimPos2 = gradient.getPosition2();
this.pos2 = dimPos2.getPixel(size);
if (dimPos2.getType() == Distance.POURCENT) {
this.pos2 = this.pos2.add(this.viewPort.first);
}
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
final Vector2f delta = this.pos2.less(this.pos1);
Vector2f delta = this.pos2.less(this.pos1);
if (delta.x() < 0.0f) {
this.axeX = new Vector2f(-1.0f, 0.0f);
} else {
@ -162,41 +147,41 @@ public class DynamicColorSpecial implements DynamicColor {
this.axeX = this.matrix.applyScaleRotation(this.axeX);
this.axeY = this.matrix.applyScaleRotation(this.axeY);
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
final Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
final Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
this.baseSize = new Vector2f((this.pos1.less(intersecX)).length(), (this.pos1.less(intersecY)).length());
// get all the colors
this.data = gradient.getColors(document);
} else {
this.linear = false;
if (!(base instanceof final RadialGradient gradient)) {
LOGGER.error("Can not cast in a linear gradient: '" + this.colorName + "' ==> wrong type");
if (!(base instanceof RadialGradient gradient)) {
Log.error("Can not cast in a linear gradient: '" + this.colorName + "' ==> wrong type");
return;
}
LOGGER.trace("get for color Radial:");
Log.verbose("get for color Radial:");
gradient.display(2);
this.unit = gradient.unit;
this.spread = gradient.spread;
LOGGER.trace(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
final Vector2f size = this.viewPort.second.less(this.viewPort.first);
Log.verbose(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
Vector2f size = this.viewPort.second.less(this.viewPort.first);
final Dimension2f dimCenter = gradient.getCenter();
Dimension dimCenter = gradient.getCenter();
Vector2f center = dimCenter.getPixel(size);
if (dimCenter.getType() == Distance.POURCENT) {
center = center.add(this.viewPort.first);
}
final Dimension2f dimFocal = gradient.getFocal();
Dimension dimFocal = gradient.getFocal();
Vector2f focal = dimFocal.getPixel(size);
if (dimFocal.getType() == Distance.POURCENT) {
focal = focal.add(this.viewPort.first);
}
final Dimension1f dimRadius = gradient.getRadius();
Dimension1D dimRadius = gradient.getRadius();
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object)..
if (center == focal) {
this.centerIsFocal = true;
this.pos2 = new Vector2f(dimRadius.getPixel(size.x()), dimRadius.getPixel(size.y()));
this.pos2 = this.pos2.add(center);
final Vector2f delta = center.less(this.pos2);
Vector2f delta = center.less(this.pos2);
if (delta.x() < 0.0f) {
this.axeX = new Vector2f(-1.0f, 0.0f);
} else {
@ -213,8 +198,7 @@ public class DynamicColorSpecial implements DynamicColor {
this.axeX = center.less(focal).safeNormalize();
this.axeY = new Vector2f(this.axeX.y(), -this.axeX.x());
this.pos2 = this.axeX.multiply(dimRadius.getPixel(size.x()))
.add(this.axeY.multiply(dimRadius.getPixel(size.y())));
this.pos2 = this.axeX.multiply(dimRadius.getPixel(size.x())).add(this.axeY.multiply(dimRadius.getPixel(size.y())));
this.pos2 = this.pos2.add(center);
this.pos1 = center;
}
@ -225,21 +209,20 @@ public class DynamicColorSpecial implements DynamicColor {
this.axeX = this.matrix.applyScaleRotation(this.axeX);
this.axeY = this.matrix.applyScaleRotation(this.axeY);
// in the basic version of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
final Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
final Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
this.baseSize = new Vector2f((intersecX.less(this.pos1)).length(), (intersecY.less(this.pos1)).length());
if (!this.centerIsFocal) {
this.focalLength = (center.less(this.matrix.multiply(focal))).length();
if (this.focalLength >= this.baseSize.x()) {
LOGGER.debug("Change position of the Focal ... ==> set it inside the circle");
Log.debug("Change position of the Focal ... ==> set it inside the circle");
this.focalLength = this.baseSize.x() * 0.999998f;
this.clipOut = true;
} else {
this.clipOut = false;
}
}
LOGGER.trace("baseSize=" + this.baseSize + " this.pos1=" + this.pos1 + " dim=" + dimCenter
+ " this.focal=" + this.focal + " this.pos2=" + this.pos2 + " dim=" + dimRadius);
Log.verbose("baseSize=" + this.baseSize + " this.pos1=" + this.pos1 + " dim=" + dimCenter + " this.focal=" + this.focal + " this.pos2=" + this.pos2 + " dim=" + dimRadius);
// get all the colors
this.data = gradient.getColors(document);
}
@ -259,13 +242,12 @@ public class DynamicColorSpecial implements DynamicColor {
private Color getColorLinear(final Vector2i pos) {
float ratio = 0.0f;
if (this.unit == GradientUnits.GRADIENT_UNITS_USER_SPACE_ON_USE) {
final Vector2f vectorBase = this.pos2.less(this.pos1);
final Vector2f vectorOrtho = new Vector2f(vectorBase.y(), -vectorBase.x());
final Vector2f intersec = DynamicColorSpecial.getIntersect(this.pos1, vectorBase,
new Vector2f(pos.x(), pos.y()), vectorOrtho);
final float baseSize = vectorBase.length();
final Vector2f vectorBaseDraw = intersec.less(this.pos1);
final float baseDraw = vectorBaseDraw.length();
Vector2f vectorBase = this.pos2.less(this.pos1);
Vector2f vectorOrtho = new Vector2f(vectorBase.y(), -vectorBase.x());
Vector2f intersec = DynamicColorSpecial.getIntersect(this.pos1, vectorBase, new Vector2f(pos.x(), pos.y()), vectorOrtho);
float baseSize = vectorBase.length();
Vector2f vectorBaseDraw = intersec.less(this.pos1);
float baseDraw = vectorBaseDraw.length();
ratio = baseDraw / baseSize;
switch (this.spread) {
default:
@ -293,12 +275,10 @@ public class DynamicColorSpecial implements DynamicColor {
}
} else {
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object..
final Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX,
new Vector2f(pos.x(), pos.y()), this.axeY);
final Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY,
new Vector2f(pos.x(), pos.y()), this.axeX);
final Vector2f vectorBaseDrawX = intersecX.less(this.pos1);
final Vector2f vectorBaseDrawY = intersecY.less(this.pos1);
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, new Vector2f(pos.x(), pos.y()), this.axeY);
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, new Vector2f(pos.x(), pos.y()), this.axeX);
Vector2f vectorBaseDrawX = intersecX.less(this.pos1);
Vector2f vectorBaseDrawY = intersecY.less(this.pos1);
float baseDrawX = vectorBaseDrawX.length();
float baseDrawY = vectorBaseDrawY.length();
if (this.axeX.dot(vectorBaseDrawX) < 0) {
@ -309,8 +289,7 @@ public class DynamicColorSpecial implements DynamicColor {
}
if (this.baseSize.x() + this.baseSize.y() != 0.0f) {
if (this.baseSize.x() != 0.0f && this.baseSize.y() != 0.0f) {
ratio = (baseDrawX * this.baseSize.y() + baseDrawY * this.baseSize.x())
/ (this.baseSize.x() * this.baseSize.y() * 2.0f);
ratio = (baseDrawX * this.baseSize.y() + baseDrawY * this.baseSize.x()) / (this.baseSize.x() * this.baseSize.y() * 2.0f);
} else if (this.baseSize.x() != 0.0f) {
ratio = baseDrawX / this.baseSize.x();
} else {
@ -349,15 +328,10 @@ public class DynamicColorSpecial implements DynamicColor {
if (ratio <= this.data.get(iii).first * 0.01f) {
float localRatio = ratio - this.data.get(iii - 1).first * 0.01f;
localRatio = localRatio / ((this.data.get(iii).first - this.data.get(iii - 1).first) * 0.01f);
return new Color(
this.data.get(iii - 1).second.r() * (1.0 - localRatio)
+ this.data.get(iii).second.r() * localRatio,
this.data.get(iii - 1).second.g() * (1.0 - localRatio)
+ this.data.get(iii).second.g() * localRatio,
this.data.get(iii - 1).second.b() * (1.0 - localRatio)
+ this.data.get(iii).second.b() * localRatio,
this.data.get(iii - 1).second.a() * (1.0 - localRatio)
+ this.data.get(iii).second.a() * localRatio);
return new Color(this.data.get(iii - 1).second.r() * (1.0 - localRatio) + this.data.get(iii).second.r() * localRatio,
this.data.get(iii - 1).second.g() * (1.0 - localRatio) + this.data.get(iii).second.g() * localRatio,
this.data.get(iii - 1).second.b() * (1.0 - localRatio) + this.data.get(iii).second.b() * localRatio,
this.data.get(iii - 1).second.a() * (1.0 - localRatio) + this.data.get(iii).second.a() * localRatio);
}
}
return Color.GREEN;
@ -366,12 +340,10 @@ public class DynamicColorSpecial implements DynamicColor {
private Color getColorRadial(final Vector2i pos) {
float ratio = 0.0f;
// in the basic vertion of the gradient the color is calculated with the ration in X and Y in the bonding box associated (it is rotate with the object)..
final Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX,
new Vector2f(pos.x(), pos.y()), this.axeY);
final Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY,
new Vector2f(pos.x(), pos.y()), this.axeX);
final Vector2f vectorBaseDrawX = intersecX.less(this.pos1);
final Vector2f vectorBaseDrawY = intersecY.less(this.pos1);
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, new Vector2f(pos.x(), pos.y()), this.axeY);
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, new Vector2f(pos.x(), pos.y()), this.axeX);
Vector2f vectorBaseDrawX = intersecX.less(this.pos1);
Vector2f vectorBaseDrawY = intersecY.less(this.pos1);
float baseDrawX = vectorBaseDrawX.length();
float baseDrawY = vectorBaseDrawY.length();
// specal case when focal == center (this is faster ...)
@ -404,16 +376,15 @@ public class DynamicColorSpecial implements DynamicColor {
if (this.clipOut && baseDrawX <= -1.0f) {
ratio = 1.0f;
} else {
final float tmpLength = -this.focalLength / this.baseSize.x();
final Vector2f focalCenter = new Vector2f(tmpLength, 0.0f);
final Vector2f currentPoint = new Vector2f(baseDrawX, baseDrawY);
float tmpLength = -this.focalLength / this.baseSize.x();
Vector2f focalCenter = new Vector2f(tmpLength, 0.0f);
Vector2f currentPoint = new Vector2f(baseDrawX, baseDrawY);
if (focalCenter == currentPoint) {
ratio = 0.0f;
} else {
final Pair<Vector2f, Vector2f> positions = DynamicColorSpecial.intersectLineToCircle(focalCenter,
currentPoint);
final float lenghtBase = currentPoint.less(focalCenter).length();
final float lenghtBorder1 = positions.first.less(focalCenter).length();
Pair<Vector2f, Vector2f> positions = DynamicColorSpecial.intersectLineToCircle(focalCenter, currentPoint);
float lenghtBase = currentPoint.less(focalCenter).length();
float lenghtBorder1 = positions.first.less(focalCenter).length();
//float lenghtBorder2 = positions.second.less(focalCenter).length();
ratio = lenghtBase / lenghtBorder1;
}
@ -447,15 +418,10 @@ public class DynamicColorSpecial implements DynamicColor {
if (ratio <= this.data.get(iii).first * 0.01f) {
float localRatio = ratio - this.data.get(iii - 1).first * 0.01f;
localRatio = localRatio / ((this.data.get(iii).first - this.data.get(iii - 1).first) * 0.01f);
return new Color(
this.data.get(iii - 1).second.r() * (1.0 - localRatio)
+ this.data.get(iii).second.r() * localRatio,
this.data.get(iii - 1).second.g() * (1.0 - localRatio)
+ this.data.get(iii).second.g() * localRatio,
this.data.get(iii - 1).second.b() * (1.0 - localRatio)
+ this.data.get(iii).second.b() * localRatio,
this.data.get(iii - 1).second.a() * (1.0 - localRatio)
+ this.data.get(iii).second.a() * localRatio);
return new Color(this.data.get(iii - 1).second.r() * (1.0 - localRatio) + this.data.get(iii).second.r() * localRatio,
this.data.get(iii - 1).second.g() * (1.0 - localRatio) + this.data.get(iii).second.g() * localRatio,
this.data.get(iii - 1).second.b() * (1.0 - localRatio) + this.data.get(iii).second.b() * localRatio,
this.data.get(iii - 1).second.a() * (1.0 - localRatio) + this.data.get(iii).second.a() * localRatio);
}
}
return Color.GREEN;

View File

@ -5,12 +5,11 @@ import java.util.List;
import org.atriasoft.esvg.CapMode;
import org.atriasoft.esvg.JoinMode;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -19,41 +18,29 @@ import org.slf4j.LoggerFactory;
*/
public class PathModel {
static final Logger LOGGER = LoggerFactory.getLogger(PathModel.class);
private static void interpolateCubicBezier(
final List<Point> listPoint,
final int recurtionMax,
final float threshold,
final Vector2f pos1,
final Vector2f pos2,
final Vector2f pos3,
final Vector2f pos4,
final int level,
final PointType type) {
private static void interpolateCubicBezier(final List<Point> listPoint, final int recurtionMax, final float threshold, final Vector2f pos1, final Vector2f pos2, final Vector2f pos3,
final Vector2f pos4, final int level, final PointType type) {
if (level > recurtionMax) {
return;
}
final Vector2f pos12 = pos1.add(pos2).multiply(0.5f);
final Vector2f pos23 = pos2.add(pos3).multiply(0.5f);
final Vector2f pos34 = pos3.add(pos4).multiply(0.5f);
Vector2f pos12 = pos1.add(pos2).multiply(0.5f);
Vector2f pos23 = pos2.add(pos3).multiply(0.5f);
Vector2f pos34 = pos3.add(pos4).multiply(0.5f);
final Vector2f delta = pos4.less(pos1);
final float distance2 = Math.abs(((pos2.x() - pos4.x()) * delta.y() - (pos2.y() - pos4.y()) * delta.x()));
final float distance3 = Math.abs(((pos3.x() - pos4.x()) * delta.y() - (pos3.y() - pos4.y()) * delta.x()));
Vector2f delta = pos4.less(pos1);
float distance2 = Math.abs(((pos2.x() - pos4.x()) * delta.y() - (pos2.y() - pos4.y()) * delta.x()));
float distance3 = Math.abs(((pos3.x() - pos4.x()) * delta.y() - (pos3.y() - pos4.y()) * delta.x()));
if ((distance2 + distance3) * (distance2 + distance3) < threshold * delta.length2()) {
listPoint.add(new Point(pos4, type));
return;
}
final Vector2f pos123 = pos12.add(pos23).multiply(0.5f);
final Vector2f pos234 = pos23.add(pos34).multiply(0.5f);
final Vector2f pos1234 = pos123.add(pos234).multiply(0.5f);
Vector2f pos123 = pos12.add(pos23).multiply(0.5f);
Vector2f pos234 = pos23.add(pos34).multiply(0.5f);
Vector2f pos1234 = pos123.add(pos234).multiply(0.5f);
PathModel.interpolateCubicBezier(listPoint, recurtionMax, threshold, pos1, pos12, pos123, pos1234, level + 1,
PointType.interpolation);
PathModel.interpolateCubicBezier(listPoint, recurtionMax, threshold, pos1234, pos234, pos34, pos4, level + 1,
type);
PathModel.interpolateCubicBezier(listPoint, recurtionMax, threshold, pos1, pos12, pos123, pos1234, level + 1, PointType.interpolation);
PathModel.interpolateCubicBezier(listPoint, recurtionMax, threshold, pos1234, pos234, pos34, pos4, level + 1, type);
}
/**
@ -108,24 +95,20 @@ public class PathModel {
}
public void display(final int spacing) {
//LOGGER.trace(PathModel.spacingDist(spacing) + "Path");
for (final Element it : this.listElement) {
Log.warning(PathModel.spacingDist(spacing) + "Path");
for (Element it : this.listElement) {
if (it == null) {
continue;
}
//LOGGER.trace(PathModel.spacingDist(spacing + 1) + it);
Log.warning(PathModel.spacingDist(spacing + 1) + it);
}
}
public Weight drawFill(
final Vector2i size,
final Matrix2x3f basicTrans,
final int level,
final RenderingConfig config) {
public Weight drawFill(final Vector2i size, final Matrix2x3f basicTrans, final int level, final RenderingConfig config) {
PointList listPoints = new PointList();
listPoints = generateListPoints(level, config.recurtionMax(), config.interpolationThreshold());
final SegmentList listSegment = new SegmentList();
final Weight weight = new Weight();
SegmentList listSegment = new SegmentList();
Weight weight = new Weight();
// Check if we need to display background
listSegment.createSegmentList(listPoints);
listSegment.applyMatrix(basicTrans);
@ -134,16 +117,11 @@ public class PathModel {
return weight;
}
public Weight drawStroke(
final Vector2i size,
final Matrix2x3f basicTrans,
final int level,
final float strokeWidth,
final RenderingConfig config) {
public Weight drawStroke(final Vector2i size, final Matrix2x3f basicTrans, final int level, final float strokeWidth, final RenderingConfig config) {
PointList listPoints = new PointList();
listPoints = generateListPoints(level, config.recurtionMax(), config.interpolationThreshold());
final SegmentList listSegment = new SegmentList();
final Weight weight = new Weight();
SegmentList listSegment = new SegmentList();
Weight weight = new Weight();
// Check if we need to display background
listSegment.createSegmentListStroke(listPoints, strokeWidth, CapMode.BUTT, JoinMode.MITER, 4.0f);
listSegment.applyMatrix(basicTrans);
@ -152,13 +130,7 @@ public class PathModel {
return weight;
}
public void ellipticTo(
final boolean relative,
final Vector2f radius,
final float angle,
final boolean largeArcFlag,
final boolean sweepFlag,
final Vector2f pos) {
public void ellipticTo(final boolean relative, final Vector2f radius, final float angle, final boolean largeArcFlag, final boolean sweepFlag, final Vector2f pos) {
this.listElement.add(new ElementElliptic(relative, radius, angle, largeArcFlag, sweepFlag, pos));
}
@ -171,23 +143,22 @@ public class PathModel {
}
public PointList generateListPoints(final int level, final int recurtionMax, final float threshold) {
LOGGER.trace(PathModel.spacingDist(level) + "Generate List Points ... from a path");
final PointList out = new PointList();
Log.verbose(PathModel.spacingDist(level) + "Generate List Points ... from a path");
PointList out = new PointList();
List<Point> tmpListPoint = new ArrayList<>();
Vector2f lastPosition = Vector2f.ZERO;
Vector2f lastAngle = Vector2f.ZERO;
// Foreach element, we move in the path:
for (final Element it : this.listElement) {
for (Element it : this.listElement) {
if (it == null) {
continue;
}
LOGGER.trace(PathModel.spacingDist(level + 1) + " Draw : " + it.toString());
Log.verbose(PathModel.spacingDist(level + 1) + " Draw : " + it.toString());
switch (it.getType()) {
case STOP:
if (tmpListPoint.size() != 0) {
if (tmpListPoint.size() == 0) {
LOGGER.warn(
PathModel.spacingDist(level + 1) + " Request path stop of not starting path ...");
Log.warning(PathModel.spacingDist(level + 1) + " Request path stop of not starting path ...");
} else {
tmpListPoint.get(tmpListPoint.size() - 1).setEndPath();
out.addList(tmpListPoint);
@ -200,17 +171,14 @@ public class PathModel {
case CLOSE:
if (tmpListPoint.size() != 0) {
if (tmpListPoint.size() == 0) {
LOGGER.warn(
PathModel.spacingDist(level + 1) + " Request path close of not starting path ...");
Log.warning(PathModel.spacingDist(level + 1) + " Request path close of not starting path ...");
} else {
// find the previous tart of the path ...
tmpListPoint.get(0).type = PointType.join;
// Remove the last point if it is the same position...
final Vector2f delta = (tmpListPoint.get(0).pos
.less(tmpListPoint.get(tmpListPoint.size() - 1).pos)).abs();
Vector2f delta = (tmpListPoint.get(0).pos.less(tmpListPoint.get(tmpListPoint.size() - 1).pos)).abs();
if (delta.x() <= 0.00001 && delta.y() <= 0.00001) {
LOGGER.trace(" Remove point Z property : "
+ tmpListPoint.get(tmpListPoint.size() - 1).pos + " with delta=" + delta);
Log.verbose(" Remove point Z property : " + tmpListPoint.get(tmpListPoint.size() - 1).pos + " with delta=" + delta);
tmpListPoint.remove(tmpListPoint.size() - 1);
}
out.addList(tmpListPoint);
@ -276,15 +244,14 @@ public class PathModel {
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
} {
final Vector2f lastPosStore = lastPosition;
Vector2f lastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f pos1 = lastPosition.add(it.getPos1());
final Vector2f pos2 = lastPosition.add(it.getPos2());
final Vector2f pos = lastPosition.add(it.getPos());
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2,
pos, 0, PointType.join);
Vector2f pos1 = lastPosition.add(it.getPos1());
Vector2f pos2 = lastPosition.add(it.getPos2());
Vector2f pos = lastPosition.add(it.getPos());
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2, pos, 0, PointType.join);
lastPosition = pos;
lastAngle = pos2;
}
@ -294,16 +261,15 @@ public class PathModel {
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
} {
final Vector2f lastPosStore = lastPosition;
Vector2f lastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f pos2 = lastPosition.add(it.getPos2());
final Vector2f pos = lastPosition.add(it.getPos());
Vector2f pos2 = lastPosition.add(it.getPos2());
Vector2f pos = lastPosition.add(it.getPos());
// generate Pos 1
final Vector2f pos1 = lastPosStore.multiply(2.0f).less(lastAngle);
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2,
pos, 0, PointType.join);
Vector2f pos1 = lastPosStore.multiply(2.0f).less(lastAngle);
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2, pos, 0, PointType.join);
lastPosition = pos;
lastAngle = pos2;
}
@ -313,17 +279,16 @@ public class PathModel {
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
} {
final Vector2f lastPosStore = lastPosition;
Vector2f lastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f pos = lastPosition.add(it.getPos());
final Vector2f tmp1 = lastPosition.add(it.getPos1());
Vector2f pos = lastPosition.add(it.getPos());
Vector2f tmp1 = lastPosition.add(it.getPos1());
// generate pos1 and pos2
final Vector2f pos1 = lastPosStore.add(tmp1.less(lastPosStore).multiply(0.666666666f));
final Vector2f pos2 = pos.add(tmp1.less(pos).multiply(0.666666666f));
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2,
pos, 0, PointType.join);
Vector2f pos1 = lastPosStore.add(tmp1.less(lastPosStore).multiply(0.666666666f));
Vector2f pos2 = pos.add(tmp1.less(pos).multiply(0.666666666f));
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2, pos, 0, PointType.join);
lastPosition = pos;
lastAngle = tmp1;
}
@ -333,17 +298,16 @@ public class PathModel {
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
} {
final Vector2f lastPosStore = lastPosition;
Vector2f lastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f pos = lastPosition.add(it.getPos());
final Vector2f tmp1 = lastPosStore.multiply(2.0f).less(lastAngle);
Vector2f pos = lastPosition.add(it.getPos());
Vector2f tmp1 = lastPosStore.multiply(2.0f).less(lastAngle);
// generate pos1 and pos2
final Vector2f pos1 = lastPosStore.add(tmp1.less(lastPosStore).multiply(0.666666666f));
final Vector2f pos2 = pos.add(tmp1.less(pos).multiply(0.66666666f));
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2,
pos, 0, PointType.join);
Vector2f pos1 = lastPosStore.add(tmp1.less(lastPosStore).multiply(0.666666666f));
Vector2f pos2 = pos.add(tmp1.less(pos).multiply(0.66666666f));
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2, pos, 0, PointType.join);
lastPosition = pos;
lastAngle = tmp1;
}
@ -353,28 +317,25 @@ public class PathModel {
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
} {
final ElementElliptic tmpIt = (ElementElliptic) it;
LOGGER.info(
"TODO:" + PathModel.spacingDist(level + 1) + " Elliptic arc: radius=" + tmpIt.getPos1());
LOGGER.info("TODO:" + PathModel.spacingDist(level + 1) + " angle=" + tmpIt.angle);
LOGGER.info("TODO:" + PathModel.spacingDist(level + 1) + " this.largeArcFlag="
+ tmpIt.largeArcFlag);
LOGGER.info("TODO:" + PathModel.spacingDist(level + 1) + " this.sweepFlag="
+ tmpIt.sweepFlag);
ElementElliptic tmpIt = (ElementElliptic) it;
Log.todo(PathModel.spacingDist(level + 1) + " Elliptic arc: radius=" + tmpIt.getPos1());
Log.todo(PathModel.spacingDist(level + 1) + " angle=" + tmpIt.angle);
Log.todo(PathModel.spacingDist(level + 1) + " this.largeArcFlag=" + tmpIt.largeArcFlag);
Log.todo(PathModel.spacingDist(level + 1) + " this.sweepFlag=" + tmpIt.sweepFlag);
final Vector2f lastPosStore = lastPosition;
Vector2f lastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f pos = lastPosition.add(it.getPos());
final float rotationX = tmpIt.angle * ((float) Math.PI / 180.0f);
Vector2f pos = lastPosition.add(it.getPos());
float rotationX = tmpIt.angle * ((float) Math.PI / 180.0f);
Vector2f radius = tmpIt.getPos1();
//this.debugInformation.addSegment(lastPosStore, pos);
Vector2f delta = lastPosStore.less(pos);
float ddd = delta.length();
if (ddd < 1e-6f || radius.x() < 1e-6f || radius.y() < 1e-6f) {
LOGGER.warn("Degenerate arc in Line");
Log.warning("Degenerate arc in Line");
if (tmpListPoint.size() == 0) {
tmpListPoint.add(new Point(lastPosition, PointType.join));
}
@ -384,21 +345,18 @@ public class PathModel {
// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
// procedure describe here : http://www.w3.org/TR/SVG11/implnote.html#ArcConversionCenterToEndpoint
// Compute delta'
final Matrix2x3f matrixRotationCenter = Matrix2x3f.createRotate(-rotationX);
final Vector2f deltaPrim = matrixRotationCenter.multiply(delta.multiply(0.5f));
ddd = (deltaPrim.x() * deltaPrim.x()) / (radius.x() * radius.x())
+ (deltaPrim.y() * deltaPrim.y()) / (radius.y() * radius.y());
Matrix2x3f matrixRotationCenter = Matrix2x3f.createRotate(-rotationX);
Vector2f deltaPrim = matrixRotationCenter.multiply(delta.multiply(0.5f));
ddd = (deltaPrim.x() * deltaPrim.x()) / (radius.x() * radius.x()) + (deltaPrim.y() * deltaPrim.y()) / (radius.y() * radius.y());
if (ddd > 1.0f) {
ddd = (float) Math.sqrt(ddd);
radius = radius.multiply(ddd);
}
// Compute center'
float sss = 0.0f;
float ssa = radius.x() * radius.x() * radius.y() * radius.y()
- radius.x() * radius.x() * deltaPrim.y() * deltaPrim.y()
float ssa = radius.x() * radius.x() * radius.y() * radius.y() - radius.x() * radius.x() * deltaPrim.y() * deltaPrim.y()
- radius.y() * radius.y() * deltaPrim.x() * deltaPrim.x();
final float ssb = radius.x() * radius.x() * deltaPrim.y() * deltaPrim.y()
+ radius.y() * radius.y() * deltaPrim.x() * deltaPrim.x();
float ssb = radius.x() * radius.x() * deltaPrim.y() * deltaPrim.y() + radius.y() * radius.y() * deltaPrim.x() * deltaPrim.x();
if (ssa < 0.0f) {
ssa = 0.0f;
}
@ -408,21 +366,19 @@ public class PathModel {
if (tmpIt.largeArcFlag == tmpIt.sweepFlag) {
sss *= -1.0f;
}
final Vector2f centerPrime = new Vector2f(sss * radius.x() * deltaPrim.y() / radius.y(),
sss * -radius.y() * deltaPrim.x() / radius.x());
Vector2f centerPrime = new Vector2f(sss * radius.x() * deltaPrim.y() / radius.y(), sss * -radius.y() * deltaPrim.x() / radius.x());
// Compute center from center'
final Matrix2x3f matrix = Matrix2x3f.createRotate(rotationX);
final Vector2f center = lastPosStore.multiply(pos).multiply(0.5f)
.add(matrix.multiply(centerPrime));
Matrix2x3f matrix = Matrix2x3f.createRotate(rotationX);
Vector2f center = lastPosStore.multiply(pos).multiply(0.5f).add(matrix.multiply(centerPrime));
//this.debugInformation.addSegment(center-Vector2f(3.0,3.0), center+Vector2f(3.0,3.0));
// this.debugInformation.addSegment(center-Vector2f(3.0,-3.0), center+Vector2f(3.0,-3.0));
// Calculate theta1, and delta theta.
final Vector2f vectorA = deltaPrim.less(centerPrime).devide(radius);
final Vector2f vectorB = deltaPrim.add(centerPrime).devide(radius.multiply(-1.0f));
Vector2f vectorA = deltaPrim.less(centerPrime).devide(radius);
Vector2f vectorB = deltaPrim.add(centerPrime).devide(radius.multiply(-1.0f));
//this.debugInformation.addSegment(center, center+vectorA*radius.x());
//this.debugInformation.addSegment(center, center+vectorB*radius.y());
// Initial angle
final float theta1 = PathModel.vectorAngle(new Vector2f(1.0f, 0.0f), vectorA);
float theta1 = PathModel.vectorAngle(new Vector2f(1.0f, 0.0f), vectorA);
// Delta angle
float deltaTheta = PathModel.vectorAngle(vectorA, vectorB);
// special case of invert angle...
@ -441,9 +397,9 @@ public class PathModel {
matrix.translate(center);
// Split arc into max 90 degree segments.
// The loop assumes an iteration per end point (including start and end), this +1.
final int ndivs = (int) (Math.abs(deltaTheta) / ((float) Math.PI * 0.5f)) + 1;
int ndivs = (int) (Math.abs(deltaTheta) / ((float) Math.PI * 0.5f)) + 1;
final float hda = (deltaTheta / ndivs) * 0.5f;
float hda = (deltaTheta / ndivs) * 0.5f;
float kappa = (float) Math.abs(4.0f / 3.0f * (1.0f - Math.cos(hda)) / Math.sin(hda));
if (deltaTheta < 0.0f) {
kappa = -kappa;
@ -451,24 +407,21 @@ public class PathModel {
Vector2f pointPosPrevious = Vector2f.ZERO;
Vector2f tangentPrevious = Vector2f.ZERO;
for (int iii = 0; iii <= ndivs; ++iii) {
final float a = theta1 + deltaTheta * ((float) iii / (float) ndivs);
float a = theta1 + deltaTheta * ((float) iii / (float) ndivs);
delta = new Vector2f(FMath.cos(a), FMath.sin(a));
// position
final Vector2f pointPos = matrix
.multiply(new Vector2f(delta.x() * radius.x(), delta.y() * radius.y()));
Vector2f pointPos = matrix.multiply(new Vector2f(delta.x() * radius.x(), delta.y() * radius.y()));
// tangent
final Vector2f tangent = matrix.applyScaleRotation(
new Vector2f(-delta.y() * radius.x() * kappa, delta.x() * radius.y() * kappa));
Vector2f tangent = matrix.applyScaleRotation(new Vector2f(-delta.y() * radius.x() * kappa, delta.x() * radius.y() * kappa));
if (iii > 0) {
final Vector2f zlastPosStore = lastPosition;
Vector2f zlastPosStore = lastPosition;
if (!it.getRelative()) {
lastPosition = Vector2f.ZERO;
}
final Vector2f zpos1 = pointPosPrevious.add(tangentPrevious);
final Vector2f zpos2 = pointPos.less(tangent);
final Vector2f zpos = pointPos;
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, zlastPosStore,
zpos1, zpos2, zpos, 0, PointType.join);
Vector2f zpos1 = pointPosPrevious.add(tangentPrevious);
Vector2f zpos2 = pointPos.less(tangent);
Vector2f zpos = pointPos;
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, zlastPosStore, zpos1, zpos2, zpos, 0, PointType.join);
lastPosition = zpos;
lastAngle = zpos2;
}
@ -480,13 +433,13 @@ public class PathModel {
}
break;
default:
LOGGER.error(PathModel.spacingDist(level + 1) + " Unknow PATH commant (internal error)");
Log.error(PathModel.spacingDist(level + 1) + " Unknow PATH commant (internal error)");
break;
}
}
// special case : No request end of path ==> open path:
if (tmpListPoint.size() != 0) {
LOGGER.trace("Auto-end PATH");
Log.verbose("Auto-end PATH");
tmpListPoint.get(tmpListPoint.size() - 1).setEndPath();
out.addList(tmpListPoint);
tmpListPoint = new ArrayList<>();

View File

@ -1,8 +1,7 @@
package org.atriasoft.esvg.render;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.math.Vector2f;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** @file
* @author Edouard DUPIN
@ -11,7 +10,6 @@ import org.slf4j.LoggerFactory;
*/
public class Point {
static final Logger LOGGER = LoggerFactory.getLogger(Point.class);
public Vector2f delta = Vector2f.ZERO;
public float len = 0;
public Vector2f miterAxe = Vector2f.ZERO;
@ -45,12 +43,12 @@ public class Point {
void setEndPath() {
if (this.type == PointType.interpolation) {
LOGGER.warn("Request stop path of an interpolate Point");
Log.warning("Request stop path of an interpolate Point");
this.type = PointType.stop;
return;
}
if (this.type == PointType.stop) {
LOGGER.warn("Request stop path of an STOP Point");
Log.warning("Request stop path of an STOP Point");
return;
}
if (this.type == PointType.start) {

View File

@ -3,14 +3,12 @@ package org.atriasoft.esvg.render;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PointList {
static final Logger LOGGER = LoggerFactory.getLogger(PointList.class);
public List<List<Point>> data = new ArrayList<>();
public PointList() {
@ -23,28 +21,28 @@ public class PointList {
}
public void applyMatrix(final Matrix2x3f transformationMatrix) {
for (final List<Point> it : this.data) {
for (final Point val : it) {
for (List<Point> it : this.data) {
for (Point val : it) {
val.pos = transformationMatrix.multiply(val.pos);
}
}
}
public void display() {
LOGGER.trace(" Display list of points : size=" + this.data.size());
for (final List<Point> it : this.data) {
LOGGER.trace(" Find List " + it.size() + " members");
Log.warning(" Display list of points : size=" + this.data.size());
for (List<Point> it : this.data) {
Log.warning(" Find List " + it.size() + " members");
for (int iii = 0; iii < it.size(); ++iii) {
final Point elem = it.get(iii);
LOGGER.trace(" [" + iii + "] Find " + elem.type + " " + elem.pos);
Point elem = it.get(iii);
Log.verbose(" [" + iii + "] Find " + elem.type + " " + elem.pos);
}
}
}
public Pair<Vector2f, Vector2f> getViewPort() {
Pair<Vector2f, Vector2f> out = new Pair<>(Vector2f.MAX_VALUE, Vector2f.MIN_VALUE);
for (final List<Point> it : this.data) {
for (final Point it2 : it) {
for (List<Point> it : this.data) {
for (Point it2 : it) {
out = new Pair<>(Vector2f.min(out.first, it2.pos), Vector2f.max(out.second, it2.pos));
}
}

View File

@ -4,15 +4,14 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.atriasoft.esvg.CapMode;
import org.atriasoft.esvg.JoinMode;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Dynamic;
import org.atriasoft.etk.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.esvg.CapMode;
import org.atriasoft.esvg.JoinMode;
import org.atriasoft.esvg.internal.Log;
/** @file
* @author Edouard DUPIN
@ -21,20 +20,13 @@ import org.slf4j.LoggerFactory;
*/
public class SegmentList {
static final Logger LOGGER = LoggerFactory.getLogger(SegmentList.class);
static Vector2f getIntersect(
final Vector2f point1,
final Vector2f vect1,
final Vector2f point2,
final Vector2f vect2) {
final float diviseur = vect1.x() * vect2.y() - vect1.y() * vect2.x();
static Vector2f getIntersect(final Vector2f point1, final Vector2f vect1, final Vector2f point2, final Vector2f vect2) {
float diviseur = vect1.x() * vect2.y() - vect1.y() * vect2.x();
if (diviseur != 0.0f) {
final float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x()
+ vect1.y() * point2.x()) / diviseur;
float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x() + vect1.y() * point2.x()) / diviseur;
return point2.add(vect2.multiply(mmm));
}
LOGGER.error("Get divider / 0.0f");
Log.error("Get divider / 0.0f");
return point2;
}
@ -63,16 +55,16 @@ public class SegmentList {
}
public void applyMatrix(final Matrix2x3f transformationMatrix) {
for (final Segment it : this.data) {
for (Segment it : this.data) {
it.applyMatrix(transformationMatrix);
}
}
public void clearHorizontals() {
// TODO Auto-generated method stub
final Iterator<Segment> itr = this.data.iterator();
Iterator<Segment> itr = this.data.iterator();
while (itr.hasNext()) {
final Segment seg = itr.next();
Segment seg = itr.next();
if (seg.p0.y() == seg.p1.y()) {
itr.remove();
}
@ -80,7 +72,7 @@ public class SegmentList {
}
public void createSegmentList(final PointList listPoint) {
for (final List<Point> it : listPoint.data) {
for (List<Point> it : listPoint.data) {
// Build Segments
for (int iii = 0, jjj = it.size() - 1; iii < it.size(); jjj = iii++) {
addSegment(it.get(jjj), it.get(iii));
@ -88,13 +80,8 @@ public class SegmentList {
}
}
public void createSegmentListStroke(
final PointList listPoint,
final float width,
final CapMode cap,
final JoinMode join,
final float miterLimit) {
for (final List<Point> itListPoint : listPoint.data) {
public void createSegmentListStroke(final PointList listPoint, final float width, final CapMode cap, final JoinMode join, final float miterLimit) {
for (List<Point> itListPoint : listPoint.data) {
// generate for every point all the orthogonal elements
//
// normal edge * end path
@ -109,31 +96,29 @@ public class SegmentList {
// . * * . * * * * * * * * * * * * *
// * *
// * *
for (int idPevious = itListPoint.size() - 1, idCurrent = 0, idNext = 1; idCurrent < itListPoint.size();
idPevious = idCurrent++, idNext++) {
for (int idPevious = itListPoint.size() - 1, idCurrent = 0, idNext = 1; idCurrent < itListPoint.size(); idPevious = idCurrent++, idNext++) {
if (idNext == itListPoint.size()) {
idNext = 0;
}
if (itListPoint.get(idCurrent).type == PointType.join
|| itListPoint.get(idCurrent).type == PointType.interpolation) {
if (itListPoint.get(idCurrent).type == PointType.join || itListPoint.get(idCurrent).type == PointType.interpolation) {
if (idPevious < 0) {
LOGGER.error("an error occure a previous ID is < 0.... ");
Log.error("an error occure a previous ID is < 0.... ");
continue;
}
if (idNext >= itListPoint.size()) {
LOGGER.error("an error occure a next ID is >= nbPoint len .... ");
Log.error("an error occure a next ID is >= nbPoint len .... ");
continue;
}
//LOGGER.debug("JOIN : id : prev/curr/next : " + idPevious + "/" + idCurrent + "/" + idNext);
//LOGGER.debug("JOIN : val : prev/curr/next : " + itListPoint.get(idPevious).pos + "/" + itListPoint.get(idCurrent).pos + "/" + itListPoint.get(idNext).pos);
//Log.debug("JOIN : id : prev/curr/next : " + idPevious + "/" + idCurrent + "/" + idNext);
//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);
//LOGGER.debug("JOIN : vecA : " + vecA);
//Log.debug("JOIN : vecA : " + vecA);
vecA = vecA.safeNormalize();
Vector2f vecB = itListPoint.get(idNext).pos.less(itListPoint.get(idCurrent).pos);
//LOGGER.debug("JOIN : vecB : " + vecB);
//Log.debug("JOIN : vecB : " + vecB);
vecB = vecB.safeNormalize();
Vector2f vecC = vecA.less(vecB);
//LOGGER.debug("JOIN : vecC : " + vecC);
//Log.debug("JOIN : vecC : " + vecC);
if (vecC.isZero()) {
// special case: 1 line ...
itListPoint.get(idCurrent).miterAxe = new Vector2f(vecA.y(), vecA.x());
@ -149,7 +134,7 @@ public class SegmentList {
vecB = itListPoint.get(idCurrent).pos.less(itListPoint.get(idPevious).pos);
vecB = vecB.safeNormalize();
itListPoint.get(idCurrent).orthoAxePrevious = new Vector2f(vecB.y(), -vecB.x());
//LOGGER.debug("JOIN : miterAxe " + itListPoint.get(idCurrent).miterAxe);
//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);
@ -159,7 +144,7 @@ public class SegmentList {
itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe;
} else if (itListPoint.get(idCurrent).type == PointType.stop) {
if (idPevious < 0) {
LOGGER.error("an error occure a previous ID is < 0.... ");
Log.error("an error occure a previous ID is < 0.... ");
continue;
}
itListPoint.get(idCurrent).posPrevious = itListPoint.get(idPevious).pos;
@ -169,27 +154,25 @@ public class SegmentList {
itListPoint.get(idCurrent).orthoAxePrevious = itListPoint.get(idCurrent).miterAxe;
itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe;
} else {
LOGGER.info("TODO: Unsupported type of point ....");
Log.todo("Unsupported type of point ....");
}
}
// create segment list:
boolean haveStartLine = false;
final Dynamic<Vector2f> leftPoint = new Dynamic<>(Vector2f.ZERO);
Dynamic<Vector2f> leftPoint = new Dynamic<Vector2f>(Vector2f.ZERO);
final Dynamic<Vector2f> rightPoint = new Dynamic<>(Vector2f.ZERO);
Dynamic<Vector2f> rightPoint = new Dynamic<Vector2f>(Vector2f.ZERO);
if (itListPoint.size() > 0) {
if (itListPoint.get(0).type == PointType.join) {
final Point it = itListPoint.get(itListPoint.size() - 1);
Point it = itListPoint.get(itListPoint.size() - 1);
// 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.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);
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 perpendicular axis ...
leftPoint.value = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f));
@ -197,14 +180,12 @@ public class SegmentList {
// project on the miter Axis ...
switch (join) {
case MITER: {
final Vector2f left = SegmentList.getIntersect(leftPoint.value,
it.pos.less(it.posPrevious), it.pos, it.miterAxe);
final Vector2f right = SegmentList.getIntersect(rightPoint.value,
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:
final float limitRight = (left.less(it.pos)).length() / width * 2.0f;
final float limitLeft = (right.less(it.pos)).length() / width * 2.0f;
LOGGER.trace(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit);
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.value = left;
rightPoint.value = right;
@ -213,16 +194,14 @@ public class SegmentList {
}
case ROUND:
case BEVEL: {
final Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
final Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
final float cross = axePrevious.cross(axeNext);
Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
float cross = axePrevious.cross(axeNext);
if (cross > 0.0f) {
rightPoint.value = SegmentList.getIntersect(rightPoint.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);
leftPoint.value = it.pos.add(it.orthoAxeNext.multiply(width * 0.5f));
} else {
leftPoint.value = SegmentList.getIntersect(leftPoint.value,
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 = it.pos.less(it.orthoAxeNext.multiply(width * 0.5f));
}
break;
@ -231,112 +210,106 @@ public class SegmentList {
break;
}
} else {
LOGGER.error("Start list point with a join, but last lement is not a join");
Log.error("Start list point with a join, but last lement is not a join");
}
}
}
for (final Point it : itListPoint) {
for (Point it : itListPoint) {
switch (it.type) {
case single:
// just do nothing ....
LOGGER.trace("Find Single " + it.pos);
Log.verbose("Find Single " + it.pos);
break;
case start:
LOGGER.trace("Find Start " + it.pos);
Log.verbose("Find Start " + it.pos);
if (haveStartLine) {
// close previous :
LOGGER.warn(" find a non close path ...");
Log.warning(" find a non close path ...");
addSegment(leftPoint.value, rightPoint.value);
}
haveStartLine = true;
startStopPoint(leftPoint, rightPoint, it, cap, width, true);
break;
case stop:
LOGGER.trace("Find Stop " + it.pos);
Log.verbose("Find Stop " + it.pos);
if (!haveStartLine) {
LOGGER.warn("find close path without start part ...");
Log.warning("find close path without start part ...");
break;
}
haveStartLine = false;
startStopPoint(leftPoint, rightPoint, it, cap, width, false);
break;
case interpolation: {
LOGGER.trace("Find interpolation " + it.pos);
final Vector2f left = SegmentList.getIntersect(leftPoint.value, it.pos.less(it.posPrevious),
it.pos, it.miterAxe);
final Vector2f right = SegmentList.getIntersect(rightPoint.value, it.pos.less(it.posPrevious),
it.pos, it.miterAxe);
Log.verbose("Find interpolation " + it.pos);
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.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
leftPoint.value = left;
rightPoint.value = right;
}
break;
case join:
LOGGER.trace("Find join " + it.pos);
Log.verbose("Find join " + it.pos);
switch (join) {
case MITER: {
final Vector2f left = SegmentList.getIntersect(leftPoint.value,
it.pos.less(it.posPrevious), it.pos, it.miterAxe);
final Vector2f right = SegmentList.getIntersect(rightPoint.value,
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:
final float limitRight = left.less(it.pos).length() / width * 2.0f;
final float limitLeft = right.less(it.pos).length() / width * 2.0f;
LOGGER.trace(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit);
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.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
leftPoint.value = left;
rightPoint.value = right;
break;
}
LOGGER.trace(" Find miter Limit ... ==> create BEVEL");
Log.verbose(" Find miter Limit ... ==> create BEVEL");
}
case ROUND:
case BEVEL: {
final Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
final Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
final float cross = axePrevious.cross(axeNext);
Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
float cross = axePrevious.cross(axeNext);
if (cross > 0.0f) {
final Vector2f right = SegmentList.getIntersect(rightPoint.value,
it.pos.less(it.posPrevious), it.pos, it.miterAxe);
final Vector2f left1 = it.pos.add(it.orthoAxePrevious.multiply(width * 0.5f));
final Vector2f left2 = it.pos.add(it.orthoAxeNext.multiply(width * 0.5f));
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.value, left1);
LOGGER.trace(" segment :" + leftPoint + " . " + left1);
Log.verbose(" segment :" + leftPoint + " . " + left1);
if (join != JoinMode.ROUND) {
// Miter and bevel:
addSegment(left1, left2);
LOGGER.trace(" segment :" + left1 + " . " + left2);
Log.verbose(" segment :" + left1 + " . " + left2);
} else {
createSegmentListStroke(left1, left2, it.pos, width, false);
}
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
leftPoint.value = left2;
rightPoint.value = right;
} else {
final Vector2f left = SegmentList.getIntersect(leftPoint.value,
it.pos.less(it.posPrevious), it.pos, it.miterAxe);
final Vector2f right1 = it.pos.less(it.orthoAxePrevious.multiply(width * 0.5f));
final Vector2f right2 = it.pos.less(it.orthoAxeNext.multiply(width * 0.5f));
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.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right1, rightPoint.value);
LOGGER.trace(" segment :" + right1 + " . " + rightPoint);
Log.verbose(" segment :" + right1 + " . " + rightPoint);
if (join != JoinMode.ROUND) {
// Miter and bevel:
addSegment(right2, right1);
LOGGER.trace(" segment :" + right2 + " . " + right1);
Log.verbose(" segment :" + right2 + " . " + right1);
} else {
createSegmentListStroke(right1, right2, it.pos, width, true);
}
@ -357,21 +330,15 @@ public class SegmentList {
}
private void createSegmentListStroke(
final Vector2f point1,
final Vector2f point2,
final Vector2f center,
final float width,
final boolean isStart) {
private void createSegmentListStroke(final Vector2f point1, final Vector2f point2, final Vector2f center, final float width, final boolean isStart) {
int nbDot = (int) width;
if (nbDot <= 2) {
nbDot = 2;
}
final float angleToDraw = FMath
.acos((point1.less(center)).safeNormalize().dot((point2.less(center)).safeNormalize()));
final float baseAngle = angleToDraw / nbDot;
float angleToDraw = FMath.acos((point1.less(center)).safeNormalize().dot((point2.less(center)).safeNormalize()));
float baseAngle = angleToDraw / nbDot;
float iii;
final Vector2f axe = (point1.less(center)).safeNormalize();
Vector2f axe = (point1.less(center)).safeNormalize();
Vector2f ppp1 = point1;
@ -383,74 +350,68 @@ public class SegmentList {
} else {
tmpMat = Matrix2x3f.createRotate(iii);
}
final Vector2f axeRotate = tmpMat.multiply(axe);
Vector2f axeRotate = tmpMat.multiply(axe);
ppp2 = center.add(axeRotate.multiply(width * 0.5f));
if (isStart) {
addSegment(ppp2, ppp1);
LOGGER.trace(" segment :" + ppp2 + " . " + ppp1);
Log.verbose(" segment :" + ppp2 + " . " + ppp1);
} else {
addSegment(ppp1, ppp2);
LOGGER.trace(" segment :" + ppp1 + " . " + ppp2);
Log.verbose(" segment :" + ppp1 + " . " + ppp2);
}
ppp1 = ppp2;
}
if (isStart) {
addSegment(point2, ppp1);
LOGGER.trace(" segment :" + point2 + " . " + ppp1);
Log.verbose(" segment :" + point2 + " . " + ppp1);
} else {
addSegment(ppp1, point2);
LOGGER.trace(" segment :" + ppp1 + " . " + point2);
Log.verbose(" segment :" + ppp1 + " . " + point2);
}
}
public Pair<Vector2f, Vector2f> getViewPort() {
Pair<Vector2f, Vector2f> out = new Pair<>(Vector2f.MAX_VALUE, Vector2f.MIN_VALUE);
for (final Segment it : this.data) {
for (Segment it : this.data) {
out = new Pair<>(Vector2f.min(out.first, it.p0, it.p1), Vector2f.max(out.second, it.p0, it.p1));
}
return out;
}
private void startStopPoint(
final Dynamic<Vector2f> leftPoint,
final Dynamic<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: {
final Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
final Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
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.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
}
leftPoint.value = left;
rightPoint.value = right;
}
if (!isStart) {
addSegment(leftPoint.value, rightPoint.value);
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
} else {
addSegment(rightPoint.value, leftPoint.value);
LOGGER.trace(" segment :" + rightPoint + " . " + leftPoint);
Log.verbose(" segment :" + rightPoint + " . " + leftPoint);
}
break;
case ROUND: {
if (!isStart) {
final Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
final Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
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.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
}
leftPoint.value = left;
rightPoint.value = right;
@ -473,30 +434,30 @@ public class SegmentList {
}
Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
final Matrix2x3f tmpMat = Matrix2x3f.createTranslate(nextAxe.safeNormalize().multiply(width * -0.5f));
Matrix2x3f tmpMat = Matrix2x3f.createTranslate(nextAxe.safeNormalize().multiply(width * -0.5f));
left = tmpMat.multiply(left);
right = tmpMat.multiply(right);
if (!isStart) {
//Draw from previous point:
addSegment(leftPoint.value, left);
LOGGER.trace(" segment :" + leftPoint + " . " + left);
Log.verbose(" segment :" + leftPoint + " . " + left);
addSegment(right, rightPoint.value);
LOGGER.trace(" segment :" + right + " . " + rightPoint);
Log.verbose(" segment :" + right + " . " + rightPoint);
}
leftPoint.value = left;
rightPoint.value = right;
if (!isStart) {
addSegment(leftPoint.value, rightPoint.value);
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
} else {
addSegment(rightPoint.value, leftPoint.value);
LOGGER.trace(" segment :" + rightPoint + " . " + leftPoint);
Log.verbose(" segment :" + rightPoint + " . " + leftPoint);
}
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
}
break;
default:
LOGGER.error(" Undefined CAP TYPE");
Log.error(" Undefined CAP TYPE");
break;
}
}

View File

@ -4,16 +4,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.util.ArraysTools;
import org.atriasoft.etk.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Weight {
static final Logger LOGGER = LoggerFactory.getLogger(Weight.class);
private float[][] data = null;
private Vector2i size;
@ -42,8 +40,7 @@ public class Weight {
public void fusion(final Weight redered, final int offsetXXX, final int offsetYYY) {
for (int yyy = 0; yyy < redered.getHeight(); yyy++) {
for (int xxx = 0; xxx < redered.getWidth(); xxx++) {
this.data[offsetYYY + yyy][offsetXXX + xxx] = FMath.avg(0.0f,
this.data[offsetYYY + yyy][offsetXXX + xxx] + redered.get(xxx, yyy), 1.0f);
this.data[offsetYYY + yyy][offsetXXX + xxx] = FMath.avg(0.0f, this.data[offsetYYY + yyy][offsetXXX + xxx] + redered.get(xxx, yyy), 1.0f);
}
}
@ -53,10 +50,10 @@ public class Weight {
resize(size);
// for each lines:
for (int yyy = 0; yyy < size.y(); ++yyy) {
LOGGER.trace("Weighting ... " + yyy + " / " + size.y());
Log.verbose("Weighting ... " + yyy + " / " + size.y());
// Reduce the number of lines in the subsampling parsing:
final List<Segment> availlableSegmentPixel = new ArrayList<>();
for (final Segment it : listSegment.data) {
List<Segment> availlableSegmentPixel = new ArrayList<Segment>();
for (Segment it : listSegment.data) {
if (it.p0.y() < yyy + 1 && it.p1.y() > (yyy)) {
availlableSegmentPixel.add(it);
}
@ -64,21 +61,20 @@ public class Weight {
if (availlableSegmentPixel.size() == 0) {
continue;
}
LOGGER.trace(" Find Basic segments " + availlableSegmentPixel.size());
Log.verbose(" Find Basic segments " + availlableSegmentPixel.size());
// This represent the pondaration on the subSampling
final float deltaSize = 1.0f / subSamplingCount;
float deltaSize = 1.0f / subSamplingCount;
for (int kkk = 0; kkk < subSamplingCount; ++kkk) {
LOGGER.trace(" Scanline ... " + kkk + " / " + subSamplingCount);
final Scanline scanline = new Scanline(size.x());
Log.verbose(" Scanline ... " + kkk + " / " + subSamplingCount);
Scanline scanline = new Scanline(size.x());
//find all the segment that cross the middle of the line of the center of the pixel line:
final float subSamplingCenterPos = yyy + deltaSize * 0.5f + deltaSize * kkk;
final List<Segment> availlableSegment = new ArrayList<>();
float subSamplingCenterPos = yyy + deltaSize * 0.5f + deltaSize * kkk;
List<Segment> availlableSegment = new ArrayList<>();
// find in the subList ...
for (final Segment it : availlableSegmentPixel) {
for (Segment it : availlableSegmentPixel) {
if (it.p0.y() <= subSamplingCenterPos && it.p1.y() > subSamplingCenterPos) {
// check if we not get 2 identical lines:
if (availlableSegment.size() > 0
&& availlableSegment.get(availlableSegment.size() - 1).p1 == it.p0
if (availlableSegment.size() > 0 && availlableSegment.get(availlableSegment.size() - 1).p1 == it.p0
&& availlableSegment.get(availlableSegment.size() - 1).direction == it.direction) {
// we not add this point in this case to prevent double count of the same point.
} else {
@ -86,24 +82,24 @@ public class Weight {
}
}
}
LOGGER.trace(" Availlable Segment " + availlableSegment.size());
Log.verbose(" Availlable Segment " + availlableSegment.size());
if (availlableSegment.size() == 0) {
continue;
}
for (final Segment it : availlableSegment) {
LOGGER.trace(" Availlable Segment " + it.p0 + " . " + it.p1 + " dir=" + it.direction);
for (Segment it : availlableSegment) {
Log.verbose(" Availlable Segment " + it.p0 + " . " + it.p1 + " dir=" + it.direction);
}
// x position, angle
final List<Pair<Float, Integer>> listPosition = new ArrayList<>();
for (final Segment it : availlableSegment) {
final Vector2f delta = it.p0.less(it.p1);
List<Pair<Float, Integer>> listPosition = new ArrayList<>();
for (Segment it : availlableSegment) {
Vector2f delta = it.p0.less(it.p1);
// x = coefficent*y+bbb;
final float coefficient = delta.x() / delta.y();
final float bbb = it.p0.x() - coefficient * it.p0.y();
final float xpos = coefficient * subSamplingCenterPos + bbb;
listPosition.add(new Pair<>(xpos, it.direction));
float coefficient = delta.x() / delta.y();
float bbb = it.p0.x() - coefficient * it.p0.y();
float xpos = coefficient * subSamplingCenterPos + bbb;
listPosition.add(new Pair<Float, Integer>(xpos, it.direction));
}
LOGGER.trace(" List position " + listPosition.size());
Log.verbose(" List position " + listPosition.size());
// now we order position of the xPosition:
Collections.sort(listPosition, (e1, e2) -> ((int) (e1.first - e2.first)));
@ -115,25 +111,25 @@ public class Weight {
// * current pos
// * pos ...
// TODO Code the Odd/even and non-zero ...
for (final Pair<Float, Integer> it : listPosition) {
for (Pair<Float, Integer> it : listPosition) {
if (currentPos != it.first.intValue()) {
// fill to the new pos -1:
final float endValue = FMath.min(1.0f, FMath.abs(lastState)) * deltaSize;
float endValue = FMath.min(1.0f, FMath.abs(lastState)) * deltaSize;
for (int iii = currentPos + 1; iii < it.first.intValue(); ++iii) {
scanline.set(iii, endValue);
}
currentPos = it.first.intValue();
currentValue = endValue;
}
final int oldState = lastState;
int oldState = lastState;
lastState += it.second;
if (oldState == 0) {
// nothing to draw before ...
final float ratio = 1.0f - (it.first - it.first.intValue());
float ratio = 1.0f - (it.first - it.first.intValue());
currentValue += ratio * deltaSize;
} else if (lastState == 0) {
// something new to draw ...
final float ratio = 1.0f - (it.first - it.first.intValue());
float ratio = 1.0f - (it.first - it.first.intValue());
currentValue -= ratio * deltaSize;
} else {
// nothing to do ...
@ -146,7 +142,7 @@ public class Weight {
// if the counter is not at 0 ==> fill if to the end with full value ... 2.0
if (lastState != 0) {
// just past the last state to the end of the image ...
LOGGER.error("end of Path whith no end ... " + currentPos + " . " + size.x());
Log.error("end of Path whith no end ... " + currentPos + " . " + size.x());
for (int xxx = currentPos; xxx < size.x(); ++xxx) {
scanline.set(xxx, 100.0f);
}
@ -187,14 +183,6 @@ public class Weight {
// -----------------------------------------------
public void resize(final Vector2i size) {
this.size = size;
if (this.size.x() <= 0) {
LOGGER.error("Error in the Weight size : " + this.size);
this.size = this.size.withX(1);
}
if (this.size.y() <= 0) {
LOGGER.error("Error in the Weight size : " + this.size);
this.size = this.size.withY(1);
}
this.data = new float[this.size.y()][this.size.x()];
clear(0);
}

View File

@ -1,188 +0,0 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestCap {
@Test
public void testTestCapButt() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>\
<polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbutt.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbutt.png"));
}
@Test
public void testTestCapButtDiag1() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>\
<polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag1.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag1.png"));
}
@Test
public void testTestCapButtDiag2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>\
<polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag2.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag2.png"));
}
@Test
public void testTestCapButtVert() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>\
<polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttVert.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttVert.png"));
}
@Test
public void testTestCapRound() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>\
<polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapround.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapround.png"));
}
@Test
public void testTestCapRoundDiag1() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>\
<polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag1.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag1.png"));
}
@Test
public void testTestCapRoundDiag2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>\
<polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag2.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag2.png"));
}
@Test
public void testTestCapRoundVert() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>\
<polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundVert.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundVert.png"));
}
@Test
public void testTestCapSquare() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>\
<polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquare.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquare.png"));
}
@Test
public void testTestCapSquareDiag1() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>\
<polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag1.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag1.png"));
}
@Test
public void testTestCapSquareDiag2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>\
<polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag2.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag2.png"));
}
@Test
public void testTestCapSquareVert() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>\
<polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.png"));
}
}

View File

@ -1,51 +0,0 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestCircle {
@Test
public void testTestCircleFill() throws RuntimeException {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<circle cx='50' cy='50' r='40' fill='red' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclefill.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclefill.png"));
}
@Test
public void testTestCircleFillandstroke() throws RuntimeException {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' fill='red' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclefillandstroke.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclefillandstroke.png"));
}
@Test
public void testTestCircleStroke() throws RuntimeException {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='100' width='100'>\
<circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.png"));
}
}

View File

@ -1,113 +0,0 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.Esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.esvg.EsvgFont;
import org.atriasoft.esvg.render.Weight;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestFont {
@Test
public void testFontError1() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='900' width='700'>\
<path d='M296 463q80 0 125 -45t45 -126q0 -130 -73 -217.5t-187 -87.5q-80 0 -125 45.5t-45 127.5q0 126 73 214.5t187 88.5zM218 51q78 0 123.5 68t45.5 166q0 115 -103 115q-75 0 -122 -66.5t-47 -167.5q0 -115 103 -115z'\
stroke='green' stroke-width='3' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError1.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError1.png"));
}
@Test
public void testFontError2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='900' width='700'>\
<path d='M296 463q80 0 125 -45t45 -126q0 -130 -73 -217.5t-187 -87.5q-80 0 -125 45.5t-45 127.5q0 126 73 214.5t187 88.5z'\
stroke='green' stroke-width='3' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError2.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError2.png"));
}
@Test
public void testFontError3() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='900' width='700'>\
<path d='M218 51q78 0 123.5 68t45.5 166q0 115 -103 115q-75 0 -122 -66.5t-47 -167.5q0 -115 103 -115z'\
stroke='green' stroke-width='3' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError3.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError3.png"));
}
@Test
public void testFontError4() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>\
<svg height='900' width='700'>\
<path d='M1011 -78q51 -11 84.5 -50.5t33.5 -93.5q0 -61 -43 -103t-104 -42q-60 0 -102 43q-43 42 -43 102q0 34 16 67q-2 0 -20 -4.5t-36.5 -8t-47 -7.5t-66.5 -6.5t-80 -2.5q-144 0 -248 27.5t-164.5 80.5t-88.5 123t-28 161q0 124 106 240l33 -30q-101 -101 -101 -206
q0 -335 487 -335q304 0 401 123q-39 -10 -68 -10q-95 3 -142 74q-50 -74 -136 -74q-68 0 -120 47t-52 125v92q0 75 -25.5 106t-58.5 31q-49 0 -92 -49t-43 -124q0 -19 3.5 -40.5t13.5 -53t34 -61.5t60 -48l-22 -25q-43 23 -72 58t-41 72.5t-16 63t-4 46.5q0 103 58.5 161.5
t130.5 58.5q24 0 47.5 -8t46.5 -26.5t37 -56t14 -89.5v-87q0 -79 37 -112t81 -33q40 0 69.5 22.5t29.5 57.5v322h83v-275q0 -55 27.5 -84.5t67.5 -29.5q60 0 95.5 52.5t35.5 125.5q0 20 -3 40t-12.5 50t-33 57.5t-57.5 46.5l29 25q57 -44 90.5 -105t33.5 -130
q0 -195 -115 -291zM972 -218q23 0 37.5 15t14.5 37q0 17 -16 32.5t-35 15.5q-30 0 -41.5 -12t-11.5 -36q0 -23 15 -37.5t37 -14.5zM970 -316q41 0 69.5 29t28.5 69q0 38 -19 60q1 -3 1 -13q0 -38 -25 -62.5t-60 -24.5q-33 0 -57.5 22.5t-28.5 55.5q-7 -20 -7 -38
q0 -41 29 -69.5t69 -28.5z'\
stroke='green' stroke-width='3' />\
</svg>""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError4.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError4.png"));
}
@Test
public void testFontprintE25() {
Esvg.init();
final EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
Assertions.assertNotNull(font);
Weight out = font.render('E', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_E25.png"));
out = font.render('e', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_e25.png"));
out = font.render('É', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Ecute25.png"));
out = font.render('é', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_ecute25.png"));
out = font.render('p', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_p25.png"));
out = font.render('f', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_f25.png"));
}
@Test
public void testFontprintSimpleText() {
Esvg.init();
final EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
Weight out = font.render("Hello, How are you? VA // @ ê É", 100, false);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Hello.png"));
out = font.render("Hello, How are you? VA // @ ê É", 100, true);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Hello_withKerning.png"));
}
@Test
public void testFontRead() {
Esvg.init();
final EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
}
}

View File

@ -1,413 +0,0 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestGradientLinear {
@Test
public void testTestGradientLinearDiag1() {
//@formatter:off
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='0%' x2='100%' y2='100%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
//@formatter:on
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1.png"));
}
@Test
public void testTestGradientLinearDiag1Partiel() {
//@formatter:off
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='40%' y1='40%' x2='70%' y2='70%'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
//@formatter:on
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1Partiel.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1Partiel.png"));
}
@Test
public void testTestGradientLinearDiag2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate0() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='50%' x2='100%' y2='50%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse transform='rotate (30 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate0.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate0.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate1() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse transform='rotate (45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate1.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate1.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse transform='rotate (-45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate2.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate2.png"));
}
@Test
public void testTestGradientLinearDiag2scale() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse transform='scale (0.5 2.0) translate (10,-25)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri
.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2scale.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2scale.png"));
}
@Test
public void testTestGradientLinearHorizontal() {
//@formatter:off
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad1' x1='0%' y1='0%' x2='100%' y2='0%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
//@formatter:on
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri
.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.png"));
}
@Test
public void testTestGradientLinearInternalHref() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2Values'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
<linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%' xlink:href='#grad2Values' />
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearinternalHref.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearinternalHref.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadNone() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadNone.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadNone.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadPad() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='pad'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadPad.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadPad.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadReflect() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='reflect'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadReflect.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadReflect.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadRepeat() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='40%' y1='40%' x2='60%' y2='60%' spreadMethod='repeat'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadRepeat.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadRepeat.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadNone() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' gradientUnits='userSpaceOnUse'>
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadNone.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadNone.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadPad() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='pad' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadPad.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadPad.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadReflect() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadReflect.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadReflect.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadRepeate() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)'/>
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadRepeate.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadRepeate.png"));
}
@Test
public void testTestGradientLinearVertical() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<linearGradient id='grad2' x1='0%' y1='0%' x2='0%' y2='100%'>
<stop offset='0%' style='stop-color:rgb(255,0,0);stop-opacity:1' />
<stop offset='45%' style='stop-color:rgb(0,255,0);stop-opacity:1' />
<stop offset='55%' style='stop-color:rgb(0,0,255);stop-opacity:1' />
<stop offset='100%' style='stop-color:rgb(255,0,255);stop-opacity:1' />
</linearGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri
.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.png"));
}
}

View File

@ -1,388 +0,0 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestGradientRadial {
@Test
public void testTestGradientRadialCircle() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='50' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialcircle.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialcircle.png"));
}
@Test
public void testTestGradientRadialFull() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialfull.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialfull.png"));
}
@Test
public void testTestGradientRadialPartial() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad2' cx='20%' cy='30%' r='30%' fx='50%' fy='50%'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri
.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialpartial.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialpartial.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadNone() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadNone.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadNone.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadPad() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='pad'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadPad.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadPad.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadReflect() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='reflect'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadReflect.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadReflect.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadRepeat() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='repeat'>
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadRepeat.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadRepeat.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadNone() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50%' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadNone.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadNone.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadPad() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='pad' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPad.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPad.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadPadunCenter() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='pad' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPadunCenter.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc,
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPadunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadReflect() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflect.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflect.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadReflectunCenter() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflectunCenter.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc,
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflectunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeat() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeat.svg"), data.replace("'", "\"")));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeat.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatout() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='24' fx='20' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatout.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc,
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatout.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatunCenter() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc,
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatunCenter2() {
final String data = """
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<svg height='100' width='100'>
<defs>
<radialGradient id='grad1' cx='50' cy='50' r='24' fx='60' fy='60' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >
<stop offset='0%' style='stop-color:orange;stop-opacity:1' />
<stop offset='45%' style='stop-color:red;stop-opacity:1' />
<stop offset='55%' style='stop-color:blue;stop-opacity:1' />
<stop offset='100%' style='stop-color:green;stop-opacity:1' />
</radialGradient>
</defs>
<ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />
</svg>
""";
final EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.svg"),
data.replace("'", "\"")));
ConfigTest.generateAnImage(doc,
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.png"));
}
}

2
test/.gitignore vendored
View File

@ -1,3 +1 @@
/__pycache__/
/bin/

View File

@ -1,127 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="300"
height="300"
viewBox="0 0 79.374998 79.375002"
version="1.1"
id="svg8"
inkscape:version="1.0.2 (e86c870879, 2021-01-15, custom)"
sodipodi:docname="Unnamed document 2.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="443.11885"
inkscape:cy="483.15179"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="3838"
inkscape:window-height="2118"
inkscape:window-x="0"
inkscape:window-y="20"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.35px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="52.662182"
y="11.725324"
id="text835"><tspan
sodipodi:role="line"
id="tspan833"
x="52.662182"
y="11.725324"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.35px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583">H<tspan
style="fill:#d38b00;fill-opacity:1"
id="tspan1023">e</tspan>llo</tspan><tspan
sodipodi:role="line"
x="52.662182"
y="19.662823"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:6.35px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
id="tspan847">sq<tspan
style="fill:#8c0000;fill-opacity:1"
id="tspan1029">m</tspan>l</tspan><tspan
sodipodi:role="line"
x="52.662182"
y="27.600323"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.35px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
id="tspan849">k<tspan
style="fill:#000063;fill-opacity:1"
id="tspan1031">s</tspan>d</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:5.64444444px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;"
x="1.3595439"
y="44.163139"
id="text853"><tspan
sodipodi:role="line"
id="tspan851"
x="1.3595439"
y="44.163139"
style="stroke-width:0.264583;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:5.64444444px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;">Hello</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:5.64444444px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;"
x="1.1807559"
y="55.513321"
id="text857"><tspan
sodipodi:role="line"
id="tspan855"
x="1.1807559"
y="55.513321"
style="stroke-width:0.264583;font-weight:bold;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-style:normal;font-stretch:normal;font-variant:normal;font-size:5.64444444px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">Hello Bold</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:5.64444444px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;"
x="1.196579"
y="65.77121"
id="text861"><tspan
sodipodi:role="line"
id="tspan859"
x="1.196579"
y="65.77121"
style="stroke-width:0.264583;font-style:italic;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-weight:normal;font-stretch:normal;font-variant:normal;font-size:5.64444444px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">Hello Italic</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:5.64444444px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;"
x="1.9766912"
y="76.594482"
id="text865"><tspan
sodipodi:role="line"
id="tspan863"
x="1.9766912"
y="76.594482"
style="stroke-width:0.264583;font-weight:bold;font-style:italic;-inkscape-font-specification:'sans-serif, Normal';font-family:sans-serif;font-stretch:normal;font-variant:normal;font-size:5.64444444px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal">Hello Bold Italic</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -1,37 +1,36 @@
package test.atriasoft.esvg;
import org.atriasoft.egami.Image;
import org.atriasoft.egami.ImageFloatRGBA;
import org.atriasoft.egami.Image;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.esvg.internal.Log;
import org.atriasoft.esvg.render.Weight;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.pngencoder.PngEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfigTest {
static final Logger LOGGER = LoggerFactory.getLogger(ConfigTest.class);
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) {
final Image data = doc.renderImageFloatRGBA(null, ConfigTest.VISUAL_DEBUG);
Image data = doc.renderImageFloatRGBA(null, ConfigTest.VISUAL_DEBUG);
if (data == null) {
LOGGER.error("No data generated ...");
Log.critical("No data generated ...");
}
LOGGER.warn("Save file in " + uri.getPath());
final byte[] outElem = new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toBytes();
LOGGER.warn("outsize = " + outElem.length);
Log.warning("Save file in " + uri.getPath());
byte[] outElem = new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toBytes();
Log.warning("outsize = " + outElem.length);
new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toFile(uri.getPath());
}
public static void generateAnImage(final Weight weight, final Uri uri) {
final ImageFloatRGBA image = new ImageFloatRGBA(weight.getWidth() + 2, weight.getHeight() + 2);
ImageFloatRGBA image = new ImageFloatRGBA(weight.getWidth() + 2, weight.getHeight() + 2);
for (int yyy = 0; yyy < weight.getHeight(); yyy++) {
for (int xxx = 0; xxx < weight.getWidth(); xxx++) {
final float elem = weight.get(new Vector2i(xxx, yyy));
float elem = weight.get(new Vector2i(xxx, yyy));
image.setColorFloat(xxx, yyy, 1.0f, 1.0f, 1.0f, elem);
}
}
@ -43,9 +42,9 @@ public class ConfigTest {
image.setColor(xxx, 0, Color.ORANGE);
image.setColor(xxx, weight.getHeight() + 1, Color.ORANGE);
}
LOGGER.warn("Save file in " + uri.getPath());
final byte[] outElem = new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toBytes();
LOGGER.warn("outsize = " + outElem.length);
Log.warning("Save file in " + uri.getPath());
byte[] outElem = new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toBytes();
Log.warning("outsize = " + outElem.length);
new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toFile(uri.getPath());
}

View File

@ -0,0 +1,139 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Test;
class TestCap {
@Test
public void testTestCapButt() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
+ " <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbutt.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbutt.png"));
}
@Test
public void testTestCapButtDiag1() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
+ " <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag1.png"));
}
@Test
public void testTestCapButtDiag2() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
+ " <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttDiag2.png"));
}
@Test
public void testTestCapButtVert() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='butt'/>"
+ " <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='butt'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapbuttVert.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapbuttVert.png"));
}
@Test
public void testTestCapRound() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
+ " <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapround.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapround.png"));
}
@Test
public void testTestCapRoundDiag1() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
+ " <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag1.png"));
}
@Test
public void testTestCapRoundDiag2() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
+ " <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundDiag2.png"));
}
@Test
public void testTestCapRoundVert() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='round'/>"
+ " <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCaproundVert.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCaproundVert.png"));
}
@Test
public void testTestCapSquare() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,75 80,75' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
+ " <polyline points='80,25 20,25' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquare.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquare.png"));
}
@Test
public void testTestCapSquareDiag1() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,20 80,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
+ " <polyline points='80,20 20,80' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag1.png"));
}
@Test
public void testTestCapSquareDiag2() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='20,80 80,20' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
+ " <polyline points='80,80 20,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareDiag2.png"));
}
@Test
public void testTestCapSquareVert() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>"
+ " <polyline points='25,20 25,80' stroke='green' stroke-width='20' fill='none' stroke-linecap='square'/>"
+ " <polyline points='75,80 75,20' stroke='orange' stroke-width='20' fill='none' stroke-linecap='square'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.png"));
}
}

View File

@ -0,0 +1,36 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Test;
class TestCircle {
@Test
public void testTestCircleFill() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <circle cx='50' cy='50' r='40' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclefill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclefill.png"));
}
@Test
public void testTestCircleFillandstroke() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' fill='red' />"
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclefillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclefillandstroke.png"));
}
@Test
public void testTestCircleStroke() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <circle cx='50' cy='50' r='40' stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestColor {
@ -13,7 +11,7 @@ class TestColor {
+ " <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-opacity='0.5' stroke-width='3' fill='#F00' fill-opacity='0.5' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColorblending.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColorblending.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestColorblending.png"));
}
@ -23,7 +21,7 @@ class TestColor {
+ " <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-opacity='0.5' stroke-width='3' fill='#F00' fill-opacity='0.5' opacity='0.7' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColorblendingandopacity.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColorblendingandopacity.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestColorblendingandopacity.png"));
}
@ -35,7 +33,7 @@ class TestColor {
+ " <rect x='30' y='30' width='20' height='20' stroke='orange' stroke-width='1' fill='violet'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColormultiplelayer.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColormultiplelayer.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestColormultiplelayer.png"));
}
@ -45,7 +43,7 @@ class TestColor {
+ " <rect x='12.5' y='12.5' width='75' height='50' stroke='#0F0' stroke-width='3' fill='#F00' opacity='0.5' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColoropacity.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestColoropacity.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestColoropacity.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestEllipse {
@ -13,7 +11,7 @@ class TestEllipse {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <ellipse cx='50' cy='50' rx='80' ry='30' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsefill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsefill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestEllipsefill.png"));
}
@ -23,7 +21,7 @@ class TestEllipse {
+ " <ellipse cx='50' cy='50' rx='80' ry='30' stroke='green' stroke-width='3' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsefillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsefillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestEllipsefillandstroke.png"));
}
@ -33,7 +31,7 @@ class TestEllipse {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsestroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestEllipsestroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestEllipsestroke.png"));
}
}

View File

@ -0,0 +1,93 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.Esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.esvg.EsvgFont;
import org.atriasoft.esvg.render.Weight;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Test;
class TestFont {
@Test
public void testFontError1() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='900' width='700'>"
+ " <path d='M296 463q80 0 125 -45t45 -126q0 -130 -73 -217.5t-187 -87.5q-80 0 -125 45.5t-45 127.5q0 126 73 214.5t187 88.5zM218 51q78 0 123.5 68t45.5 166q0 115 -103 115q-75 0 -122 -66.5t-47 -167.5q0 -115 103 -115z'"
+ " stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError1.png"));
}
@Test
public void testFontError2() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='900' width='700'>"
+ " <path d='M296 463q80 0 125 -45t45 -126q0 -130 -73 -217.5t-187 -87.5q-80 0 -125 45.5t-45 127.5q0 126 73 214.5t187 88.5z'" + " stroke='green' stroke-width='3' />"
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError2.png"));
}
@Test
public void testFontError3() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='900' width='700'>"
+ " <path d='M218 51q78 0 123.5 68t45.5 166q0 115 -103 115q-75 0 -122 -66.5t-47 -167.5q0 -115 103 -115z'" + " stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError3.png"));
}
@Test
public void testFontError4() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='900' width='700'>"
+ " <path d='M1011 -78q51 -11 84.5 -50.5t33.5 -93.5q0 -61 -43 -103t-104 -42q-60 0 -102 43q-43 42 -43 102q0 34 16 67q-2 0 -20 -4.5t-36.5 -8t-47 -7.5t-66.5 -6.5t-80 -2.5q-144 0 -248 27.5t-164.5 80.5t-88.5 123t-28 161q0 124 106 240l33 -30q-101 -101 -101 -206\n"
+ "q0 -335 487 -335q304 0 401 123q-39 -10 -68 -10q-95 3 -142 74q-50 -74 -136 -74q-68 0 -120 47t-52 125v92q0 75 -25.5 106t-58.5 31q-49 0 -92 -49t-43 -124q0 -19 3.5 -40.5t13.5 -53t34 -61.5t60 -48l-22 -25q-43 23 -72 58t-41 72.5t-16 63t-4 46.5q0 103 58.5 161.5\n"
+ "t130.5 58.5q24 0 47.5 -8t46.5 -26.5t37 -56t14 -89.5v-87q0 -79 37 -112t81 -33q40 0 69.5 22.5t29.5 57.5v322h83v-275q0 -55 27.5 -84.5t67.5 -29.5q60 0 95.5 52.5t35.5 125.5q0 20 -3 40t-12.5 50t-33 57.5t-57.5 46.5l29 25q57 -44 90.5 -105t33.5 -130\n"
+ "q0 -195 -115 -291zM972 -218q23 0 37.5 15t14.5 37q0 17 -16 32.5t-35 15.5q-30 0 -41.5 -12t-11.5 -36q0 -23 15 -37.5t37 -14.5zM970 -316q41 0 69.5 29t28.5 69q0 38 -19 60q1 -3 1 -13q0 -38 -25 -62.5t-60 -24.5q-33 0 -57.5 22.5t-28.5 55.5q-7 -20 -7 -38\n"
+ "q0 -41 29 -69.5t69 -28.5z'" + " stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestFontError4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestFontError4.png"));
}
@Test
public void testFontprintE25() {
Esvg.init();
EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
Weight out = font.render('E', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_E25.png"));
out = font.render('e', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_e25.png"));
out = font.render('É', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Ecute25.png"));
out = font.render('é', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_ecute25.png"));
out = font.render('p', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_p25.png"));
out = font.render('f', 25);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_f25.png"));
}
@Test
public void testFontprintSimpleText() {
Esvg.init();
EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
Weight out = font.render("Hello, How are you? VA // @ ê É", 100, false);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Hello.png"));
out = font.render("Hello, How are you? VA // @ ê É", 100, true);
ConfigTest.generateAnImage(out, new Uri(ConfigTest.BASE_PATH + "testFontprint_Hello_withKerning.png"));
}
@Test
public void testFontRead() {
Esvg.init();
EsvgFont font = EsvgFont.load(new Uri("FONTS", "FreeSherif.svg", "esvg"));
}
}

View File

@ -0,0 +1,258 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Test;
class TestGradientLinear {
@Test
public void testTestGradientLinearDiag1() {
//@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("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1.png"));
}
@Test
public void testTestGradientLinearDiag1Partiel() {
//@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("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1Partiel.png"));
}
@Test
public void testTestGradientLinearDiag2() {
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='100%' 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(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate0() {
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='50%' x2='100%' y2='50%'>\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 transform='rotate (30 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate0.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate0.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate1() {
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='100%' 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 transform='rotate (45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate1.png"));
}
@Test
public void testTestGradientLinearDiag2Rotate2() {
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='100%' 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 transform='rotate (-45 50 50)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2Rotate2.png"));
}
@Test
public void testTestGradientLinearDiag2scale() {
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='100%' 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 transform='scale (0.5 2.0) translate (10,-25)' cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2scale.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag2scale.png"));
}
@Test
public void testTestGradientLinearHorizontal() {
//@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("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.png"));
}
@Test
public void testTestGradientLinearInternalHref() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n" + " <linearGradient id='grad2Values'>\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" + " <linearGradient id='grad2' x1='0%' y1='100%' x2='100%' y2='0%' xlink:href='#grad2Values' />\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearinternalHref.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearinternalHref.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadNone() {
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='60%' y2='60%'>\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadNone.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadNone.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadPad() {
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='60%' y2='60%' spreadMethod='pad'>\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadPad.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadPad.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadReflect() {
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='60%' y2='60%' spreadMethod='reflect'>\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadReflect.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadReflect.png"));
}
@Test
public void testTestGradientLinearUnitBoxspreadRepeat() {
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='60%' y2='60%' spreadMethod='repeat'>\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadRepeat.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitBoxspreadRepeat.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadNone() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' gradientUnits='userSpaceOnUse'>\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadNone.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadNone.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadPad() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadPad.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadPad.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadReflect() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadReflect.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadReflect.png"));
}
@Test
public void testTestGradientLinearUnitUserspreadRepeate() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <linearGradient id='grad2' x1='45' y1='45' x2='55' y2='55' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadRepeate.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearunitUserspreadRepeate.png"));
}
@Test
public void testTestGradientLinearVertical() {
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='0%' 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";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.png"));
}
}

View File

@ -0,0 +1,216 @@
package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Test;
class TestGradientRadial {
@Test
public void testTestGradientRadialCircle() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='50' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialcircle.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialcircle.png"));
}
@Test
public void testTestGradientRadialFull() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='50%' fx='50%' fy='50%'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialfull.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialfull.png"));
}
@Test
public void testTestGradientRadialPartial() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad2' cx='20%' cy='30%' r='30%' fx='50%' fy='50%'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad2)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialpartial.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialpartial.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadNone() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadNone.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadNone.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadPad() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='pad'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadPad.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadPad.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadReflect() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='reflect'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadReflect.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadReflect.png"));
}
@Test
public void testTestGradientRadialUnitBoxspreadRepeat() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50%' cy='50%' r='10%' fx='50%' fy='50%' spreadMethod='repeat'>\n" + " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n"
+ " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n" + " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n"
+ " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n" + " </defs>\n"
+ " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadRepeat.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitBoxspreadRepeat.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadNone() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50%' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadNone.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadNone.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadPad() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPad.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPad.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadPadunCenter() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='pad' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPadunCenter.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadPadunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadReflect() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflect.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflect.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadReflectunCenter() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflectunCenter.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadReflectunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeat() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='10' fx='50' fy='50' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeat.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeat.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatout() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='24' fx='20' fy='40' spreadMethod='reflect' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatout.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatout.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatunCenter() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='24' fx='40' fy='40' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter.png"));
}
@Test
public void testTestGradientRadialUnitUserspreadRepeatunCenter2() {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n" + "<svg height='100' width='100'>\n" + " <defs>\n"
+ " <radialGradient id='grad1' cx='50' cy='50' r='24' fx='60' fy='60' spreadMethod='repeat' gradientUnits='userSpaceOnUse' >\n"
+ " <stop offset='0%' style='stop-color:orange;stop-opacity:1' />\n" + " <stop offset='45%' style='stop-color:red;stop-opacity:1' />\n"
+ " <stop offset='55%' style='stop-color:blue;stop-opacity:1' />\n" + " <stop offset='100%' style='stop-color:green;stop-opacity:1' />\n" + " </radialGradient>\n"
+ " </defs>\n" + " <ellipse cx='50' cy='50' rx='50' ry='20' fill='url(#grad1)' />\n" + "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestJoin {
@ -14,7 +12,7 @@ class TestJoin {
+ " stroke='green' stroke-width='5' fill='orange' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelCornerCasePath.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelCornerCasePath.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelCornerCasePath.png"));
}
@ -24,7 +22,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft1.png"));
}
@ -34,7 +32,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft2.png"));
}
@ -44,7 +42,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft3.png"));
}
@ -54,7 +52,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelLeft4.png"));
}
@ -64,7 +62,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight1.png"));
}
@ -74,7 +72,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight2.png"));
}
@ -84,7 +82,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight3.png"));
}
@ -94,7 +92,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='bevel'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinbevelRight4.png"));
}
@ -105,7 +103,7 @@ class TestJoin {
+ " stroke='green' stroke-width='5' fill='orange' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePath.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePath.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePath.png"));
}
@ -116,7 +114,7 @@ class TestJoin {
+ " stroke='green' stroke-width='5' fill='orange' stroke-linejoin='miter' stroke-miterlimit='0.3'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePathLimit.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePathLimit.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterCornerCasePathLimit.png"));
}
@ -126,7 +124,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft1.png"));
}
@ -136,7 +134,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft2.png"));
}
@ -146,7 +144,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft3.png"));
}
@ -158,7 +156,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLeft4.png"));
}
@ -168,7 +166,7 @@ class TestJoin {
+ " <polyline points='10,10 25,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit1.png"));
}
@ -178,7 +176,7 @@ class TestJoin {
+ " <polyline points='10,10 50,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit2.png"));
}
@ -188,7 +186,7 @@ class TestJoin {
+ " <polyline points='10,10 75,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit3.png"));
}
@ -198,7 +196,7 @@ class TestJoin {
+ " <polyline points='10,10 90,25 10,40' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterLimit4.png"));
}
@ -208,7 +206,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight1.png"));
}
@ -218,7 +216,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight2.png"));
}
@ -228,7 +226,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight3.png"));
}
@ -238,7 +236,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='miter'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinmiterRight4.png"));
}
@ -251,7 +249,7 @@ class TestJoin {
+ " stroke='green' stroke-width='5' fill='orange' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundCornerCasePath.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundCornerCasePath.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundCornerCasePath.png"));
}
@ -261,7 +259,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft1.png"));
}
@ -271,7 +269,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft2.png"));
}
@ -281,7 +279,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft3.png"));
}
@ -291,7 +289,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundLeft4.png"));
}
@ -301,7 +299,7 @@ class TestJoin {
+ " <polyline points='20,20 50,50 20,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight1.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight1.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight1.png"));
}
@ -311,7 +309,7 @@ class TestJoin {
+ " <polyline points='20,80 50,50 80,80' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight2.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight2.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight2.png"));
}
@ -321,7 +319,7 @@ class TestJoin {
+ " <polyline points='80,80 50,50 80,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight3.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight3.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight3.png"));
}
@ -331,7 +329,7 @@ class TestJoin {
+ " <polyline points='80,20 50,50 20,20' stroke='green' stroke-width='20' fill='none' stroke-linejoin='round'/>" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight4.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight4.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestJoinroundRight4.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestLine {
@ -13,7 +11,7 @@ class TestLine {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestLinestroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestLinestroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestLinestroke.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestPath {
@ -15,7 +13,7 @@ class TestPath {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPatharc.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPatharc.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPatharc.png"));
}
@ -24,7 +22,7 @@ class TestPath {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <path d='m 50,50 q -30,1 -20,20 z'" + " fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathbezierCurveTo.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathbezierCurveTo.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathbezierCurveTo.png"));
}
@ -33,7 +31,7 @@ class TestPath {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <path d='m 50,50 t -20,30 t 30,-20 z'" + " fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathbezierSmoothCurveTo.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathbezierSmoothCurveTo.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathbezierSmoothCurveTo.png"));
}
@ -42,7 +40,7 @@ class TestPath {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <path d='m 50,50 c -30,0 -30,1 -20,20 z'" + " fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathcurveTo.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathcurveTo.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathcurveTo.png"));
}
@ -54,7 +52,7 @@ class TestPath {
+ " id='path3421'\n" + " inkscape:connector-curvature='0' />\n" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathendpathbordercase.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathendpathbordercase.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathendpathbordercase.png"));
}
@ -65,7 +63,7 @@ class TestPath {
+ " fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathfill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathfill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathfill.png"));
}
@ -76,7 +74,7 @@ class TestPath {
+ " stroke='green' stroke-width='3' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathfillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathfillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathfillandstroke.png"));
}
@ -85,7 +83,7 @@ class TestPath {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <path d='m 50,50 s -30,0 -20,20 z'" + " fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathsmoothCurveTo.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathsmoothCurveTo.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathsmoothCurveTo.png"));
}
@ -96,7 +94,7 @@ class TestPath {
+ " stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPathstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPathstroke.png"));
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestPolygon {
@ -12,7 +10,7 @@ class TestPolygon {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <polygon points='50,10 90,50 10,80' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonfill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonfill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolygonfill.png"));
}
@ -22,7 +20,7 @@ class TestPolygon {
+ " <polygon points='50,10 90,50 10,80' stroke='green' stroke-width='3' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonfillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonfillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolygonfillandstroke.png"));
}
@ -32,7 +30,7 @@ class TestPolygon {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolygonstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolygonstroke.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestPolyline {
@ -13,7 +11,7 @@ class TestPolyline {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinefill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinefill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolyLinefill.png"));
}
@ -23,7 +21,7 @@ class TestPolyline {
+ " <polyline points='20,20 40,25 60,40 80,90 90,50 5,90' stroke='green' stroke-width='3' fill='orange' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinefillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinefillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolyLinefillandstroke.png"));
}
@ -33,7 +31,7 @@ class TestPolyline {
+ " <polyline points='20,20 40,25 60,40 80,90 90,50 5,90' stroke='green' stroke-width='3' fill='none' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinestroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestPolyLinestroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestPolyLinestroke.png"));
}
}

View File

@ -2,8 +2,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TestRectangle {
@ -13,7 +11,7 @@ class TestRectangle {
+ "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfill.png"));
}
@ -23,7 +21,7 @@ class TestRectangle {
+ " <rect x='12.5' y='12.5' width='75' height='50' rx='20' ry='20' stroke='green' stroke-width='3' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedfillandstroke.png"));
}
@ -33,7 +31,7 @@ class TestRectangle {
+ " <rect x='12.5' y='12.5' width='75' height='50' rx='20' ry='20' stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglecornedstroke.png"));
}
@ -42,7 +40,7 @@ class TestRectangle {
String data = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<svg height='100' width='100'>" + " <rect x='12.5' y='12.5' width='75' height='50' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglefill.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglefill.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglefill.png"));
}
@ -52,7 +50,7 @@ class TestRectangle {
+ " <rect x='12.5' y='12.5' width='75' height='50' stroke='green' stroke-width='3' fill='red' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglefillandstroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglefillandstroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglefillandstroke.png"));
}
@ -62,7 +60,7 @@ class TestRectangle {
+ " <rect x='12.5' y='12.5' width='75' height='50' stroke='green' stroke-width='3' />" + "</svg>";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglestroke.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestRectanglestroke.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestRectanglestroke.png"));
}
}

View File

@ -3,8 +3,6 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
class TestStyle {
public void testTestExternWorddown() {
@ -118,7 +116,7 @@ class TestStyle {
+ "</svg>\n";
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestExternworddown.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestExternworddown.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestExternworddown.png"));
}
}

View File

@ -2,10 +2,8 @@ package test.atriasoft.esvg;
import org.atriasoft.esvg.Esvg;
import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.etk.Uri;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.atriasoft.etk.Uri;
class TestText {
@Test
@ -45,7 +43,7 @@ class TestText {
//@formatter:on
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestTextFull.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestTextFull.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestTextFull.png"));
}
@ -113,7 +111,7 @@ class TestText {
//@formatter:on
EsvgDocument doc = new EsvgDocument();
doc.parse(data);
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestTextFull.svg"), data.replace("'", "\"")));
Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestTextFull.svg"), data.replace("'", "\""));
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestTextFull.png"));
}
}

View File