[FEAT] use Maven a build system root tool
This commit is contained in:
parent
563cb8957f
commit
eb4570dd72
36
.classpath
36
.classpath
@ -1,37 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="resources"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry including="**/*.java" kind="src" output="out/eclipse/classes-test" path="test/src">
|
||||
<classpathentry including="**/*.java" kind="src" output="out/maven/classes" path="src">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="out/maven/test-classes" path="test/src">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/atriasoft-png-encoder">
|
||||
<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 kind="output" path="out/eclipse/classes"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
|
||||
<classpathentry kind="output" path="out/maven/classes"/>
|
||||
</classpath>
|
||||
|
23
.project
23
.project
@ -1,35 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>atriasoft-esvg</name>
|
||||
<name>esvg</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>atriasoft-esvg</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1646149232192</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
||||
|
11
esvg.iml
11
esvg.iml
@ -1,11 +0,0 @@
|
||||
<?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>
|
@ -38,7 +38,7 @@ def configure(target, my_module):
|
||||
'src/org/atriasoft/esvg/Base.java',
|
||||
'src/org/atriasoft/esvg/Text.java',
|
||||
'src/org/atriasoft/esvg/RadialGradient.java',
|
||||
'src/org/atriasoft/esvg/internal/Log.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',
|
||||
|
144
pom.xml
Normal file
144
pom.xml
Normal file
@ -0,0 +1,144 @@
|
||||
<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>
|
||||
<properties>
|
||||
<maven.compiler.version>3.13.0</maven.compiler.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<maven.dependency.version>3.1.1</maven.dependency.version>
|
||||
</properties>
|
||||
|
||||
<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-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<testSourceDirectory>test/src</testSourceDirectory>
|
||||
<directory>${project.basedir}/out/maven/</directory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven.compiler.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<!--<encoding>${project.build.sourceEncoding}</encoding>-->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Create the source bundle -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<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.0.0-M5</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.2.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.2.0</version>
|
||||
<configuration>
|
||||
<show>public</show>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
</project>
|
@ -6,8 +6,7 @@ open module org.atriasoft.esvg {
|
||||
exports org.atriasoft.esvg;
|
||||
exports org.atriasoft.esvg.font;
|
||||
exports org.atriasoft.esvg.render;
|
||||
|
||||
requires transitive org.atriasoft.reggol;
|
||||
|
||||
requires transitive org.atriasoft.etk;
|
||||
requires transitive org.atriasoft.exml;
|
||||
requires org.atriasoft.pngencoder;
|
||||
|
@ -2,7 +2,6 @@ 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;
|
||||
@ -11,6 +10,8 @@ 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
|
||||
@ -19,6 +20,7 @@ import org.atriasoft.exml.model.XmlElement;
|
||||
*/
|
||||
|
||||
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.
|
||||
|
||||
@ -30,7 +32,7 @@ public class Base {
|
||||
}
|
||||
posStart += base.length();
|
||||
if (value.length() < posStart + 2) {
|
||||
Log.error("Not enought spece in the String to have transform value for ' (' or '()' in '" + value + "'");
|
||||
LOGGER.error("Not enought spece in the String to have transform value for ' (' or '()' in '" + value + "'");
|
||||
return "";
|
||||
}
|
||||
if (value.charAt(posStart) == '(') {
|
||||
@ -39,19 +41,19 @@ public class Base {
|
||||
} else if (value.charAt(posStart) == ' ' && value.charAt(posStart + 1) == '(') {
|
||||
posStart += 2;
|
||||
} else {
|
||||
Log.error("Can not indexOf ' (' or '(' in '" + value.substring(posStart) + "' for '" + value + "'");
|
||||
LOGGER.error("Can not indexOf ' (' or '(' in '" + value.substring(posStart) + "' for '" + value + "'");
|
||||
return "";
|
||||
}
|
||||
if (value.length() < posStart + 1) {
|
||||
Log.error("Not enought spece in the String to have transform value for ')' in '" + value + "'");
|
||||
LOGGER.error("Not enought spece in the String to have transform value for ')' in '" + value + "'");
|
||||
return "";
|
||||
}
|
||||
int posEnd = value.indexOf(')', posStart);
|
||||
final int posEnd = value.indexOf(')', posStart);
|
||||
if (posEnd == -1) {
|
||||
Log.error("Missing element ')' in '" + value + "' for " + base);
|
||||
LOGGER.error("Missing element ')' in '" + value + "' for " + base);
|
||||
return "";
|
||||
}
|
||||
Log.verbose("indexOf : '" + value.substring(posStart, posEnd) + "' for " + base);
|
||||
LOGGER.trace("indexOf : '" + value.substring(posStart, posEnd) + "' for " + base);
|
||||
return value.substring(posStart, posEnd);
|
||||
}
|
||||
|
||||
@ -83,10 +85,14 @@ public class Base {
|
||||
* @param level Level of the tree
|
||||
*/
|
||||
void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.warning(spacingDist(level) + "DRAW esvg::Base ... ==> No drawing availlable");
|
||||
LOGGER.warn(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);
|
||||
}
|
||||
|
||||
@ -95,10 +101,15 @@ public class Base {
|
||||
* @param out where the lines are added
|
||||
* @param recurtionMax interpolation recurtion max
|
||||
* @param threshold threshold to stop recurtion
|
||||
* @param basicTrans Parant transformation of the environement
|
||||
* @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) {
|
||||
|
||||
}
|
||||
|
||||
@ -117,22 +128,24 @@ 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) == '#') {
|
||||
String color = inputData.substring(5, inputData.length() - 1);
|
||||
final String color = inputData.substring(5, inputData.length() - 1);
|
||||
localColor = new Pair<>(Color.NONE, color);
|
||||
} else {
|
||||
Log.error("Problem in parsing the color : '" + inputData + "' == > url(XXX) is not supported now ...");
|
||||
LOGGER.error(
|
||||
"Problem in parsing the color : '" + inputData + "' == > url(XXX) is not supported now ...");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
localColor = new Pair<>(Color.valueOf256(inputData), "");
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Log.verbose("Parse color : \"" + inputData + "\" == > " + localColor.first + " " + localColor.second);
|
||||
LOGGER.trace("Parse color : \"" + inputData + "\" == > " + localColor.first + " " + localColor.second);
|
||||
return localColor;
|
||||
}
|
||||
|
||||
@ -142,31 +155,21 @@ public class Base {
|
||||
* @return standard number of pixels
|
||||
*/
|
||||
float parseLength(final String dataInput) {
|
||||
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;
|
||||
}
|
||||
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> parseLength2(String config) {
|
||||
@ -235,7 +238,7 @@ public class Base {
|
||||
} else {
|
||||
if (content.length() != 0) {
|
||||
this.paint.stroke = parseColor(content);
|
||||
Log.error("Parse color : " + this.paint.stroke);
|
||||
LOGGER.error("Parse color : " + this.paint.stroke);
|
||||
}
|
||||
content = element.getAttribute("stroke-width", "");
|
||||
if (content.length() != 0) {
|
||||
@ -253,7 +256,7 @@ public class Base {
|
||||
if (content.equals("none")) {
|
||||
// OK, Nothing to do ...
|
||||
} else {
|
||||
Log.todo(" 'stroke-dasharray' not implemented ...");
|
||||
LOGGER.info("TODO 'stroke-dasharray' not implemented ...");
|
||||
}
|
||||
}
|
||||
content = element.getAttribute("stroke-linecap", "");
|
||||
@ -266,7 +269,7 @@ public class Base {
|
||||
this.paint.lineCap = CapMode.SQUARE;
|
||||
} else {
|
||||
this.paint.lineCap = CapMode.BUTT;
|
||||
Log.error("not know stroke-linecap value : '" + content + "', not in [butt,round,square]");
|
||||
LOGGER.error("not know stroke-linecap value : '" + content + "', not in [butt,round,square]");
|
||||
}
|
||||
}
|
||||
content = element.getAttribute("stroke-linejoin", "");
|
||||
@ -279,12 +282,12 @@ public class Base {
|
||||
this.paint.lineJoin = JoinMode.BEVEL;
|
||||
} else {
|
||||
this.paint.lineJoin = JoinMode.MITER;
|
||||
Log.error("not know stroke-linejoin value : '" + content + "', not in [miter,round,bevel]");
|
||||
LOGGER.error("not know stroke-linejoin value : '" + content + "', not in [miter,round,bevel]");
|
||||
}
|
||||
}
|
||||
content = element.getAttribute("stroke-miterlimit", "");
|
||||
if (content.length() != 0) {
|
||||
float tmp = parseLength(content);
|
||||
final float tmp = parseLength(content);
|
||||
this.paint.miterLimit = FMath.max(0.0f, tmp);
|
||||
}
|
||||
}
|
||||
@ -309,7 +312,7 @@ public class Base {
|
||||
} else if (content.equals("evenodd")) {
|
||||
this.paint.flagEvenOdd = true;
|
||||
} else {
|
||||
Log.error("not know fill-rule value : \"" + content + "\", not in [nonzero,evenodd]");
|
||||
LOGGER.error("not know fill-rule value : \"" + content + "\", not in [nonzero,evenodd]");
|
||||
}
|
||||
}
|
||||
// ---------------- opacity ----------------
|
||||
@ -329,51 +332,56 @@ public class Base {
|
||||
if (inputString.length() == 0) {
|
||||
return;
|
||||
}
|
||||
Log.verbose("indexOf transform : '" + inputString + "'");
|
||||
LOGGER.trace("indexOf transform : '" + inputString + "'");
|
||||
inputString = inputString.replace(',', ' ');
|
||||
Log.verbose("indexOf transform : '" + inputString + "'");
|
||||
LOGGER.trace("indexOf transform : '" + inputString + "'");
|
||||
// need to indexOf elements in order ...
|
||||
String data = Base.extractTransformData(inputString, "matrix");
|
||||
if (data.length() != 0) {
|
||||
double[] matrix = FMath.getTableDouble(data, " ", 6);
|
||||
final double[] matrix = FMath.getTableDouble(data, " ", 6);
|
||||
if (matrix != null) {
|
||||
this.transformMatrix = new Matrix2x3f(matrix);
|
||||
// indexOf a matrix : simply exit ...
|
||||
return;
|
||||
}
|
||||
Log.error("Parsing matrix() with wrong data ... '" + data + "'");
|
||||
LOGGER.error("Parsing matrix() with wrong data ... '" + data + "'");
|
||||
}
|
||||
data = Base.extractTransformData(inputString, "translate");
|
||||
if (data.length() != 0) {
|
||||
float[] elements = FMath.getTableFloat(data, " ", 2);
|
||||
final float[] elements = FMath.getTableFloat(data, " ", 2);
|
||||
if (elements != null) {
|
||||
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[0], elements[1])));
|
||||
Log.verbose("Translate : " + elements[0] + ", " + elements[1]);
|
||||
this.transformMatrix = this.transformMatrix
|
||||
.multiply(Matrix2x3f.createTranslate(new Vector2f(elements[0], elements[1])));
|
||||
LOGGER.trace("Translate : " + elements[0] + ", " + elements[1]);
|
||||
} else {
|
||||
float elem = Float.parseFloat(data);
|
||||
final 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) {
|
||||
float[] elements = FMath.getTableFloat(data, " ", 2);
|
||||
final float[] elements = FMath.getTableFloat(data, " ", 2);
|
||||
if (elements != null) {
|
||||
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
|
||||
Log.verbose("Translate : " + elements[0] + ", " + elements[1]);
|
||||
this.transformMatrix = this.transformMatrix
|
||||
.multiply(Matrix2x3f.createScale(new Vector2f(elements[0], elements[1])));
|
||||
LOGGER.trace("Translate : " + elements[0] + ", " + elements[1]);
|
||||
} else {
|
||||
float elem = Float.parseFloat(data);
|
||||
final float elem = Float.parseFloat(data);
|
||||
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createScale(elem));
|
||||
}
|
||||
}
|
||||
data = Base.extractTransformData(inputString, "rotate");
|
||||
if (data.length() != 0) {
|
||||
float[] elements = FMath.getTableFloat(data, " ", 3);
|
||||
final float[] elements = FMath.getTableFloat(data, " ", 3);
|
||||
if (elements != null) {
|
||||
float angle = (float) Math.toRadians(elements[0]);
|
||||
this.transformMatrix = this.transformMatrix.multiply(Matrix2x3f.createTranslate(new Vector2f(-elements[1], -elements[2])));
|
||||
final 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);
|
||||
@ -455,7 +463,7 @@ public class Base {
|
||||
}
|
||||
|
||||
protected String spacingDist(final int spacing) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
final StringBuilder out = new StringBuilder();
|
||||
for (int iii = 0; iii < spacing; iii++) {
|
||||
out.append(" ");
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ 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;
|
||||
@ -14,6 +13,8 @@ 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,55 +23,61 @@ import org.atriasoft.exml.model.XmlElement;
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
|
||||
public Circle(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
public Circle(final Vector2f position, final float radius, final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
this.position = position;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
|
||||
private PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final 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) {
|
||||
Log.debug(spacingDist(spacing) + "Circle " + this.position + " radius=" + this.radius);
|
||||
LOGGER.debug(spacingDist(spacing) + "Circle " + this.position + " radius=" + this.radius);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Circle");
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Circle");
|
||||
if (this.radius <= 0.0f) {
|
||||
Log.verbose(spacingDist(level + 1) + "Too small radius" + this.radius);
|
||||
LOGGER.trace(spacingDist(level + 1) + "Too small radius" + this.radius);
|
||||
return;
|
||||
}
|
||||
PathModel listElement = createPath();
|
||||
|
||||
final 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);
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
Weight tmpFill = new Weight();
|
||||
Weight tmpStroke = new Weight();
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, 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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -85,7 +92,8 @@ 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
|
||||
@ -96,25 +104,30 @@ public class Circle extends Base {
|
||||
//myRenderer.addDebugSegment(listSegmentFill);
|
||||
//myRenderer.addDebugSegment(listSegmentStroke);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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();
|
||||
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();
|
||||
Matrix2x3f mtx = this.transformMatrix;
|
||||
mtx = mtx.multiply(basicTrans);
|
||||
PointList listPoints = new PointList();
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
this.radius = 0.0f;
|
||||
@ -124,10 +137,10 @@ public class Circle extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
String content = element.getAttribute("cx", "");
|
||||
if (content.length() != 0) {
|
||||
this.position = this.position.withX(parseLength(content));
|
||||
@ -138,13 +151,13 @@ public class Circle extends Base {
|
||||
}
|
||||
content = element.getAttribute("r", "");
|
||||
if (content.length() == 0) {
|
||||
Log.error("Circle \"r\" is not present");
|
||||
LOGGER.error("Circle \"r\" is not present");
|
||||
return false;
|
||||
}
|
||||
this.radius = parseLength(content);
|
||||
if (0 > this.radius) {
|
||||
this.radius = 0;
|
||||
Log.error("Circle \"r\" is negative");
|
||||
LOGGER.error("Circle \"r\" is negative");
|
||||
return false;
|
||||
}
|
||||
sizeMax.value = new Vector2f(this.position.x() + this.radius, this.position.y() + this.radius);
|
||||
|
@ -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,6 +13,8 @@ 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
|
||||
@ -21,55 +23,61 @@ import org.atriasoft.exml.model.XmlElement;
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
|
||||
public Ellipse(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
public Ellipse(final Vector2f center, final Vector2f radius, final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
this.c = center;
|
||||
this.r = radius;
|
||||
}
|
||||
|
||||
|
||||
PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final 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) {
|
||||
Log.debug(spacingDist(spacing) + "Ellipse c=" + this.c + " r=" + this.r);
|
||||
LOGGER.debug(spacingDist(spacing) + "Ellipse c=" + this.c + " r=" + this.r);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Ellipse");
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Ellipse");
|
||||
if (this.r.x() <= 0.0f || this.r.y() <= 0.0f) {
|
||||
Log.verbose(spacingDist(level + 1) + "Too small radius" + this.r);
|
||||
LOGGER.trace(spacingDist(level + 1) + "Too small radius" + this.r);
|
||||
return;
|
||||
}
|
||||
PathModel listElement = createPath();
|
||||
|
||||
final 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);
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
Weight tmpFill = new Weight();
|
||||
Weight tmpStroke = new Weight();
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, 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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -84,7 +92,8 @@ 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
|
||||
@ -95,25 +104,30 @@ public class Ellipse extends Base {
|
||||
//myRenderer.addDebugSegment(listSegmentFill);
|
||||
//myRenderer.addDebugSegment(listSegmentStroke)
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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();
|
||||
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();
|
||||
Matrix2x3f mtx = this.transformMatrix;
|
||||
mtx = mtx.multiply(basicTrans);
|
||||
PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
if (element == null) {
|
||||
@ -121,13 +135,13 @@ public class Ellipse extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
this.c = Vector2f.ZERO;
|
||||
this.r = Vector2f.ZERO;
|
||||
|
||||
|
||||
String content = element.getAttribute("cx", "");
|
||||
if (content.length() != 0) {
|
||||
this.c = this.c.withX(parseLength(content));
|
||||
@ -138,18 +152,18 @@ public class Ellipse extends Base {
|
||||
}
|
||||
content = element.getAttribute("rx", "");
|
||||
if (content.length() == 0) {
|
||||
Log.error("Ellipse \"rx\" is not present");
|
||||
LOGGER.error("Ellipse \"rx\" is not present");
|
||||
return false;
|
||||
}
|
||||
this.r = this.r.withX(parseLength(content));
|
||||
content = element.getAttribute("ry", "");
|
||||
if (content.length() == 0) {
|
||||
Log.error("Ellipse \"ry\" is not present");
|
||||
LOGGER.error("Ellipse \"ry\" is not present");
|
||||
return false;
|
||||
}
|
||||
this.r = this.r.withY(parseLength(content));
|
||||
sizeMax.value = new Vector2f(this.c.x() + this.r.x(), this.c.y() + this.r.y());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ 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.math.Matrix2x3f;
|
||||
import org.atriasoft.etk.math.Vector2f;
|
||||
@ -16,8 +15,11 @@ import org.atriasoft.exml.exception.ExmlException;
|
||||
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;
|
||||
@ -25,19 +27,19 @@ public class EsvgDocument extends Base {
|
||||
private String title = ""; //!< sub-element list
|
||||
private Uri uri = null; //!< reference elements ...
|
||||
private String version = "0.0";
|
||||
|
||||
|
||||
public EsvgDocument() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public EsvgDocument(final Vector2i size) {
|
||||
this.size = new Vector2f(size.x(), size.y());
|
||||
}
|
||||
|
||||
|
||||
public void addElement(final Base elem) {
|
||||
this.subElementList.add(elem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* change all style in a xml atribute
|
||||
*/
|
||||
@ -55,7 +57,7 @@ public class EsvgDocument extends Base {
|
||||
for (final String it1 : listStyle) {
|
||||
final String[] value = it1.split(":");
|
||||
if (value.length != 2) {
|
||||
Log.error("parsing style with a wrong patern : " + it1 + " missing ':'");
|
||||
LOGGER.error("parsing style with a wrong patern : " + it1 + " missing ':'");
|
||||
continue;
|
||||
}
|
||||
// TODO Check if the attibute already exist ...
|
||||
@ -70,7 +72,7 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
this.uri = null;
|
||||
this.version = "0.0";
|
||||
@ -78,54 +80,59 @@ public class EsvgDocument extends Base {
|
||||
this.paint.clear();
|
||||
this.size = Vector2f.ZERO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display all the node in the svg file.
|
||||
*/
|
||||
public void displayDebug() {
|
||||
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("Main SVG: size=" + this.size);
|
||||
LOGGER.debug(" refs:");
|
||||
for (final Base element : this.refList) {
|
||||
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);
|
||||
LOGGER.debug(" Nodes:");
|
||||
for (final Base element : this.subElementList) {
|
||||
if (element != null) {
|
||||
element.display(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
for (int iii = 0; iii < this.subElementList.size(); iii++) {
|
||||
if (this.subElementList.get(iii) != null) {
|
||||
this.subElementList.get(iii).draw(myRenderer, basicTrans);
|
||||
for (final Base element : this.subElementList) {
|
||||
if (element != null) {
|
||||
element.draw(myRenderer, basicTrans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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");
|
||||
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) {
|
||||
if (it != null) {
|
||||
it.drawShapePoints(out, recurtionMax, threshold, basicTrans, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO remove this fucntion : use generic function ...
|
||||
public Vector2f getDefinedSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
|
||||
public List<List<Vector2f>> getLines() {
|
||||
return getLines(new Vector2f(256, 256));
|
||||
}
|
||||
|
||||
|
||||
public List<List<Vector2f>> getLines(Vector2f size) {
|
||||
final List<List<Vector2f>> out = new ArrayList<>();
|
||||
if (size.x() <= 0) {
|
||||
@ -134,16 +141,17 @@ public class EsvgDocument extends Base {
|
||||
if (size.y() <= 0) {
|
||||
size = size.withY(this.size.y());
|
||||
}
|
||||
Log.debug("lineification size " + size);
|
||||
LOGGER.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())));
|
||||
final 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()) {
|
||||
Log.error("request a reference with no name ... ");
|
||||
LOGGER.error("request a reference with no name ... ");
|
||||
return null;
|
||||
}
|
||||
for (final Base it : this.refList) {
|
||||
@ -154,14 +162,14 @@ public class EsvgDocument extends Base {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
Log.error("Can not find reference name : '" + name + "'");
|
||||
LOGGER.error("Can not find reference name : '" + name + "'");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public boolean isLoadOk() {
|
||||
return this.loadOK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! @previous
|
||||
public List<Color> renderImageFloatRGB(final Vector2i size) {
|
||||
@ -174,7 +182,7 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//! @previous
|
||||
public List<Color<uint8t,4>> renderImageU8RGBA(final Vector2i size) {
|
||||
List<Color> data = renderImageFloatRGBA(size);
|
||||
@ -186,7 +194,7 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//! @previous
|
||||
public List<Color<uint8t,3>> renderImageU8RGB(final Vector2i size) {
|
||||
List<Color> data = renderImageFloatRGBA(size);
|
||||
@ -230,7 +238,7 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return this.loadOK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* parse a string that contain an svg stream
|
||||
* @param data Data to parse
|
||||
@ -262,11 +270,11 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return this.loadOK;
|
||||
}
|
||||
|
||||
|
||||
public boolean parseXMLData(final XmlElement root) {
|
||||
return parseXMLData(root, false);
|
||||
}
|
||||
|
||||
|
||||
public boolean parseXMLData(final XmlElement root, final boolean isReference) {
|
||||
// get the svg version :
|
||||
this.version = root.getAttribute("version", "");
|
||||
@ -277,11 +285,11 @@ public class EsvgDocument extends Base {
|
||||
pos = parseXmlPosition(root);
|
||||
this.size = parseXmlSize(root);
|
||||
parsePaintAttr(root);
|
||||
Log.verbose("parsed .ROOT trans: " + this.transformMatrix);
|
||||
LOGGER.trace("parsed .ROOT trans: " + this.transformMatrix);
|
||||
} else {
|
||||
Log.verbose("Parse Reference section ... (no attibute)");
|
||||
LOGGER.trace("Parse Reference section ... (no attibute)");
|
||||
}
|
||||
|
||||
|
||||
Vector2f maxSize = Vector2f.ZERO;
|
||||
final Dynamic<Vector2f> size = new Dynamic<>(Vector2f.ZERO);
|
||||
// parse all sub node:
|
||||
@ -294,7 +302,7 @@ public class EsvgDocument extends Base {
|
||||
if (child.getValue().equals("g")) {
|
||||
elementParser = new Group(this.paint);
|
||||
} else if (child.getValue().equals("a")) {
|
||||
Log.info("Note : 'a' balise is parsed like a g balise ...");
|
||||
LOGGER.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 ...";
|
||||
@ -317,19 +325,19 @@ public class EsvgDocument extends Base {
|
||||
elementParser = new Text(this.paint);
|
||||
} else if (child.getValue().equals("radialGradient")) {
|
||||
if (!isReference) {
|
||||
Log.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
|
||||
LOGGER.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) {
|
||||
Log.error("'" + child.getValue() + "' node must not be defined outside a defs Section");
|
||||
LOGGER.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) {
|
||||
Log.error("'" + child.getValue() + "' node must not be defined in a defs Section");
|
||||
LOGGER.error("'" + child.getValue() + "' node must not be defined in a defs Section");
|
||||
continue;
|
||||
}
|
||||
final boolean retRefs = parseXMLData(child, true);
|
||||
@ -342,14 +350,15 @@ public class EsvgDocument extends Base {
|
||||
// Node ignore : generaly inkscape data
|
||||
continue;
|
||||
} else {
|
||||
Log.error("node not suported : '" + child.getValue() + "' must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
|
||||
LOGGER.error("node not suported : '" + child.getValue()
|
||||
+ "' must be [title,g,a,path,rect,circle,ellipse,line,polyline,polygon,text,metadata]");
|
||||
}
|
||||
if (elementParser == null) {
|
||||
Log.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
|
||||
LOGGER.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
|
||||
continue;
|
||||
}
|
||||
if (!elementParser.parseXML(child, this.transformMatrix, size)) {
|
||||
Log.error("error on node: '" + child.getValue() + "' Sub Parsing ERROR");
|
||||
LOGGER.error("error on node: '" + child.getValue() + "' Sub Parsing ERROR");
|
||||
elementParser = null;
|
||||
continue;
|
||||
}
|
||||
@ -376,12 +385,12 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public float[][] renderImageFloat(final Vector2i size) {
|
||||
return renderImageFloat(size, false);
|
||||
}
|
||||
|
||||
|
||||
public float[][] renderImageFloat(Vector2i size, final boolean visualDebug) {
|
||||
if (size == null) {
|
||||
size = new Vector2i((int) this.size.x(), (int) this.size.y());
|
||||
@ -393,12 +402,12 @@ public class EsvgDocument extends Base {
|
||||
size = size.withY((int) this.size.y());
|
||||
}
|
||||
}
|
||||
Log.debug("Generate size " + size);
|
||||
LOGGER.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())));
|
||||
draw(renderedElement, basicTrans);
|
||||
|
||||
|
||||
// direct return the generated data ...
|
||||
return renderedElement.getData();
|
||||
}
|
||||
@ -411,7 +420,7 @@ public class EsvgDocument extends Base {
|
||||
public ImageFloatRGBA renderImageFloatRGBA(final Vector2i size) {
|
||||
return renderImageFloatRGBA(size, false);
|
||||
}
|
||||
|
||||
|
||||
public ImageFloatRGBA renderImageFloatRGBA(Vector2i size, final boolean visualDebug) {
|
||||
if (size == null) {
|
||||
size = new Vector2i((int) this.size.x(), (int) this.size.y());
|
||||
@ -424,19 +433,20 @@ public class EsvgDocument extends Base {
|
||||
}
|
||||
}
|
||||
if (size.x() <= 0) {
|
||||
Log.error("Generate size " + size);
|
||||
LOGGER.error("Generate size " + size);
|
||||
}
|
||||
if (size.y() <= 0) {
|
||||
Log.error("Generate size " + size);
|
||||
LOGGER.error("Generate size " + size);
|
||||
}
|
||||
Log.verbose("Generate size " + size);
|
||||
LOGGER.trace("Generate size " + size);
|
||||
final 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())));
|
||||
final 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 ...
|
||||
return renderedElement.getData();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import java.util.Map;
|
||||
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;
|
||||
@ -21,6 +20,8 @@ import org.atriasoft.exml.Exml;
|
||||
import org.atriasoft.exml.exception.ExmlException;
|
||||
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
|
||||
|
||||
@ -52,11 +53,11 @@ import org.atriasoft.exml.model.XmlNode;
|
||||
<------------------------> : advance.x
|
||||
<------------> : sizeTexture.x
|
||||
<---> : bearing.x
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
_
|
||||
*----------------------* ^ ==> calculateFontRealHeight(fontSize);
|
||||
| | | ^ ==> getAscent(fontSize);
|
||||
@ -72,12 +73,13 @@ import org.atriasoft.exml.model.XmlNode;
|
||||
| | | |==> getDescent(fontSize);
|
||||
| | | |
|
||||
*----------------------* | |
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
public class EsvgFont {
|
||||
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(EsvgFont.class);
|
||||
|
||||
/**
|
||||
* Load the file that might contain the svg
|
||||
* @param uri File of the svg
|
||||
@ -99,24 +101,25 @@ public class EsvgFont {
|
||||
return null;
|
||||
}
|
||||
if (!(doc instanceof final XmlElement root)) {
|
||||
Log.error("can not load the SVG font ==> wrong root node");
|
||||
LOGGER.error("can not load the SVG font ==> wrong root node");
|
||||
return null;
|
||||
}
|
||||
if (!root.existNode("svg") || !(root.getNodeNoExcept("svg") instanceof final XmlElement svgNode)) {
|
||||
Log.error("can not load Node <svg> in svg document");
|
||||
LOGGER.error("can not load Node <svg> in svg document");
|
||||
return null;
|
||||
}
|
||||
if (!svgNode.existNode("defs") || !(svgNode.getNodeNoExcept("defs") instanceof final XmlElement defsNode)) {
|
||||
Log.error("can not load Node <defs> in svg document");
|
||||
LOGGER.error("can not load Node <defs> in svg document");
|
||||
return null;
|
||||
}
|
||||
if (!defsNode.existNode("font") || !(defsNode.getNodeNoExcept("font") instanceof final XmlElement fontElement)) {
|
||||
Log.error("can not load Node <font> in svg document");
|
||||
if (!defsNode.existNode("font")
|
||||
|| !(defsNode.getNodeNoExcept("font") instanceof final XmlElement fontElement)) {
|
||||
LOGGER.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()) {
|
||||
if (values.getValue().equals("font-face")) {
|
||||
@ -157,7 +160,7 @@ public class EsvgFont {
|
||||
for (final XmlNode values : fontElement.getNodes()) {
|
||||
if (values.getValue().equals("glyph")) {
|
||||
nbGlyph++;
|
||||
//Log.info("find flyph: " + nbGlyph);
|
||||
//LOGGER.info("find flyph: " + nbGlyph);
|
||||
final Glyph tmp = Glyph.valueOf(values.toElement(), font);
|
||||
if (tmp != null) {
|
||||
font.glyphs.put(tmp.getUnicodeValue(), tmp);
|
||||
@ -169,7 +172,7 @@ public class EsvgFont {
|
||||
} else if (values.getValue().equals("font-face")) {
|
||||
// already done ...
|
||||
} else {
|
||||
Log.warning("unsupported node name :" + values.getValue());
|
||||
LOGGER.warn("unsupported node name :" + values.getValue());
|
||||
}
|
||||
}
|
||||
for (final XmlNode values : fontElement.getNodes()) {
|
||||
@ -188,18 +191,18 @@ public class EsvgFont {
|
||||
final String[] g2Splited = g2.split(",");
|
||||
// create the list of kerning of the next elements
|
||||
final List<Kerning> elementsKerning = new ArrayList<>();
|
||||
for (int iii = 0; iii < g2Splited.length; iii++) {
|
||||
for (final String element : g2Splited) {
|
||||
for (final Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
|
||||
if (entry.getValue().getName().equals(g2Splited[iii])) {
|
||||
if (entry.getValue().getName().equals(element)) {
|
||||
elementsKerning.add(new Kerning(offset, entry.getKey()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add it on the
|
||||
for (int iii = 0; iii < g1Splited.length; iii++) {
|
||||
for (final String element : g1Splited) {
|
||||
for (final Map.Entry<Integer, Glyph> entry : font.glyphs.entrySet()) {
|
||||
if (entry.getValue().getName().equals(g1Splited[iii])) {
|
||||
if (entry.getValue().getName().equals(element)) {
|
||||
entry.getValue().addKerning(elementsKerning);
|
||||
font.hasKerning = true;
|
||||
break;
|
||||
@ -211,7 +214,7 @@ public class EsvgFont {
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
// The maximum accented height of the font within the font coordinate system.
|
||||
private int ascent = 800; // this is the height of the font (on top...)
|
||||
private int[] bbox = { -879, -545, 1767, 934 };
|
||||
@ -235,7 +238,7 @@ public class EsvgFont {
|
||||
private int unitsPerEm = 1000; // full size of the font
|
||||
// The height of lowercase glyphs in the font within the font coordinate system.
|
||||
private int xHeight = 450;
|
||||
|
||||
|
||||
/**
|
||||
* Get the font real size use (height) for all the characters.
|
||||
* @param fontSize size of the font the user require
|
||||
@ -243,33 +246,33 @@ public class EsvgFont {
|
||||
*/
|
||||
public int calculateFontRealHeight(final int fontSize) {
|
||||
return fontSize * this.unitsPerEm / this.capHeight;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public float calculateFontSizeWithHeight(final float fontHeight) {
|
||||
return fontHeight * this.capHeight / this.unitsPerEm;
|
||||
}
|
||||
|
||||
|
||||
public Vector2f calculateRenderOffset(final int fontSize) {
|
||||
final int realSize = calculateFontRealHeight(fontSize);
|
||||
final float deltaY = realSize * this.ascent / this.unitsPerEm;
|
||||
return new Vector2f(0, deltaY);
|
||||
}
|
||||
|
||||
|
||||
public float calculateSclaleFactor(final int fontSize) {
|
||||
final 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()) {
|
||||
@ -282,7 +285,7 @@ public class EsvgFont {
|
||||
offsetWriting -= glyph.getKerning(lastValue) * scale;
|
||||
lastValue = uVal;
|
||||
}
|
||||
|
||||
|
||||
float advenceXLocal = glyph.getHorizAdvX() * scale;
|
||||
// No generation of output ...
|
||||
offsetWriting += advenceXLocal;
|
||||
@ -290,7 +293,7 @@ public class EsvgFont {
|
||||
return new Vector2i(offsetWriting, realSize);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public int calculateWidth(final int uVal, final int fontSize) {
|
||||
final Glyph glyph = getGlyph(uVal);
|
||||
if (glyph == null) {
|
||||
@ -300,15 +303,15 @@ public class EsvgFont {
|
||||
final float scale = (float) realSize / (float) this.unitsPerEm;
|
||||
return (int) (glyph.getHorizAdvX() * scale);
|
||||
}
|
||||
|
||||
|
||||
public int calculateWidth(final String uVal, final int fontSize) {
|
||||
return calculateWidth(uVal, fontSize, true);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
//Log.error("scale =" + scale+ " font size = " + fontSize + " realSize=" + realSize);
|
||||
//LOGGER.error("scale =" + scale+ " font size = " + fontSize + " realSize=" + realSize);
|
||||
float offsetWriting = 0;
|
||||
int lastValue = 0;
|
||||
for (final char uVal : data.toCharArray()) {
|
||||
@ -321,14 +324,14 @@ public class EsvgFont {
|
||||
offsetWriting -= glyph.getKerning(lastValue) * scale;
|
||||
lastValue = uVal;
|
||||
}
|
||||
|
||||
|
||||
final float advenceXLocal = glyph.getHorizAdvX() * scale;
|
||||
offsetWriting += advenceXLocal;
|
||||
//Log.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
|
||||
//LOGGER.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
|
||||
}
|
||||
return (int) offsetWriting;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the rendering size of the specific glyph (size rendered in the Weight class).
|
||||
* @param unicodeValue Unicode value to render
|
||||
@ -338,11 +341,11 @@ public class EsvgFont {
|
||||
public Vector2i calculateWidthRendering(final Integer unicodeValue, final int fontSize) {
|
||||
return new Vector2i(calculateWidth(unicodeValue, fontSize), calculateFontRealHeight(fontSize));
|
||||
}
|
||||
|
||||
|
||||
public int getDescent() {
|
||||
return this.descent;
|
||||
}
|
||||
|
||||
|
||||
public Glyph getGlyph(final int glyphIndex) {
|
||||
final Glyph out = this.glyphs.get(glyphIndex);
|
||||
if (out == null) {
|
||||
@ -350,7 +353,7 @@ public class EsvgFont {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public Glyph getGlyphNullIfMissing(final int glyphIndex) {
|
||||
final Glyph out = this.glyphs.get(glyphIndex);
|
||||
if (out == null) {
|
||||
@ -358,11 +361,11 @@ public class EsvgFont {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public int getHorizAdvX() {
|
||||
return this.horizAdvX;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of available glyph in the Font
|
||||
* @return the glyph count.
|
||||
@ -370,11 +373,11 @@ public class EsvgFont {
|
||||
public int getNumGlyphs() {
|
||||
return this.glyphs.size();
|
||||
}
|
||||
|
||||
|
||||
public float getUnitsPerEm() {
|
||||
return this.unitsPerEm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the font have some kerning data
|
||||
* @return true if kerning is availlable.
|
||||
@ -382,7 +385,7 @@ public class EsvgFont {
|
||||
public boolean hasKerning() {
|
||||
return this.hasKerning;
|
||||
}
|
||||
|
||||
|
||||
public Weight render(final int uVal, final int fontSize) {
|
||||
final int realSize = calculateFontRealHeight(fontSize);
|
||||
final Glyph glyph = getGlyph(uVal);
|
||||
@ -391,7 +394,8 @@ public class EsvgFont {
|
||||
}
|
||||
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 Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent))
|
||||
.multiply(Matrix2x3f.createScale(scale));
|
||||
final PathModel model = glyph.getModel();
|
||||
if (model == null) {
|
||||
return null;
|
||||
@ -399,19 +403,19 @@ public class EsvgFont {
|
||||
final Weight data = glyph.getModel().drawFill(calculateWidthRendering(uVal, fontSize), transform, 8, config);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public Weight render(final String uVal, final int fontSize) {
|
||||
return render(uVal, fontSize, true);
|
||||
}
|
||||
|
||||
|
||||
public Weight render(final String data, final int fontSize, final boolean withKerning) {
|
||||
final int widthOut = calculateWidth(data, fontSize, withKerning);
|
||||
|
||||
|
||||
final int realSize = calculateFontRealHeight(fontSize);
|
||||
final float scale = (float) realSize / (float) this.unitsPerEm;
|
||||
|
||||
|
||||
final Weight weight = new Weight(new Vector2i(widthOut, realSize));
|
||||
|
||||
|
||||
float offsetWriting = 0;
|
||||
int lastValue = 0;
|
||||
for (final char uVal : data.toCharArray()) {
|
||||
@ -422,21 +426,23 @@ public class EsvgFont {
|
||||
}
|
||||
if (withKerning) {
|
||||
offsetWriting -= glyph.getKerning(lastValue) * scale;
|
||||
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
LOGGER.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
lastValue = uVal;
|
||||
}
|
||||
|
||||
|
||||
final 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 Matrix2x3f transform = Matrix2x3f.createTranslate(new Vector2f(0, -this.descent))
|
||||
.multiply(Matrix2x3f.createScale(scale));
|
||||
final PathModel model = glyph.getModel();
|
||||
if (model != null) {
|
||||
final Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8, config);
|
||||
final Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8,
|
||||
config);
|
||||
weight.fusion(redered, (int) offsetWriting, 0);
|
||||
}
|
||||
offsetWriting += advenceXLocal;
|
||||
|
||||
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
@ -2,59 +2,62 @@ package org.atriasoft.esvg;
|
||||
|
||||
import org.atriasoft.egami.ImageByte;
|
||||
import org.atriasoft.egami.ToolImage;
|
||||
import org.atriasoft.esvg.internal.Log;
|
||||
import org.atriasoft.esvg.render.PathModel;
|
||||
import org.atriasoft.etk.Color;
|
||||
import org.atriasoft.etk.Configs;
|
||||
import org.atriasoft.etk.math.Vector2f;
|
||||
import org.atriasoft.etk.math.Vector2i;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Graphic context is used to manage dynamic
|
||||
* Graphic context is used to manage dynamic
|
||||
* @author heero
|
||||
*
|
||||
*/
|
||||
public class GraphicContext {
|
||||
static final Logger LOGGER = LoggerFactory.getLogger(GraphicContext.class);
|
||||
private EsvgDocument document = new EsvgDocument();
|
||||
PaintState paintState;
|
||||
private PathModel path = null;
|
||||
private Vector2i size = Vector2i.VALUE_32;
|
||||
|
||||
|
||||
public GraphicContext() {
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
public Vector2i calculateTextSize(final String data) {
|
||||
return FontCache.getFont(Configs.getConfigFonts().getName(), false, false).calculateTextSize(Configs.getConfigFonts().getSize(), data);
|
||||
return FontCache.getFont(Configs.getConfigFonts().getName(), false, false)
|
||||
.calculateTextSize(Configs.getConfigFonts().getSize(), data);
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
@ -62,7 +65,7 @@ public class GraphicContext {
|
||||
public Color getColorFill() {
|
||||
return this.paintState.getFill();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the stroke color.
|
||||
* @return Stroke color.
|
||||
@ -70,85 +73,86 @@ public class GraphicContext {
|
||||
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 int getTextHeight() {
|
||||
return getTextHeight(Configs.getConfigFonts().getSize());
|
||||
}
|
||||
|
||||
public int getTextSize() {
|
||||
return Configs.getConfigFonts().getSize();
|
||||
}
|
||||
|
||||
|
||||
public int getTextHeight(final float height) {
|
||||
return FontCache.getFont(Configs.getConfigFonts().getName(), false, false).calculateFontRealHeight((int) height);
|
||||
return FontCache.getFont(Configs.getConfigFonts().getName(), false, false)
|
||||
.calculateFontRealHeight((int) height);
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
LOGGER.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");
|
||||
LOGGER.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");
|
||||
LOGGER.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");
|
||||
LOGGER.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;
|
||||
@ -157,7 +161,7 @@ public class GraphicContext {
|
||||
this.document.addElement(new Path(this.path, this.paintState.clone()));
|
||||
this.path = null;
|
||||
}
|
||||
|
||||
|
||||
public void pathStopLinked() {
|
||||
if (this.path == null) {
|
||||
return;
|
||||
@ -166,43 +170,43 @@ public class GraphicContext {
|
||||
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");
|
||||
LOGGER.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");
|
||||
LOGGER.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");
|
||||
LOGGER.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");
|
||||
LOGGER.error("Path not empty ... Need call pathStart() before");
|
||||
pathStop();
|
||||
}
|
||||
this.document.addElement(new Rectangle(position, width, this.paintState.clone()));
|
||||
}
|
||||
|
||||
|
||||
public ImageByte render() {
|
||||
return ToolImage.convertImageByte(this.document.renderImageFloatRGBA(null));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set the fill color
|
||||
* @param color Color to set on fill
|
||||
@ -211,7 +215,7 @@ public class GraphicContext {
|
||||
public void setColorFill(final Color color) {
|
||||
this.paintState.setFill(color);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set the stroke color
|
||||
* @param color Color to set on stroke
|
||||
@ -220,23 +224,23 @@ public class GraphicContext {
|
||||
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
|
||||
@ -246,7 +250,7 @@ public class GraphicContext {
|
||||
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
|
||||
@ -256,17 +260,18 @@ public class GraphicContext {
|
||||
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, Configs.getConfigFonts().getName(), height, data, this.paintState.clone()));
|
||||
this.document.addElement(
|
||||
new Text(position, Configs.getConfigFonts().getName(), height, data, this.paintState.clone()));
|
||||
}
|
||||
|
||||
|
||||
public void text(final Vector2f position, final String data) {
|
||||
text(position, Configs.getConfigFonts().getSize(), data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,13 @@ 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
|
||||
@ -16,44 +17,51 @@ import org.atriasoft.exml.model.XmlNode;
|
||||
* @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) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.debug(spacingDist(spacing) + "Group (START) fill=" + this.paint.fill.first + "/" + this.paint.fill.second + " stroke=" + this.paint.stroke.first + "/" + this.paint.stroke.second
|
||||
+ " stroke-width=" + this.paint.strokeWidth);
|
||||
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);
|
||||
for (final Base it : this.subElementList) {
|
||||
if (it != null) {
|
||||
it.display(spacing + 1);
|
||||
}
|
||||
}
|
||||
Log.debug(spacingDist(spacing) + "Group (STOP)");
|
||||
LOGGER.debug(spacingDist(spacing) + "Group (STOP)");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::group");
|
||||
for (Base it : this.subElementList) {
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::group");
|
||||
for (final Base it : this.subElementList) {
|
||||
if (it != null) {
|
||||
it.draw(myRenderer, basicTrans, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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) {
|
||||
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) {
|
||||
if (it != null) {
|
||||
it.drawShapePoints(out, recurtionMax, threshold, basicTrans, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
if (element == null) {
|
||||
@ -66,18 +74,18 @@ public class Group extends Base {
|
||||
pos = parseXmlPosition(element);
|
||||
size = parseXmlSize(element);
|
||||
parsePaintAttr(element);
|
||||
Log.verbose("parsed G1. trans : " + this.transformMatrix);
|
||||
|
||||
LOGGER.trace("parsed G1. trans : " + this.transformMatrix);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
Log.verbose("parsed G2. trans : " + this.transformMatrix);
|
||||
|
||||
|
||||
LOGGER.trace("parsed G2. trans : " + this.transformMatrix);
|
||||
|
||||
sizeMax.value = Vector2f.ZERO;
|
||||
Dynamic<Vector2f> tmpPos = new Dynamic<Vector2f>(Vector2f.ZERO);
|
||||
final Dynamic<Vector2f> tmpPos = new Dynamic<>(Vector2f.ZERO);
|
||||
// parse all sub node :
|
||||
for (XmlNode it : element.getNodes()) {
|
||||
if (!(it instanceof XmlElement child)) {
|
||||
for (final XmlNode it : element.getNodes()) {
|
||||
if (!(it instanceof final XmlElement child)) {
|
||||
// can be a comment ...
|
||||
continue;
|
||||
}
|
||||
@ -103,14 +111,15 @@ public class Group extends Base {
|
||||
} else if (child.getValue().equals("text")) {
|
||||
elementParser = new Text(this.paint);
|
||||
} else {
|
||||
Log.error("node not suported : '" + child.getValue() + "' must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
|
||||
LOGGER.error("node not suported : '" + child.getValue()
|
||||
+ "' must be [g,a,path,rect,circle,ellipse,line,polyline,polygon,text]");
|
||||
}
|
||||
if (elementParser == null) {
|
||||
Log.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
|
||||
LOGGER.error("error on node: '" + child.getValue() + "' allocation error or not supported ...");
|
||||
continue;
|
||||
}
|
||||
if (!elementParser.parseXML(child, this.transformMatrix, tmpPos)) {
|
||||
Log.error(" error on node: '" + child.getValue() + "' Sub Parsing ERROR");
|
||||
LOGGER.error(" error on node: '" + child.getValue() + "' Sub Parsing ERROR");
|
||||
elementParser = null;
|
||||
continue;
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ 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;
|
||||
@ -14,6 +13,8 @@ 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
|
||||
@ -21,47 +22,49 @@ import org.atriasoft.exml.model.XmlElement;
|
||||
* @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
|
||||
|
||||
|
||||
public Line(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
public Line(final Vector2f startPos, final Vector2f stopPos, final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
this.startPos = startPos;
|
||||
this.stopPos = stopPos;
|
||||
}
|
||||
|
||||
|
||||
private PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final PathModel out = new PathModel();
|
||||
out.clear();
|
||||
out.moveTo(false, this.startPos);
|
||||
out.lineTo(false, this.stopPos);
|
||||
out.stop();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.debug(spacingDist(spacing) + "Line " + this.startPos + " to " + this.stopPos);
|
||||
LOGGER.debug(spacingDist(spacing) + "Line " + this.startPos + " to " + this.stopPos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Line");
|
||||
|
||||
PathModel listElement = createPath();
|
||||
|
||||
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
|
||||
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Line");
|
||||
|
||||
final PathModel listElement = createPath();
|
||||
|
||||
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
|
||||
|
||||
PointList listPoints = new PointList();
|
||||
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);
|
||||
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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -70,7 +73,8 @@ 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
|
||||
@ -79,24 +83,29 @@ public class Line extends Base {
|
||||
// add on images:
|
||||
myRenderer.print(tmpFill, colorFill, tmpStroke, colorStroke, this.paint.opacity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
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);
|
||||
PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
// line must have a minimum size...
|
||||
@ -106,10 +115,10 @@ public class Line extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
String content = element.getAttribute("x1", "");
|
||||
if (content.length() != 0) {
|
||||
this.startPos = this.startPos.withX(parseLength(content));
|
||||
|
@ -3,7 +3,6 @@ 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.Distance;
|
||||
@ -14,6 +13,8 @@ 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
|
||||
@ -22,63 +23,64 @@ import org.atriasoft.exml.model.XmlNode;
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
|
||||
public SpreadMethod spread = SpreadMethod.PAD; //!< in case of using a single gradient in multiple gradient, the gradient is store in an other element...
|
||||
|
||||
|
||||
public GradientUnits unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX; //!< incompatible with href
|
||||
|
||||
|
||||
public LinearGradient(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::LinearGradient");
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::LinearGradient");
|
||||
}
|
||||
|
||||
|
||||
public List<Pair<Float, Color>> getColors(final EsvgDocument document) {
|
||||
if (this.href.isEmpty()) {
|
||||
return this.data;
|
||||
}
|
||||
if (document == null) {
|
||||
Log.error("Get null input for document");
|
||||
LOGGER.error("Get null input for document");
|
||||
return this.data;
|
||||
}
|
||||
Base base = document.getReference(this.href);
|
||||
final Base base = document.getReference(this.href);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" + this.href + "'");
|
||||
LOGGER.error("Can not get base : '" + this.href + "'");
|
||||
return this.data;
|
||||
}
|
||||
if (base instanceof RadialGradient gradientR) {
|
||||
if (base instanceof final RadialGradient gradientR) {
|
||||
return gradientR.getColors(document);
|
||||
}
|
||||
if (base instanceof LinearGradient gradientL) {
|
||||
if (base instanceof final LinearGradient gradientL) {
|
||||
return gradientL.getColors(document);
|
||||
}
|
||||
return this.data;
|
||||
}
|
||||
|
||||
|
||||
public Dimension2f getPosition1() {
|
||||
return this.pos1;
|
||||
}
|
||||
|
||||
|
||||
public Dimension2f getPosition2() {
|
||||
return this.pos2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
{
|
||||
@ -87,16 +89,16 @@ public class LinearGradient extends Base {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ---------------- get unique ID ----------------
|
||||
this.id = element.getAttribute("id", "");
|
||||
|
||||
|
||||
//parseTransform(element);
|
||||
//parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
String contentX = element.getAttribute("x1", "");
|
||||
String contentY = element.getAttribute("y1", "");
|
||||
if (!contentX.isEmpty() && !contentY.isEmpty()) {
|
||||
@ -113,7 +115,8 @@ public class LinearGradient extends Base {
|
||||
} else {
|
||||
this.unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
|
||||
if (contentX.length() != 0 && contentX != "objectBoundingBox") {
|
||||
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX + "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
LOGGER.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX
|
||||
+ "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
}
|
||||
}
|
||||
contentX = element.getAttribute("spreadMethod", "");
|
||||
@ -124,7 +127,8 @@ public class LinearGradient extends Base {
|
||||
} else {
|
||||
this.spread = SpreadMethod.PAD;
|
||||
if (contentX.length() != 0 && !contentX.equals("pad")) {
|
||||
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad");
|
||||
LOGGER.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX
|
||||
+ "' not in : {reflect/repeate/pad} use pad");
|
||||
}
|
||||
}
|
||||
// note: xlink:href is incompatible with subNode "stop"
|
||||
@ -133,19 +137,20 @@ public class LinearGradient extends Base {
|
||||
this.href = this.href.substring(1);
|
||||
}
|
||||
// parse all sub node :
|
||||
for (XmlNode it : element.getNodes()) {
|
||||
if (it instanceof XmlElement child) {
|
||||
for (final XmlNode it : element.getNodes()) {
|
||||
if (it instanceof final XmlElement child) {
|
||||
if (child.getValue().equals("stop")) {
|
||||
float offset = 100;
|
||||
Color stopColor = Color.NONE;
|
||||
String content = child.getAttribute("offset", "");
|
||||
if (content.length() != 0) {
|
||||
Pair<Float, Distance> tmp = parseLength2(content);
|
||||
final 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) {
|
||||
Log.error("offset : " + content + " res=" + tmp.first + "," + tmp.second + " Not support other than pourcent %");
|
||||
LOGGER.error("offset : " + content + " res=" + tmp.first + "," + tmp.second
|
||||
+ " Not support other than pourcent %");
|
||||
} else {
|
||||
offset = tmp.first;
|
||||
}
|
||||
@ -153,29 +158,30 @@ public class LinearGradient extends Base {
|
||||
content = child.getAttribute("stop-color", "");
|
||||
if (content.length() != 0) {
|
||||
stopColor = parseColor(content).first;
|
||||
Log.verbose(" color : '" + content + "' == > " + stopColor);
|
||||
LOGGER.trace(" 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);
|
||||
Log.verbose(" opacity : '" + content + "' == > " + stopColor);
|
||||
LOGGER.trace(" opacity : '" + content + "' == > " + stopColor);
|
||||
}
|
||||
this.data.add(new Pair<>(offset, stopColor));
|
||||
} else {
|
||||
Log.error(" node not suported : '" + child.getValue() + "' must be [stop]");
|
||||
LOGGER.error(" node not suported : '" + child.getValue() + "' must be [stop]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.data.size() != 0) {
|
||||
if (!this.href.isEmpty()) {
|
||||
Log.error(" node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
LOGGER.error(
|
||||
" node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
this.href = "";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ 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;
|
||||
@ -15,6 +14,8 @@ 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,6 +23,8 @@ import org.atriasoft.exml.model.XmlElement;
|
||||
* @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,
|
||||
@ -31,42 +34,43 @@ public class Path extends Base {
|
||||
this.listElem = listElem;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
|
||||
Command(final char cmd, final int offset) {
|
||||
this(cmd, null, offset);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static PathModel createPathModel(final String d) {
|
||||
final PathModel out = new PathModel();
|
||||
Log.verbose("Parse Path : \"" + d + "\"");
|
||||
LOGGER.trace("Parse Path : \"" + d + "\"");
|
||||
final 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();
|
||||
|
||||
// Log.verbose("Find new command : '" + sss.cmd + "'");
|
||||
|
||||
// LOGGER.trace("Find new command : '" + sss.cmd + "'");
|
||||
// if (listDot != null) {
|
||||
// for (int jjj = 0; jjj < listDot.length; jjj++) {
|
||||
// Log.verbose(" -> '" + listDot[jjj] + "'");
|
||||
// LOGGER.trace(" -> '" + listDot[jjj] + "'");
|
||||
// }
|
||||
// } else {
|
||||
// Log.verbose(" -> no elements");
|
||||
// LOGGER.trace(" -> no elements");
|
||||
// }
|
||||
switch (sss.cmd) {
|
||||
case 'm': // Move to (relative)
|
||||
relative = true;
|
||||
case 'M': // Move to (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
if (listDot.length % 2 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " must be a multiple of 2");
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " must be a multiple of 2");
|
||||
break;
|
||||
}
|
||||
// 2 Elements ...
|
||||
@ -74,134 +78,145 @@ 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) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
if (listDot.length % 2 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " must be a multiple of 2");
|
||||
LOGGER.warn("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;
|
||||
|
||||
|
||||
case 'v': // Vertical Line to (relative)
|
||||
relative = true;
|
||||
case 'V': // Vertical Line to (absolute)
|
||||
// 1 Element ...
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
for (int iii = 0; iii < listDot.length; iii++) {
|
||||
out.lineToV(relative, Float.parseFloat(listDot[iii]));
|
||||
for (final String element : listDot) {
|
||||
out.lineToV(relative, Float.parseFloat(element));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'h': // Horizantal Line to (relative)
|
||||
relative = true;
|
||||
case 'H': // Horizantal Line to (absolute)
|
||||
// 1 Element ...
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
for (int iii = 0; iii < listDot.length; iii++) {
|
||||
out.lineToH(relative, Float.parseFloat(listDot[iii]));
|
||||
for (final String element : listDot) {
|
||||
out.lineToH(relative, Float.parseFloat(element));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'q': // Quadratic Bezier curve (relative)
|
||||
relative = true;
|
||||
case 'Q': // Quadratic Bezier curve (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
// 4 Elements ...
|
||||
if (listDot.length % 4 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + " (must have 4 numbers)");
|
||||
LOGGER.warn("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;
|
||||
|
||||
|
||||
case 't': // smooth quadratic Bezier curve to (relative)
|
||||
relative = true;
|
||||
case 'T': // smooth quadratic Bezier curve to (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
// 4 Elements ...
|
||||
if (listDot.length % 2 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + " (must have 2 numbers)");
|
||||
LOGGER.warn("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;
|
||||
|
||||
|
||||
case 'c': // curve to (relative)
|
||||
relative = true;
|
||||
case 'C': // curve to (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
// 6 Elements ...
|
||||
if (listDot.length % 6 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + "(Must be a multiple of 6)");
|
||||
LOGGER.warn("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])));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 's': // smooth curve to (relative)
|
||||
relative = true;
|
||||
case 'S': // smooth curve to (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
break;
|
||||
}
|
||||
// 4 Elements ...
|
||||
if (listDot.length % 4 != 0) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length + "(Must be a multiple of 4)");
|
||||
LOGGER.warn("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;
|
||||
|
||||
|
||||
case 'a': // elliptical Arc (relative)
|
||||
relative = true;
|
||||
case 'A': // elliptical Arc (absolute)
|
||||
if (listDot == null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot);
|
||||
LOGGER.warn("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) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
|
||||
+ listDot.length);
|
||||
break;
|
||||
}
|
||||
for (int iii = 0; iii < listDot.length; iii += 7) {
|
||||
@ -213,7 +228,9 @@ 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;
|
||||
@ -222,38 +239,39 @@ public class Path extends Base {
|
||||
case 'Z': // closepath (absolute)
|
||||
// 0 Element ...
|
||||
if (listDot != null) {
|
||||
Log.warning("the PATH command " + sss.cmd + " has not the good number of element = " + listDot.length);
|
||||
LOGGER.warn("the PATH command " + sss.cmd + " has not the good number of element = "
|
||||
+ listDot.length);
|
||||
break;
|
||||
}
|
||||
out.close(relative);
|
||||
break;
|
||||
default:
|
||||
Log.error("Unknow error : '" + sss.cmd + "'");
|
||||
LOGGER.error("Unknow error : '" + sss.cmd + "'");
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//return the next char position ... (after 'X' or NULL)
|
||||
private static Command extractCmd(final List<String> input, final int offset) {
|
||||
if (input.size() <= offset) {
|
||||
// Log.warning("parse command : END");
|
||||
// LOGGER.warn("parse command : END");
|
||||
return null;
|
||||
}
|
||||
// Log.warning("parse command : (rest) " + offset);
|
||||
// LOGGER.warn("parse command : (rest) " + offset);
|
||||
// for (int iii = offset; iii < input.size(); iii++) {
|
||||
// Log.warning(" -[" + iii + "] '" + input.get(iii) + "'");
|
||||
// LOGGER.warn(" -[" + iii + "] '" + input.get(iii) + "'");
|
||||
// }
|
||||
if (input.get(offset).length() != 1) {
|
||||
Log.error("Error in the SVG Path : '" + input.get(offset) + "' [" + Integer.toString(offset));
|
||||
LOGGER.error("Error in the SVG Path : '" + input.get(offset) + "' [" + Integer.toString(offset));
|
||||
return null;
|
||||
}
|
||||
final char cmd = input.get(offset).charAt(0);
|
||||
if (!((cmd <= 'Z' && cmd >= 'A') || (cmd <= 'z' && cmd >= 'a'))) {
|
||||
Log.error("Error in the SVG Path : '" + cmd + "' [" + Integer.toString(offset));
|
||||
LOGGER.error("Error in the SVG Path : '" + cmd + "' [" + Integer.toString(offset));
|
||||
return null;
|
||||
}
|
||||
//Log.verbose("Find command : " + cmd);
|
||||
//LOGGER.trace("Find command : " + cmd);
|
||||
if (input.size() == offset) {
|
||||
return new Command(cmd, offset + 1);
|
||||
}
|
||||
@ -275,7 +293,7 @@ public class Path extends Base {
|
||||
}
|
||||
return new Command(cmd, outputList, iii);
|
||||
}
|
||||
|
||||
|
||||
static List<String> splitCommand(final String data) {
|
||||
final List<String> out = new ArrayList<>();
|
||||
final StringBuilder tmpString = new StringBuilder(20);
|
||||
@ -300,7 +318,7 @@ public class Path extends Base {
|
||||
isNumber = false;
|
||||
out.add(Character.toString(it));
|
||||
} else {
|
||||
Log.error("Can not parse path : '" + it + "'");
|
||||
LOGGER.error("Can not parse path : '" + it + "'");
|
||||
}
|
||||
}
|
||||
final String elements = tmpString.toString();
|
||||
@ -309,31 +327,32 @@ public class Path extends Base {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public PathModel listElement = new PathModel();
|
||||
|
||||
|
||||
public Path(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
public Path(final PathModel elements, final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
this.listElement = elements;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void display(final int spacing) {
|
||||
this.listElement.display(spacing);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Path");
|
||||
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Path");
|
||||
|
||||
final 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();
|
||||
@ -354,7 +373,8 @@ 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
|
||||
@ -366,15 +386,20 @@ public class Path extends Base {
|
||||
//myRenderer.addDebugSegment(listSegmentStroke);
|
||||
//this.listElement.debugInformation.applyMatrix(mtx);
|
||||
//myRenderer.addDebugSegment(this.listElement.debugInformation);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
final Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
|
||||
|
||||
|
||||
PointList listPoints = new PointList();
|
||||
listPoints = this.listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
@ -386,7 +411,7 @@ public class Path extends Base {
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
if (element == null) {
|
||||
@ -394,17 +419,17 @@ public class Path extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
final String elementXML1 = element.getAttribute("d", "");
|
||||
if (elementXML1.length() == 0) {
|
||||
Log.warning("path: missing 'd' attribute or empty");
|
||||
LOGGER.warn("path: missing 'd' attribute or empty");
|
||||
return false;
|
||||
}
|
||||
this.listElement = Path.createPathModel(elementXML1);
|
||||
return this.listElement != null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
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;
|
||||
@ -10,11 +13,8 @@ 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.esvg.internal.Log;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
@ -23,14 +23,15 @@ import org.atriasoft.esvg.internal.Log;
|
||||
*/
|
||||
|
||||
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) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
private PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final 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));
|
||||
@ -38,28 +39,29 @@ public class Polygon extends Base {
|
||||
out.close();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.debug(spacingDist(spacing) + "Polygon nbPoint=" + this.listPoint.size());
|
||||
LOGGER.debug(spacingDist(spacing) + "Polygon nbPoint=" + this.listPoint.size());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Polygon");
|
||||
|
||||
PathModel listElement = createPath();
|
||||
|
||||
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
|
||||
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Polygon");
|
||||
|
||||
final PathModel listElement = createPath();
|
||||
|
||||
final 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);
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
Weight tmpFill = new Weight();
|
||||
Weight tmpStroke = new Weight();
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, 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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -74,7 +76,8 @@ 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
|
||||
@ -85,24 +88,29 @@ public class Polygon extends Base {
|
||||
//myRenderer.addDebugSegment(listSegmentFill);
|
||||
//myRenderer.addDebugSegment(listSegmentStroke);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
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);
|
||||
PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
if (element == null) {
|
||||
@ -110,25 +118,25 @@ public class Polygon extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
Log.verbose("parsed P1. trans: " + this.transformMatrix);
|
||||
|
||||
|
||||
LOGGER.trace("parsed P1. trans: " + this.transformMatrix);
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
Log.verbose("parsed P2. trans: " + this.transformMatrix);
|
||||
|
||||
String sss1 = element.getAttribute("points", "");
|
||||
|
||||
LOGGER.trace("parsed P2. trans: " + this.transformMatrix);
|
||||
|
||||
final String sss1 = element.getAttribute("points", "");
|
||||
if (sss1.length() == 0) {
|
||||
Log.error("(l "/*+element.Pos()*/ + ") polygon: missing points attribute");
|
||||
LOGGER.error("(l "/*+element.Pos()*/ + ") polygon: missing points attribute");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
sizeMax.value = Vector2f.ZERO;
|
||||
Log.verbose("Parse polyline : '" + sss1 + "'");
|
||||
String[] elems = sss1.split(" ");
|
||||
for (String elem : elems) {
|
||||
Vector2f pos = Vector2f.valueOf(elem);
|
||||
LOGGER.trace("Parse polyline : '" + sss1 + "'");
|
||||
final String[] elems = sss1.split(" ");
|
||||
for (final String elem : elems) {
|
||||
final Vector2f pos = Vector2f.valueOf(elem);
|
||||
this.listPoint.add(pos);
|
||||
sizeMax.value = Vector2f.max(sizeMax.value, pos);
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
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;
|
||||
@ -10,11 +13,8 @@ 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.esvg.internal.Log;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
@ -22,14 +22,15 @@ import org.atriasoft.esvg.internal.Log;
|
||||
* @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) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
private PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final PathModel out = new PathModel();
|
||||
out.clear();
|
||||
out.moveTo(false, this.listPoint.get(0));
|
||||
for (int iii = 1; iii < this.listPoint.size(); iii++) {
|
||||
@ -38,28 +39,29 @@ public class Polyline extends Base {
|
||||
out.stop();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.debug(spacingDist(spacing) + "Polyline nbPoint=" + this.listPoint.size());
|
||||
LOGGER.debug(spacingDist(spacing) + "Polyline nbPoint=" + this.listPoint.size());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Polyline");
|
||||
|
||||
PathModel listElement = createPath();
|
||||
|
||||
Matrix2x3f mtx = this.transformMatrix.multiply(basicTrans);
|
||||
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Polyline");
|
||||
|
||||
final PathModel listElement = createPath();
|
||||
|
||||
final 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);
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
Weight tmpFill = new Weight();
|
||||
Weight tmpStroke = new Weight();
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, 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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -74,7 +76,8 @@ 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
|
||||
@ -85,24 +88,29 @@ public class Polyline extends Base {
|
||||
//myRenderer.addDebugSegment(listSegmentFill);
|
||||
//myRenderer.addDebugSegment(listSegmentStroke);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
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);
|
||||
PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
// line must have a minimum size...
|
||||
@ -112,20 +120,20 @@ public class Polyline extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
String sss1 = element.getAttribute("points", "");
|
||||
|
||||
final String sss1 = element.getAttribute("points", "");
|
||||
if (sss1.length() == 0) {
|
||||
Log.error("polyline: missing points attribute");
|
||||
LOGGER.error("polyline: missing points attribute");
|
||||
return false;
|
||||
}
|
||||
sizeMax.value = Vector2f.ZERO;
|
||||
Log.verbose("Parse polyline : '" + sss1 + "'");
|
||||
String[] elems = sss1.split(" ");
|
||||
for (String elem : elems) {
|
||||
Vector2f pos = Vector2f.valueOf(elem);
|
||||
LOGGER.trace("Parse polyline : '" + sss1 + "'");
|
||||
final String[] elems = sss1.split(" ");
|
||||
for (final String elem : elems) {
|
||||
final Vector2f pos = Vector2f.valueOf(elem);
|
||||
this.listPoint.add(pos);
|
||||
sizeMax.value = Vector2f.max(sizeMax.value, pos);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ 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;
|
||||
@ -15,6 +14,8 @@ 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
|
||||
@ -22,6 +23,7 @@ import org.atriasoft.exml.model.XmlNode;
|
||||
* @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 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
|
||||
@ -29,58 +31,59 @@ public class RadialGradient extends Base {
|
||||
private Dimension1f radius = new Dimension1f(50, Distance.POURCENT); //!< Radius of the gradient
|
||||
public SpreadMethod spread = SpreadMethod.PAD;
|
||||
public GradientUnits unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
|
||||
|
||||
|
||||
public RadialGradient(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::RadialGradient");
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::RadialGradient");
|
||||
}
|
||||
|
||||
|
||||
public Dimension2f getCenter() {
|
||||
return this.center;
|
||||
}
|
||||
|
||||
|
||||
public List<Pair<Float, Color>> getColors(final EsvgDocument document) {
|
||||
if (this.href.isEmpty()) {
|
||||
return this.data;
|
||||
}
|
||||
if (document == null) {
|
||||
Log.error("Get null input for document");
|
||||
LOGGER.error("Get null input for document");
|
||||
return this.data;
|
||||
}
|
||||
Base base = document.getReference(this.href);
|
||||
final Base base = document.getReference(this.href);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" + this.href + "'");
|
||||
LOGGER.error("Can not get base : '" + this.href + "'");
|
||||
return this.data;
|
||||
}
|
||||
if (base instanceof RadialGradient gradientR) {
|
||||
if (base instanceof final RadialGradient gradientR) {
|
||||
return gradientR.getColors(document);
|
||||
}
|
||||
if (base instanceof LinearGradient gradientL) {
|
||||
if (base instanceof final LinearGradient gradientL) {
|
||||
return gradientL.getColors(document);
|
||||
}
|
||||
return this.data;
|
||||
}
|
||||
|
||||
|
||||
public Dimension2f getFocal() {
|
||||
return this.focal;
|
||||
}
|
||||
|
||||
|
||||
public Dimension1f getRadius() {
|
||||
return this.radius;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
// line must have a minimum size...
|
||||
@ -88,16 +91,16 @@ public class RadialGradient extends Base {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ---------------- get unique ID ----------------
|
||||
this.id = element.getAttribute("id", "");
|
||||
|
||||
|
||||
//parseTransform(element);
|
||||
//parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
String contentX = element.getAttribute("cx", "");
|
||||
String contentY = element.getAttribute("cy", "");
|
||||
if (!contentX.isEmpty() && !contentY.isEmpty()) {
|
||||
@ -118,7 +121,8 @@ public class RadialGradient extends Base {
|
||||
} else {
|
||||
this.unit = GradientUnits.GRADIENT_UNITS_OBJECT_BOUNDING_BOX;
|
||||
if (contentX.length() != 0 && contentX != "objectBoundingBox") {
|
||||
Log.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX + "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
LOGGER.error("Parsing error of 'gradientUnits' ==> not suported value: '" + contentX
|
||||
+ "' not in : {userSpaceOnUse/objectBoundingBox} use objectBoundingBox");
|
||||
}
|
||||
}
|
||||
contentX = element.getAttribute("spreadMethod", "");
|
||||
@ -129,7 +133,8 @@ public class RadialGradient extends Base {
|
||||
} else {
|
||||
this.spread = SpreadMethod.PAD;
|
||||
if (contentX.length() != 0 && !contentX.equals("pad")) {
|
||||
Log.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX + "' not in : {reflect/repeate/pad} use pad");
|
||||
LOGGER.error("Parsing error of 'spreadMethod' ==> not suported value: '" + contentX
|
||||
+ "' not in : {reflect/repeate/pad} use pad");
|
||||
}
|
||||
}
|
||||
// note: xlink:href is incompatible with subNode "stop"
|
||||
@ -138,19 +143,20 @@ public class RadialGradient extends Base {
|
||||
this.href = this.href.substring(1);
|
||||
}
|
||||
// parse all sub node :
|
||||
for (XmlNode it : element.getNodes()) {
|
||||
if (it instanceof XmlElement child) {
|
||||
for (final XmlNode it : element.getNodes()) {
|
||||
if (it instanceof final XmlElement child) {
|
||||
if (child.getValue().equals("stop")) {
|
||||
float offset = 100;
|
||||
Color stopColor = Color.NONE;
|
||||
String content = child.getAttribute("offset", "");
|
||||
if (content.length() != 0) {
|
||||
Pair<Float, Distance> tmp = parseLength2(content);
|
||||
final 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) {
|
||||
Log.error("offset : " + content + " res=" + tmp.first + "," + tmp.second + " Not support other than pourcent %");
|
||||
LOGGER.error("offset : " + content + " res=" + tmp.first + "," + tmp.second
|
||||
+ " Not support other than pourcent %");
|
||||
} else {
|
||||
offset = tmp.first;
|
||||
}
|
||||
@ -158,28 +164,28 @@ public class RadialGradient extends Base {
|
||||
content = child.getAttribute("stop-color", "");
|
||||
if (content.length() != 0) {
|
||||
stopColor = parseColor(content).first;
|
||||
Log.verbose(" color : \"" + content + "\" == > " + stopColor);
|
||||
LOGGER.trace(" 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);
|
||||
Log.verbose(" opacity : '" + content + "' == > " + stopColor);
|
||||
LOGGER.trace(" opacity : '" + content + "' == > " + stopColor);
|
||||
}
|
||||
this.data.add(new Pair<>(offset, stopColor));
|
||||
} else {
|
||||
Log.error("node not suported : '" + child.getValue() + "' must be [stop]");
|
||||
LOGGER.error("node not suported : '" + child.getValue() + "' must be [stop]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.data.size() != 0) {
|
||||
if (!this.href.isEmpty()) {
|
||||
Log.error("node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
LOGGER.error("node can not have an xlink:href element with sub node named: stop ==> removing href");
|
||||
this.href = "";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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,29 +22,31 @@ import org.atriasoft.etk.util.Dynamic;
|
||||
* @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
|
||||
|
||||
|
||||
public Rectangle(final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
}
|
||||
|
||||
|
||||
public Rectangle(final Vector2f position, final Vector2f size, final PaintState parentPaintState) {
|
||||
super(parentPaintState);
|
||||
this.position = position;
|
||||
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;
|
||||
this.roundedCorner = roundedCorner;
|
||||
}
|
||||
|
||||
|
||||
private PathModel createPath() {
|
||||
PathModel out = new PathModel();
|
||||
final PathModel out = new PathModel();
|
||||
out.clear();
|
||||
if (this.roundedCorner.x() == 0.0f || this.roundedCorner.y() == 0.0f) {
|
||||
out.moveTo(false, this.position);
|
||||
@ -55,43 +57,50 @@ 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();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.debug(spacingDist(spacing) + "Rectangle : pos=" + this.position + " size=" + this.size + " corner=" + this.roundedCorner);
|
||||
LOGGER.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) {
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
Weight tmpFill = new Weight();
|
||||
Weight tmpStroke = new Weight();
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, 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);
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
@ -106,7 +115,8 @@ 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
|
||||
@ -116,27 +126,32 @@ public class Rectangle extends Base {
|
||||
myRenderer.print(tmpFill, colorFill, tmpStroke, colorStroke, this.paint.opacity);
|
||||
//myRenderer.addDebugSegment(listSegmentFill);
|
||||
//myRenderer.addDebugSegment(listSegmentStroke)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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();
|
||||
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();
|
||||
Matrix2x3f mtx = this.transformMatrix;
|
||||
mtx = mtx.multiply(basicTrans);
|
||||
PointList listPoints;
|
||||
listPoints = listElement.generateListPoints(level, recurtionMax, threshold);
|
||||
listPoints.applyMatrix(mtx);
|
||||
for (List<Point> it : listPoints.data) {
|
||||
List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (Point itDot : it) {
|
||||
for (final List<Point> it : listPoints.data) {
|
||||
final List<Vector2f> listPoint = new ArrayList<>();
|
||||
for (final Point itDot : it) {
|
||||
listPoint.add(itDot.pos);
|
||||
}
|
||||
out.add(listPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
if (element == null) {
|
||||
@ -145,16 +160,16 @@ public class Rectangle extends Base {
|
||||
this.position = Vector2f.ZERO;
|
||||
this.size = Vector2f.ZERO;
|
||||
this.roundedCorner = Vector2f.ZERO;
|
||||
|
||||
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
this.position = parseXmlPosition(element);
|
||||
this.size = parseXmlSize(element);
|
||||
|
||||
|
||||
String content = element.getAttribute("rx", "");
|
||||
if (content.length() != 0) {
|
||||
this.roundedCorner = this.roundedCorner.withX(parseLength(content));
|
||||
@ -163,7 +178,8 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ 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;
|
||||
@ -16,6 +15,8 @@ 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
|
||||
@ -23,106 +24,116 @@ import org.atriasoft.exml.model.XmlText;
|
||||
* @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<>();
|
||||
|
||||
|
||||
public Text(final PaintState parentPaintState) {
|
||||
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.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()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(final int spacing) {
|
||||
Log.verbose(spacingDist(spacing) + "Text : ");
|
||||
for (TextSpan elem : this.texts) {
|
||||
Log.debug(spacingDist(spacing + 1) + elem.toString());
|
||||
LOGGER.trace(spacingDist(spacing) + "Text : ");
|
||||
for (final TextSpan elem : this.texts) {
|
||||
LOGGER.debug(spacingDist(spacing + 1) + elem.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
|
||||
Log.verbose(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position);
|
||||
LOGGER.trace(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position);
|
||||
if (this.texts.size() == 0) {
|
||||
Log.verbose(spacingDist(level + 1) + "No text ...");
|
||||
LOGGER.trace(spacingDist(level + 1) + "No text ...");
|
||||
return;
|
||||
}
|
||||
boolean withKerning = true;
|
||||
|
||||
for (TextSpan elem : this.texts) {
|
||||
final boolean withKerning = true;
|
||||
|
||||
for (final TextSpan elem : this.texts) {
|
||||
// get the font or a generic font of the program.
|
||||
EsvgFont font = FontCache.getFont(elem.fontState().fontName(), elem.fontState().bold(), elem.fontState().italic());
|
||||
final EsvgFont font = FontCache.getFont(elem.fontState().fontName(), elem.fontState().bold(),
|
||||
elem.fontState().italic());
|
||||
if (font == null) {
|
||||
Log.error("Can not get the font :" + elem.fontState());
|
||||
LOGGER.error("Can not get the font :" + elem.fontState());
|
||||
return;
|
||||
}
|
||||
|
||||
int realSize = font.calculateFontRealHeight((int) elem.fontState().fontSize());
|
||||
float scale = realSize / font.getUnitsPerEm();
|
||||
//Log.warning("elem.fontState() =" + elem.fontState());
|
||||
//Log.warning("scale =" + scale + " font size = " + elem.fontState().fontSize() + " realSize=" + realSize);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
float offsetWriting = 0;
|
||||
int lastValue = 0;
|
||||
for (char uVal : elem.text().toCharArray()) {
|
||||
Log.verbose(spacingDist(level) + " elem.position = " + elem.position());
|
||||
Glyph glyph = font.getGlyph(uVal);
|
||||
for (final char uVal : elem.text().toCharArray()) {
|
||||
LOGGER.trace(
|
||||
spacingDist(level) + " elem.position = " + elem.position());
|
||||
final Glyph glyph = font.getGlyph(uVal);
|
||||
if (glyph == null) {
|
||||
//lastValue = uVal;
|
||||
continue;
|
||||
}
|
||||
if (withKerning) {
|
||||
offsetWriting -= glyph.getKerning(lastValue) * scale;
|
||||
Log.verbose(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
LOGGER.trace(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
lastValue = uVal;
|
||||
}
|
||||
|
||||
float advenceXLocal = glyph.getHorizAdvX() * scale;
|
||||
|
||||
|
||||
final float advenceXLocal = glyph.getHorizAdvX() * scale;
|
||||
|
||||
//Matrix2x3f mtx = this.transformMatrix;
|
||||
Vector2f tranlate = new Vector2f(elem.position().x() + offsetWriting, elem.position().y() - font.getDescent() * scale);
|
||||
Log.verbose("translate : " + tranlate);
|
||||
Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate);
|
||||
Matrix2x3f scaleGlyph = Matrix2x3f.createScale(new Vector2f(scale, -scale));
|
||||
|
||||
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));
|
||||
|
||||
//Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate).multiply(Matrix2x3f.createScale(scale));
|
||||
//mtx = translateGlyph.multiply(this.transformMatrix);
|
||||
//mtx = mtx.multiply(translateGlyph);
|
||||
//mtx = mtx.multiply(basicTrans);
|
||||
|
||||
|
||||
//Matrix2x3f mtx = this.transformMatrix;
|
||||
//mtx = mtx.multiply(basicTrans);
|
||||
|
||||
|
||||
Matrix2x3f mtx = scaleGlyph;
|
||||
mtx = mtx.multiply(translateGlyph);
|
||||
mtx = mtx.multiply(this.transformMatrix);
|
||||
mtx = mtx.multiply(basicTrans);
|
||||
//Matrix2x3f mtx = this.transformMatrix;
|
||||
//mtx = mtx.multiply(basicTrans);
|
||||
|
||||
PathModel listElement = glyph.getModel();
|
||||
|
||||
final PathModel listElement = glyph.getModel();
|
||||
if (listElement != null) {
|
||||
//--------------------------------------------------
|
||||
// -- Generate Fill weight
|
||||
//--------------------------------------------------
|
||||
PointList listPoints = listElement.generateListPoints(level, myRenderer.getInterpolationRecurtionMax(), myRenderer.getInterpolationThreshold());
|
||||
DynamicColor colorFill = DynamicColor.createColor(this.paint.fill, mtx);
|
||||
Weight tmpFill = new 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();
|
||||
// Check if we need to display background
|
||||
if (colorFill != null) {
|
||||
SegmentList listSegmentFill = new SegmentList();
|
||||
final SegmentList listSegmentFill = new SegmentList();
|
||||
listSegmentFill.createSegmentList(listPoints);
|
||||
colorFill.setViewPort(listSegmentFill.getViewPort());
|
||||
listSegmentFill.applyMatrix(mtx);
|
||||
@ -130,36 +141,38 @@ public class Text extends Base {
|
||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||
tmpFill.generate(myRenderer.getSize(), myRenderer.getNumberSubScanLine(), listSegmentFill);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// -- Generate Stroke weight
|
||||
//--------------------------------------------------
|
||||
|
||||
Weight tmpStroke = new Weight();
|
||||
|
||||
final Weight tmpStroke = new Weight();
|
||||
DynamicColor colorStroke = null;
|
||||
if (this.paint.strokeWidth > 0.0f) {
|
||||
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
|
||||
if (colorStroke == null) {
|
||||
Log.verbose("Color stroke is null: ...");
|
||||
LOGGER.trace("Color stroke is null: ...");
|
||||
} else {
|
||||
// check if we need to display stroke:
|
||||
SegmentList listSegmentStroke = new SegmentList();
|
||||
listSegmentStroke.createSegmentListStroke(listPoints, this.paint.strokeWidth, this.paint.lineCap, this.paint.lineJoin, this.paint.miterLimit);
|
||||
final 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;
|
||||
//Log.warning("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
|
||||
//LOGGER.warn("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parseXML(final XmlElement element, final Matrix2x3f parentTrans, final Dynamic<Vector2f> sizeMax) {
|
||||
// line must have a minimum size...
|
||||
@ -169,37 +182,37 @@ public class Text extends Base {
|
||||
}
|
||||
parseTransform(element);
|
||||
parsePaintAttr(element);
|
||||
|
||||
|
||||
// add the property of the parrent modifications ...
|
||||
this.transformMatrix = this.transformMatrix.multiply(parentTrans);
|
||||
|
||||
|
||||
boolean italic = false;
|
||||
String fontStyle = element.getAttribute("font-style", "normal");
|
||||
final String fontStyle = element.getAttribute("font-style", "normal");
|
||||
if ("italic".equals(fontStyle)) {
|
||||
italic = true;
|
||||
} else if ("normal".equals(fontStyle)) {
|
||||
italic = false;
|
||||
} else {
|
||||
Log.error("can not parse font-style='" + fontStyle + "' support ['normal', 'italic']");
|
||||
LOGGER.error("can not parse font-style='" + fontStyle + "' support ['normal', 'italic']");
|
||||
}
|
||||
boolean bold = false;
|
||||
String fontWeight = element.getAttribute("font-weight", "normal");
|
||||
final String fontWeight = element.getAttribute("font-weight", "normal");
|
||||
if ("bold".equals(fontWeight)) {
|
||||
bold = true;
|
||||
} else if ("normal".equals(fontWeight)) {
|
||||
bold = false;
|
||||
} else {
|
||||
Log.error("can not parse font-weight='" + fontWeight + "' support ['normal', 'bold']");
|
||||
LOGGER.error("can not parse font-weight='" + fontWeight + "' support ['normal', 'bold']");
|
||||
}
|
||||
String fontFamily = element.getAttribute("font-family", "FreeSans");
|
||||
if (fontStyle.contains(";")) {
|
||||
fontFamily = fontFamily.split(";")[0];
|
||||
}
|
||||
Log.info("Get font family: '" + fontFamily + "'");
|
||||
|
||||
float fontSize = parseLength(element.getAttribute("font-size", "50"));
|
||||
LOGGER.info("Get font family: '" + fontFamily + "'");
|
||||
|
||||
final float fontSize = parseLength(element.getAttribute("font-size", "50"));
|
||||
this.position = Vector2f.ZERO;
|
||||
|
||||
|
||||
String content = element.getAttribute("x", "");
|
||||
if (content.length() != 0) {
|
||||
this.position = this.position.withX(parseLength(content));
|
||||
@ -208,31 +221,32 @@ public class Text extends Base {
|
||||
if (content.length() != 0) {
|
||||
this.position = this.position.withY(parseLength(content));
|
||||
}
|
||||
|
||||
|
||||
// parse all subElement in the Text <TSPAN/>
|
||||
for (XmlNode elem : element.getNodes()) {
|
||||
if (elem instanceof XmlElement elementSpan && "tspan".equals(elementSpan.getValue())) {
|
||||
|
||||
} else if (elem instanceof XmlText elementText) {
|
||||
this.texts.add(new TextSpan(this.position, elementText.getValue(), new FontProperty(fontFamily, fontSize, bold, italic), this.paint.clone()));
|
||||
for (final XmlNode elem : element.getNodes()) {
|
||||
if (elem instanceof final 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 {
|
||||
Log.warning("not managed element : " + elem);
|
||||
LOGGER.warn("not managed element : " + elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//sizeMax.value = Vector2f.max(this.startPos, this.stopPos);
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
/*
|
||||
public Weight render(final String data, final int fontSize, final boolean withKerning) {
|
||||
int widthOut = calculateWidth(data, fontSize, withKerning);
|
||||
|
||||
|
||||
int realSize = calculateFontRealHeight(fontSize);
|
||||
float scale = realSize / (float) this.unitsPerEm;
|
||||
|
||||
|
||||
Weight weight = new Weight(new Vector2i(widthOut, realSize));
|
||||
|
||||
|
||||
int offsetWriting = 0;
|
||||
int lastValue = 0;
|
||||
for (char uVal : data.toCharArray()) {
|
||||
@ -243,12 +257,12 @@ public class Text extends Base {
|
||||
}
|
||||
if (withKerning) {
|
||||
offsetWriting -= glyph.getKerning(lastValue) * scale;
|
||||
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
LOGGER.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
|
||||
lastValue = uVal;
|
||||
}
|
||||
|
||||
|
||||
float advenceXLocal = glyph.getHorizAdvX() * scale;
|
||||
|
||||
|
||||
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();
|
||||
@ -257,7 +271,7 @@ public class Text extends Base {
|
||||
weight.fusion(redered, offsetWriting, 0);
|
||||
}
|
||||
offsetWriting += advenceXLocal;
|
||||
|
||||
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
@ -269,17 +283,21 @@ 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);
|
||||
}
|
||||
|
@ -5,77 +5,80 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
public static Glyph valueOf(final XmlElement element, final EsvgFont font) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
String name = element.getAttribute("glyph-name", null);
|
||||
Log.verbose("get glyph name = '" + name + "'");
|
||||
String tmpValue = element.getAttribute("horiz-adv-x", null);
|
||||
final String name = element.getAttribute("glyph-name", null);
|
||||
LOGGER.trace("get glyph name = '" + name + "'");
|
||||
final 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);
|
||||
}
|
||||
Log.verbose(" horizAdvX= '" + horizAdvX + "'");
|
||||
String unicode = element.getAttribute("unicode", null);
|
||||
Log.verbose(" unicode= '" + unicode + "'");
|
||||
LOGGER.trace(" horizAdvX= '" + horizAdvX + "'");
|
||||
final String unicode = element.getAttribute("unicode", null);
|
||||
LOGGER.trace(" unicode= '" + unicode + "'");
|
||||
if (unicode == null) {
|
||||
Log.debug("Not manage glyph : '" + name + "' (missing unicode value)");
|
||||
LOGGER.debug("Not manage glyph : '" + name + "' (missing unicode value)");
|
||||
return null;
|
||||
}
|
||||
String d = element.getAttribute("d", null);
|
||||
Log.verbose(" d= '" + d + "'");
|
||||
final String d = element.getAttribute("d", null);
|
||||
LOGGER.trace(" d= '" + d + "'");
|
||||
int unicodeValue = 0;
|
||||
if (unicode.startsWith("&#x") && unicode.endsWith(";")) {
|
||||
String subElement = unicode.substring(3, unicode.length() - 1);
|
||||
final String subElement = unicode.substring(3, unicode.length() - 1);
|
||||
if (subElement.indexOf("&") != -1) {
|
||||
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
return null;
|
||||
}
|
||||
unicodeValue = Integer.parseInt(subElement, 16);
|
||||
} else if (unicode.startsWith("&#") && unicode.endsWith(";")) {
|
||||
String subElement = unicode.substring(2, unicode.length() - 1);
|
||||
final String subElement = unicode.substring(2, unicode.length() - 1);
|
||||
if (subElement.indexOf("&") != -1) {
|
||||
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
return null;
|
||||
}
|
||||
unicodeValue = Integer.parseInt(subElement, 16);
|
||||
} else if (unicode.length() != 1) {
|
||||
Log.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
LOGGER.debug("not supported glyph concatenarion" + name + " value='" + unicode + "'");
|
||||
return null;
|
||||
} else {
|
||||
unicodeValue = unicode.charAt(0);
|
||||
}
|
||||
Log.verbose(" unicodeValue= '" + unicodeValue + "'");
|
||||
Glyph out = new Glyph(horizAdvX, d, name, unicode, unicodeValue);
|
||||
LOGGER.trace(" unicodeValue= '" + unicodeValue + "'");
|
||||
final 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();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
private int horizAdvX;
|
||||
private List<Kerning> kernings = new ArrayList<>();
|
||||
private PathModel model;
|
||||
private String name;
|
||||
private final String path;
|
||||
private String unicode;
|
||||
|
||||
|
||||
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;
|
||||
@ -83,8 +86,9 @@ public class Glyph {
|
||||
this.unicode = unicode;
|
||||
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;
|
||||
@ -92,73 +96,74 @@ public class Glyph {
|
||||
this.unicode = unicode;
|
||||
this.unicodeValue = unicodeValue;
|
||||
}
|
||||
|
||||
|
||||
public void addKerning(final List<Kerning> elementsKerning) {
|
||||
this.kernings.addAll(elementsKerning);
|
||||
}
|
||||
|
||||
|
||||
public int getHorizAdvX() {
|
||||
return this.horizAdvX;
|
||||
}
|
||||
|
||||
|
||||
public float getKerning(final int unicodeValue) {
|
||||
if (unicodeValue == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
for (Kerning elem : this.kernings) {
|
||||
for (final Kerning elem : this.kernings) {
|
||||
if (elem.unicode() == unicodeValue) {
|
||||
Log.verbose("Get kerning between : '" + (char) this.unicodeValue + "' and '" + (char) unicodeValue + "' => " + elem.offset());
|
||||
LOGGER.trace("Get kerning between : '" + (char) this.unicodeValue + "' and '" + (char) unicodeValue
|
||||
+ "' => " + elem.offset());
|
||||
return elem.offset();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public List<Kerning> getKernings() {
|
||||
return this.kernings;
|
||||
}
|
||||
|
||||
|
||||
public PathModel getModel() {
|
||||
if (this.model == null && this.path != null) {
|
||||
this.model = Path.createPathModel(this.path);
|
||||
}
|
||||
return this.model;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
public String getUnicode() {
|
||||
return this.unicode;
|
||||
}
|
||||
|
||||
|
||||
public Integer getUnicodeValue() {
|
||||
return this.unicodeValue;
|
||||
}
|
||||
|
||||
|
||||
public void setHorizAdvX(final int horizAdvX) {
|
||||
this.horizAdvX = horizAdvX;
|
||||
}
|
||||
|
||||
|
||||
public void setKernings(final List<Kerning> kernings) {
|
||||
this.kernings = kernings;
|
||||
}
|
||||
|
||||
|
||||
public void setModel(final PathModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public void setUnicode(final String unicode) {
|
||||
this.unicode = unicode;
|
||||
}
|
||||
|
||||
|
||||
public void setUnicodeValue(final int unicodeValue) {
|
||||
this.unicodeValue = unicodeValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
package org.atriasoft.esvg.internal;
|
||||
|
||||
import org.atriasoft.reggol.LogLevel;
|
||||
import org.atriasoft.reggol.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 Exception e, final String data) {
|
||||
e.printStackTrace();
|
||||
if (PRINT_CRITICAL || FORCE_ALL) {
|
||||
Logger.critical(LIB_NAME_DRAW, data + " : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void critical(final String data, final Object... objects) {
|
||||
if (PRINT_CRITICAL || FORCE_ALL) {
|
||||
Logger.critical(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(final String data, final Object... objects) {
|
||||
if (PRINT_DEBUG || FORCE_ALL) {
|
||||
Logger.debug(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void error(final String data, final Object... objects) {
|
||||
if (PRINT_ERROR || FORCE_ALL) {
|
||||
Logger.error(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void info(final String data, final Object... objects) {
|
||||
if (PRINT_INFO || FORCE_ALL) {
|
||||
Logger.info(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void print(final String data, final Object... objects) {
|
||||
if (PRINT_PRINT || FORCE_ALL) {
|
||||
Logger.print(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void todo(final String data, final Object... objects) {
|
||||
if (PRINT_TODO || FORCE_ALL) {
|
||||
Logger.todo(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verbose(final String data, final Object... objects) {
|
||||
if (PRINT_VERBOSE || FORCE_ALL) {
|
||||
Logger.verbose(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning(final String data, final Object... objects) {
|
||||
if (PRINT_WARNING || FORCE_ALL) {
|
||||
Logger.warning(LIB_NAME_DRAW, data, objects);
|
||||
}
|
||||
}
|
||||
|
||||
private Log() {}
|
||||
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
package org.atriasoft.esvg.render;
|
||||
|
||||
import org.atriasoft.esvg.EsvgDocument;
|
||||
import org.atriasoft.esvg.internal.Log;
|
||||
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;
|
||||
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
@ -15,22 +16,24 @@ import org.atriasoft.etk.util.Pair;
|
||||
*/
|
||||
|
||||
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()) {
|
||||
Log.verbose("use stroke color :" + color);
|
||||
LOGGER.trace("use stroke color :" + color);
|
||||
return new DynamicColorUni(color.first);
|
||||
}
|
||||
return new DynamicColorSpecial(color.second, mtx);
|
||||
}
|
||||
|
||||
|
||||
void generate(EsvgDocument document);
|
||||
|
||||
|
||||
public Color getColor(Vector2i pos);
|
||||
|
||||
|
||||
public void setViewPort(Pair<Vector2f, Vector2f> viewPort);
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ 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;
|
||||
@ -18,38 +17,54 @@ 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;
|
||||
|
||||
public class DynamicColorSpecial implements DynamicColor {
|
||||
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();
|
||||
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();
|
||||
if (diviseur != 0.0f) {
|
||||
float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x() + vect1.y() * point2.x()) / diviseur;
|
||||
final 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));
|
||||
}
|
||||
Log.error("Get divider / 0.0f");
|
||||
LOGGER.error("Get divider / 0.0f");
|
||||
return point2;
|
||||
}
|
||||
|
||||
|
||||
protected static Pair<Vector2f, Vector2f> intersectLineToCircle(final Vector2f pos1, final Vector2f pos2) {
|
||||
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
|
||||
v1 = pos2.less(pos1);
|
||||
//vector2D from point 1 to the circle's center
|
||||
v2 = center.less(pos1);
|
||||
|
||||
float dot = v1.dot(v2);
|
||||
Vector2f proj1 = new Vector2f(((dot / (v1.length2())) * v1.x()), ((dot / (v1.length2())) * v1.y()));
|
||||
Vector2f midpt = pos1.add(proj1);
|
||||
|
||||
|
||||
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 distToCenter = midpt.less(center).length2();
|
||||
if (distToCenter > radius * radius) {
|
||||
return new Pair<>(Vector2f.ZERO, Vector2f.ZERO);
|
||||
@ -69,7 +84,7 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
v1 = v1.multiply(distToIntersection);
|
||||
return new Pair<>(midpt.add(v1), midpt.less(v1));
|
||||
}
|
||||
|
||||
|
||||
public Vector2f axeX;
|
||||
public Vector2f axeY;
|
||||
public Vector2f baseSize;
|
||||
@ -81,56 +96,56 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
public float focalLength;
|
||||
public boolean linear;
|
||||
public Matrix2x3f matrix;
|
||||
|
||||
|
||||
public Vector2f pos1; // in radius ==> center
|
||||
|
||||
|
||||
public Vector2f pos2; // in radius ==> radius end position
|
||||
|
||||
|
||||
public SpreadMethod spread;
|
||||
|
||||
|
||||
public GradientUnits unit;
|
||||
|
||||
|
||||
public Pair<Vector2f, Vector2f> viewPort;
|
||||
|
||||
|
||||
public DynamicColorSpecial(final String link, final Matrix2x3f mtx) {
|
||||
this.linear = true;
|
||||
this.colorName = link;
|
||||
this.matrix = mtx;
|
||||
this.viewPort = new Pair<>(Vector2f.MAX_VALUE, Vector2f.MAX_VALUE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void generate(final EsvgDocument document) {
|
||||
if (document == null) {
|
||||
Log.error("Get null input for document");
|
||||
LOGGER.error("Get null input for document");
|
||||
}
|
||||
Base base = document.getReference(this.colorName);
|
||||
final Base base = document.getReference(this.colorName);
|
||||
if (base == null) {
|
||||
Log.error("Can not get base : '" + this.colorName + "'");
|
||||
LOGGER.error("Can not get base : '" + this.colorName + "'");
|
||||
return;
|
||||
}
|
||||
// Now we can know if we use linear or radial gradient ...
|
||||
if (base instanceof LinearGradient gradient) {
|
||||
if (base instanceof final LinearGradient gradient) {
|
||||
this.linear = true;
|
||||
Log.verbose("get for color linear:");
|
||||
LOGGER.trace("get for color linear:");
|
||||
gradient.display(2);
|
||||
this.unit = gradient.unit;
|
||||
this.spread = gradient.spread;
|
||||
Log.verbose(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
|
||||
Vector2f size = this.viewPort.second.less(this.viewPort.first);
|
||||
|
||||
Dimension2f dimPos1 = gradient.getPosition1();
|
||||
LOGGER.trace(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
|
||||
final Vector2f size = this.viewPort.second.less(this.viewPort.first);
|
||||
|
||||
final Dimension2f dimPos1 = gradient.getPosition1();
|
||||
this.pos1 = dimPos1.getPixel(size);
|
||||
if (dimPos1.getType() == Distance.POURCENT) {
|
||||
this.pos1 = this.pos1.add(this.viewPort.first);
|
||||
}
|
||||
Dimension2f dimPos2 = gradient.getPosition2();
|
||||
final Dimension2f 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..
|
||||
Vector2f delta = this.pos2.less(this.pos1);
|
||||
final Vector2f delta = this.pos2.less(this.pos1);
|
||||
if (delta.x() < 0.0f) {
|
||||
this.axeX = new Vector2f(-1.0f, 0.0f);
|
||||
} else {
|
||||
@ -147,41 +162,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..
|
||||
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
|
||||
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
|
||||
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);
|
||||
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 RadialGradient gradient)) {
|
||||
Log.error("Can not cast in a linear gradient: '" + this.colorName + "' ==> wrong type");
|
||||
if (!(base instanceof final RadialGradient gradient)) {
|
||||
LOGGER.error("Can not cast in a linear gradient: '" + this.colorName + "' ==> wrong type");
|
||||
return;
|
||||
}
|
||||
Log.verbose("get for color Radial:");
|
||||
LOGGER.trace("get for color Radial:");
|
||||
gradient.display(2);
|
||||
this.unit = gradient.unit;
|
||||
this.spread = gradient.spread;
|
||||
Log.verbose(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
|
||||
Vector2f size = this.viewPort.second.less(this.viewPort.first);
|
||||
|
||||
Dimension2f dimCenter = gradient.getCenter();
|
||||
LOGGER.trace(" viewport = {" + this.viewPort.first + "," + this.viewPort.second + "}");
|
||||
final Vector2f size = this.viewPort.second.less(this.viewPort.first);
|
||||
|
||||
final Dimension2f dimCenter = gradient.getCenter();
|
||||
Vector2f center = dimCenter.getPixel(size);
|
||||
if (dimCenter.getType() == Distance.POURCENT) {
|
||||
center = center.add(this.viewPort.first);
|
||||
}
|
||||
Dimension2f dimFocal = gradient.getFocal();
|
||||
final Dimension2f dimFocal = gradient.getFocal();
|
||||
Vector2f focal = dimFocal.getPixel(size);
|
||||
if (dimFocal.getType() == Distance.POURCENT) {
|
||||
focal = focal.add(this.viewPort.first);
|
||||
}
|
||||
Dimension1f dimRadius = gradient.getRadius();
|
||||
final Dimension1f 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);
|
||||
Vector2f delta = center.less(this.pos2);
|
||||
final Vector2f delta = center.less(this.pos2);
|
||||
if (delta.x() < 0.0f) {
|
||||
this.axeX = new Vector2f(-1.0f, 0.0f);
|
||||
} else {
|
||||
@ -197,8 +212,9 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
this.centerIsFocal = false;
|
||||
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;
|
||||
}
|
||||
@ -209,25 +225,26 @@ 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..
|
||||
Vector2f intersecX = DynamicColorSpecial.getIntersect(this.pos1, this.axeX, this.pos2, this.axeY);
|
||||
Vector2f intersecY = DynamicColorSpecial.getIntersect(this.pos1, this.axeY, this.pos2, this.axeX);
|
||||
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);
|
||||
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()) {
|
||||
Log.debug("Change position of the Focal ... ==> set it inside the circle");
|
||||
LOGGER.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;
|
||||
}
|
||||
}
|
||||
Log.verbose("baseSize=" + this.baseSize + " this.pos1=" + this.pos1 + " dim=" + dimCenter + " this.focal=" + this.focal + " this.pos2=" + this.pos2 + " dim=" + dimRadius);
|
||||
LOGGER.trace("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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Color getColor(final Vector2i pos) {
|
||||
if (this.data.size() < 2) {
|
||||
@ -238,16 +255,17 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
}
|
||||
return getColorRadial(pos);
|
||||
}
|
||||
|
||||
|
||||
private Color getColorLinear(final Vector2i pos) {
|
||||
float ratio = 0.0f;
|
||||
if (this.unit == GradientUnits.GRADIENT_UNITS_USER_SPACE_ON_USE) {
|
||||
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();
|
||||
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();
|
||||
ratio = baseDraw / baseSize;
|
||||
switch (this.spread) {
|
||||
default:
|
||||
@ -267,7 +285,7 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
ratio *= -1.0;
|
||||
}
|
||||
ratio -= ((int) (ratio));
|
||||
|
||||
|
||||
if (ratio < 0.0f) {
|
||||
ratio = 1.0f - FMath.abs(ratio);
|
||||
}
|
||||
@ -275,10 +293,12 @@ 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..
|
||||
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);
|
||||
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);
|
||||
float baseDrawX = vectorBaseDrawX.length();
|
||||
float baseDrawY = vectorBaseDrawY.length();
|
||||
if (this.axeX.dot(vectorBaseDrawX) < 0) {
|
||||
@ -289,7 +309,8 @@ 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 {
|
||||
@ -328,22 +349,29 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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)..
|
||||
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);
|
||||
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);
|
||||
float baseDrawX = vectorBaseDrawX.length();
|
||||
float baseDrawY = vectorBaseDrawY.length();
|
||||
// specal case when focal == center (this is faster ...)
|
||||
@ -376,15 +404,16 @@ public class DynamicColorSpecial implements DynamicColor {
|
||||
if (this.clipOut && baseDrawX <= -1.0f) {
|
||||
ratio = 1.0f;
|
||||
} else {
|
||||
float tmpLength = -this.focalLength / this.baseSize.x();
|
||||
Vector2f focalCenter = new Vector2f(tmpLength, 0.0f);
|
||||
Vector2f currentPoint = new Vector2f(baseDrawX, baseDrawY);
|
||||
final float tmpLength = -this.focalLength / this.baseSize.x();
|
||||
final Vector2f focalCenter = new Vector2f(tmpLength, 0.0f);
|
||||
final Vector2f currentPoint = new Vector2f(baseDrawX, baseDrawY);
|
||||
if (focalCenter == currentPoint) {
|
||||
ratio = 0.0f;
|
||||
} else {
|
||||
Pair<Vector2f, Vector2f> positions = DynamicColorSpecial.intersectLineToCircle(focalCenter, currentPoint);
|
||||
float lenghtBase = currentPoint.less(focalCenter).length();
|
||||
float lenghtBorder1 = positions.first.less(focalCenter).length();
|
||||
final Pair<Vector2f, Vector2f> positions = DynamicColorSpecial.intersectLineToCircle(focalCenter,
|
||||
currentPoint);
|
||||
final float lenghtBase = currentPoint.less(focalCenter).length();
|
||||
final float lenghtBorder1 = positions.first.less(focalCenter).length();
|
||||
//float lenghtBorder2 = positions.second.less(focalCenter).length();
|
||||
ratio = lenghtBase / lenghtBorder1;
|
||||
}
|
||||
@ -418,15 +447,20 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setViewPort(final Pair<Vector2f, Vector2f> viewPort) {
|
||||
this.viewPort = viewPort;
|
||||
|
@ -5,11 +5,12 @@ 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
|
||||
@ -18,29 +19,41 @@ import org.atriasoft.etk.math.Vector2i;
|
||||
*/
|
||||
|
||||
public class PathModel {
|
||||
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) {
|
||||
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) {
|
||||
if (level > recurtionMax) {
|
||||
return;
|
||||
}
|
||||
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 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 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()));
|
||||
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()));
|
||||
|
||||
if ((distance2 + distance3) * (distance2 + distance3) < threshold * delta.length2()) {
|
||||
listPoint.add(new Point(pos4, type));
|
||||
return;
|
||||
}
|
||||
Vector2f pos123 = pos12.add(pos23).multiply(0.5f);
|
||||
Vector2f pos234 = pos23.add(pos34).multiply(0.5f);
|
||||
Vector2f pos1234 = pos123.add(pos234).multiply(0.5f);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,20 +108,24 @@ public class PathModel {
|
||||
}
|
||||
|
||||
public void display(final int spacing) {
|
||||
Log.warning(PathModel.spacingDist(spacing) + "Path");
|
||||
for (Element it : this.listElement) {
|
||||
LOGGER.warn(PathModel.spacingDist(spacing) + "Path");
|
||||
for (final Element it : this.listElement) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
Log.warning(PathModel.spacingDist(spacing + 1) + it);
|
||||
LOGGER.warn(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());
|
||||
SegmentList listSegment = new SegmentList();
|
||||
Weight weight = new Weight();
|
||||
final SegmentList listSegment = new SegmentList();
|
||||
final Weight weight = new Weight();
|
||||
// Check if we need to display background
|
||||
listSegment.createSegmentList(listPoints);
|
||||
listSegment.applyMatrix(basicTrans);
|
||||
@ -117,11 +134,16 @@ 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());
|
||||
SegmentList listSegment = new SegmentList();
|
||||
Weight weight = new Weight();
|
||||
final SegmentList listSegment = new SegmentList();
|
||||
final Weight weight = new Weight();
|
||||
// Check if we need to display background
|
||||
listSegment.createSegmentListStroke(listPoints, strokeWidth, CapMode.BUTT, JoinMode.MITER, 4.0f);
|
||||
listSegment.applyMatrix(basicTrans);
|
||||
@ -130,7 +152,13 @@ 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));
|
||||
}
|
||||
|
||||
@ -143,22 +171,23 @@ public class PathModel {
|
||||
}
|
||||
|
||||
public PointList generateListPoints(final int level, final int recurtionMax, final float threshold) {
|
||||
Log.verbose(PathModel.spacingDist(level) + "Generate List Points ... from a path");
|
||||
PointList out = new PointList();
|
||||
LOGGER.trace(PathModel.spacingDist(level) + "Generate List Points ... from a path");
|
||||
final 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 (Element it : this.listElement) {
|
||||
for (final Element it : this.listElement) {
|
||||
if (it == null) {
|
||||
continue;
|
||||
}
|
||||
Log.verbose(PathModel.spacingDist(level + 1) + " Draw : " + it.toString());
|
||||
LOGGER.trace(PathModel.spacingDist(level + 1) + " Draw : " + it.toString());
|
||||
switch (it.getType()) {
|
||||
case STOP:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
Log.warning(PathModel.spacingDist(level + 1) + " Request path stop of not starting path ...");
|
||||
LOGGER.warn(
|
||||
PathModel.spacingDist(level + 1) + " Request path stop of not starting path ...");
|
||||
} else {
|
||||
tmpListPoint.get(tmpListPoint.size() - 1).setEndPath();
|
||||
out.addList(tmpListPoint);
|
||||
@ -171,14 +200,17 @@ public class PathModel {
|
||||
case CLOSE:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
Log.warning(PathModel.spacingDist(level + 1) + " Request path close of not starting path ...");
|
||||
LOGGER.warn(
|
||||
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...
|
||||
Vector2f delta = (tmpListPoint.get(0).pos.less(tmpListPoint.get(tmpListPoint.size() - 1).pos)).abs();
|
||||
final Vector2f delta = (tmpListPoint.get(0).pos
|
||||
.less(tmpListPoint.get(tmpListPoint.size() - 1).pos)).abs();
|
||||
if (delta.x() <= 0.00001 && delta.y() <= 0.00001) {
|
||||
Log.verbose(" Remove point Z property : " + tmpListPoint.get(tmpListPoint.size() - 1).pos + " with delta=" + delta);
|
||||
LOGGER.trace(" Remove point Z property : "
|
||||
+ tmpListPoint.get(tmpListPoint.size() - 1).pos + " with delta=" + delta);
|
||||
tmpListPoint.remove(tmpListPoint.size() - 1);
|
||||
}
|
||||
out.addList(tmpListPoint);
|
||||
@ -244,14 +276,15 @@ public class PathModel {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
} {
|
||||
Vector2f lastPosStore = lastPosition;
|
||||
final Vector2f lastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
lastPosition = pos;
|
||||
lastAngle = pos2;
|
||||
}
|
||||
@ -261,15 +294,16 @@ public class PathModel {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
} {
|
||||
Vector2f lastPosStore = lastPosition;
|
||||
final Vector2f lastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
Vector2f pos2 = lastPosition.add(it.getPos2());
|
||||
Vector2f pos = lastPosition.add(it.getPos());
|
||||
final Vector2f pos2 = lastPosition.add(it.getPos2());
|
||||
final Vector2f pos = lastPosition.add(it.getPos());
|
||||
// generate Pos 1
|
||||
Vector2f pos1 = lastPosStore.multiply(2.0f).less(lastAngle);
|
||||
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2, pos, 0, PointType.join);
|
||||
final Vector2f pos1 = lastPosStore.multiply(2.0f).less(lastAngle);
|
||||
PathModel.interpolateCubicBezier(tmpListPoint, recurtionMax, threshold, lastPosStore, pos1, pos2,
|
||||
pos, 0, PointType.join);
|
||||
lastPosition = pos;
|
||||
lastAngle = pos2;
|
||||
}
|
||||
@ -279,16 +313,17 @@ public class PathModel {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
} {
|
||||
Vector2f lastPosStore = lastPosition;
|
||||
final Vector2f lastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
Vector2f pos = lastPosition.add(it.getPos());
|
||||
Vector2f tmp1 = lastPosition.add(it.getPos1());
|
||||
final Vector2f pos = lastPosition.add(it.getPos());
|
||||
final Vector2f tmp1 = lastPosition.add(it.getPos1());
|
||||
// generate pos1 and pos2
|
||||
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);
|
||||
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);
|
||||
lastPosition = pos;
|
||||
lastAngle = tmp1;
|
||||
}
|
||||
@ -298,16 +333,17 @@ public class PathModel {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
} {
|
||||
Vector2f lastPosStore = lastPosition;
|
||||
final Vector2f lastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
Vector2f pos = lastPosition.add(it.getPos());
|
||||
Vector2f tmp1 = lastPosStore.multiply(2.0f).less(lastAngle);
|
||||
final Vector2f pos = lastPosition.add(it.getPos());
|
||||
final Vector2f tmp1 = lastPosStore.multiply(2.0f).less(lastAngle);
|
||||
// generate pos1 and pos2
|
||||
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);
|
||||
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);
|
||||
lastPosition = pos;
|
||||
lastAngle = tmp1;
|
||||
}
|
||||
@ -317,25 +353,28 @@ public class PathModel {
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
} {
|
||||
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 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);
|
||||
|
||||
Vector2f lastPosStore = lastPosition;
|
||||
final Vector2f lastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
Vector2f pos = lastPosition.add(it.getPos());
|
||||
float rotationX = tmpIt.angle * ((float) Math.PI / 180.0f);
|
||||
final Vector2f pos = lastPosition.add(it.getPos());
|
||||
final 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) {
|
||||
Log.warning("Degenerate arc in Line");
|
||||
LOGGER.warn("Degenerate arc in Line");
|
||||
if (tmpListPoint.size() == 0) {
|
||||
tmpListPoint.add(new Point(lastPosition, PointType.join));
|
||||
}
|
||||
@ -345,18 +384,21 @@ 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'
|
||||
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());
|
||||
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());
|
||||
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();
|
||||
float ssb = 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();
|
||||
if (ssa < 0.0f) {
|
||||
ssa = 0.0f;
|
||||
}
|
||||
@ -366,19 +408,21 @@ public class PathModel {
|
||||
if (tmpIt.largeArcFlag == tmpIt.sweepFlag) {
|
||||
sss *= -1.0f;
|
||||
}
|
||||
Vector2f centerPrime = new Vector2f(sss * radius.x() * deltaPrim.y() / radius.y(), sss * -radius.y() * deltaPrim.x() / radius.x());
|
||||
final Vector2f centerPrime = new Vector2f(sss * radius.x() * deltaPrim.y() / radius.y(),
|
||||
sss * -radius.y() * deltaPrim.x() / radius.x());
|
||||
// Compute center from center'
|
||||
Matrix2x3f matrix = Matrix2x3f.createRotate(rotationX);
|
||||
Vector2f center = lastPosStore.multiply(pos).multiply(0.5f).add(matrix.multiply(centerPrime));
|
||||
final Matrix2x3f matrix = Matrix2x3f.createRotate(rotationX);
|
||||
final 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.
|
||||
Vector2f vectorA = deltaPrim.less(centerPrime).devide(radius);
|
||||
Vector2f vectorB = deltaPrim.add(centerPrime).devide(radius.multiply(-1.0f));
|
||||
final Vector2f vectorA = deltaPrim.less(centerPrime).devide(radius);
|
||||
final 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
|
||||
float theta1 = PathModel.vectorAngle(new Vector2f(1.0f, 0.0f), vectorA);
|
||||
final float theta1 = PathModel.vectorAngle(new Vector2f(1.0f, 0.0f), vectorA);
|
||||
// Delta angle
|
||||
float deltaTheta = PathModel.vectorAngle(vectorA, vectorB);
|
||||
// special case of invert angle...
|
||||
@ -397,9 +441,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.
|
||||
int ndivs = (int) (Math.abs(deltaTheta) / ((float) Math.PI * 0.5f)) + 1;
|
||||
final int ndivs = (int) (Math.abs(deltaTheta) / ((float) Math.PI * 0.5f)) + 1;
|
||||
|
||||
float hda = (deltaTheta / ndivs) * 0.5f;
|
||||
final 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;
|
||||
@ -407,21 +451,24 @@ public class PathModel {
|
||||
Vector2f pointPosPrevious = Vector2f.ZERO;
|
||||
Vector2f tangentPrevious = Vector2f.ZERO;
|
||||
for (int iii = 0; iii <= ndivs; ++iii) {
|
||||
float a = theta1 + deltaTheta * ((float) iii / (float) ndivs);
|
||||
final float a = theta1 + deltaTheta * ((float) iii / (float) ndivs);
|
||||
delta = new Vector2f(FMath.cos(a), FMath.sin(a));
|
||||
// position
|
||||
Vector2f pointPos = matrix.multiply(new Vector2f(delta.x() * radius.x(), delta.y() * radius.y()));
|
||||
final Vector2f pointPos = matrix
|
||||
.multiply(new Vector2f(delta.x() * radius.x(), delta.y() * radius.y()));
|
||||
// tangent
|
||||
Vector2f tangent = matrix.applyScaleRotation(new Vector2f(-delta.y() * radius.x() * kappa, delta.x() * radius.y() * kappa));
|
||||
final Vector2f tangent = matrix.applyScaleRotation(
|
||||
new Vector2f(-delta.y() * radius.x() * kappa, delta.x() * radius.y() * kappa));
|
||||
if (iii > 0) {
|
||||
Vector2f zlastPosStore = lastPosition;
|
||||
final Vector2f zlastPosStore = lastPosition;
|
||||
if (!it.getRelative()) {
|
||||
lastPosition = Vector2f.ZERO;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
lastPosition = zpos;
|
||||
lastAngle = zpos2;
|
||||
}
|
||||
@ -433,13 +480,13 @@ public class PathModel {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.error(PathModel.spacingDist(level + 1) + " Unknow PATH commant (internal error)");
|
||||
LOGGER.error(PathModel.spacingDist(level + 1) + " Unknow PATH commant (internal error)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// special case : No request end of path ==> open path:
|
||||
if (tmpListPoint.size() != 0) {
|
||||
Log.verbose("Auto-end PATH");
|
||||
LOGGER.trace("Auto-end PATH");
|
||||
tmpListPoint.get(tmpListPoint.size() - 1).setEndPath();
|
||||
out.addList(tmpListPoint);
|
||||
tmpListPoint = new ArrayList<>();
|
||||
|
@ -1,7 +1,8 @@
|
||||
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
|
||||
@ -10,6 +11,7 @@ import org.atriasoft.etk.math.Vector2f;
|
||||
*/
|
||||
|
||||
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;
|
||||
@ -20,35 +22,35 @@ public class Point {
|
||||
public Vector2f posNext = Vector2f.ZERO;
|
||||
public Vector2f posPrevious = Vector2f.ZERO;
|
||||
public PointType type;
|
||||
|
||||
|
||||
public Point() {
|
||||
this.pos = Vector2f.ZERO;
|
||||
this.type = PointType.join;
|
||||
}
|
||||
|
||||
|
||||
public Point(final Vector2f pos) {
|
||||
this.pos = pos;
|
||||
this.type = PointType.join;
|
||||
}
|
||||
|
||||
|
||||
public Point(final Vector2f pos, final PointType type) {
|
||||
this.pos = pos;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
void normalize(final Vector2f nextPoint) {
|
||||
this.delta = nextPoint.less(this.pos);
|
||||
this.len = this.delta.length();
|
||||
}
|
||||
|
||||
|
||||
void setEndPath() {
|
||||
if (this.type == PointType.interpolation) {
|
||||
Log.warning("Request stop path of an interpolate Point");
|
||||
LOGGER.warn("Request stop path of an interpolate Point");
|
||||
this.type = PointType.stop;
|
||||
return;
|
||||
}
|
||||
if (this.type == PointType.stop) {
|
||||
Log.warning("Request stop path of an STOP Point");
|
||||
LOGGER.warn("Request stop path of an STOP Point");
|
||||
return;
|
||||
}
|
||||
if (this.type == PointType.start) {
|
||||
|
@ -3,46 +3,48 @@ package org.atriasoft.esvg.render;
|
||||
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.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() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void addList(final List<Point> list) {
|
||||
this.data.add(list);
|
||||
// TODO : Add a checker of correct list ...
|
||||
}
|
||||
|
||||
|
||||
public void applyMatrix(final Matrix2x3f transformationMatrix) {
|
||||
for (List<Point> it : this.data) {
|
||||
for (Point val : it) {
|
||||
for (final List<Point> it : this.data) {
|
||||
for (final Point val : it) {
|
||||
val.pos = transformationMatrix.multiply(val.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void display() {
|
||||
Log.verbose(" Display list of points : size=" + this.data.size());
|
||||
for (List<Point> it : this.data) {
|
||||
Log.verbose(" Find List " + it.size() + " members");
|
||||
LOGGER.trace(" Display list of points : size=" + this.data.size());
|
||||
for (final List<Point> it : this.data) {
|
||||
LOGGER.trace(" Find List " + it.size() + " members");
|
||||
for (int iii = 0; iii < it.size(); ++iii) {
|
||||
Point elem = it.get(iii);
|
||||
Log.verbose(" [" + iii + "] Find " + elem.type + " " + elem.pos);
|
||||
final Point elem = it.get(iii);
|
||||
LOGGER.trace(" [" + iii + "] Find " + elem.type + " " + elem.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Pair<Vector2f, Vector2f> getViewPort() {
|
||||
Pair<Vector2f, Vector2f> out = new Pair<>(Vector2f.MAX_VALUE, Vector2f.MIN_VALUE);
|
||||
for (List<Point> it : this.data) {
|
||||
for (Point it2 : it) {
|
||||
for (final List<Point> it : this.data) {
|
||||
for (final Point it2 : it) {
|
||||
out = new Pair<>(Vector2f.min(out.first, it2.pos), Vector2f.max(out.second, it2.pos));
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,15 @@ 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.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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
@ -20,13 +21,20 @@ import org.atriasoft.esvg.internal.Log;
|
||||
*/
|
||||
|
||||
public class SegmentList {
|
||||
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();
|
||||
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();
|
||||
if (diviseur != 0.0f) {
|
||||
float mmm = (vect1.x() * point1.y() - vect1.x() * point2.y() - vect1.y() * point1.x() + vect1.y() * point2.x()) / diviseur;
|
||||
final 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));
|
||||
}
|
||||
Log.error("Get divider / 0.0f");
|
||||
LOGGER.error("Get divider / 0.0f");
|
||||
return point2;
|
||||
}
|
||||
|
||||
@ -55,16 +63,16 @@ public class SegmentList {
|
||||
}
|
||||
|
||||
public void applyMatrix(final Matrix2x3f transformationMatrix) {
|
||||
for (Segment it : this.data) {
|
||||
for (final Segment it : this.data) {
|
||||
it.applyMatrix(transformationMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearHorizontals() {
|
||||
// TODO Auto-generated method stub
|
||||
Iterator<Segment> itr = this.data.iterator();
|
||||
final Iterator<Segment> itr = this.data.iterator();
|
||||
while (itr.hasNext()) {
|
||||
Segment seg = itr.next();
|
||||
final Segment seg = itr.next();
|
||||
if (seg.p0.y() == seg.p1.y()) {
|
||||
itr.remove();
|
||||
}
|
||||
@ -72,7 +80,7 @@ public class SegmentList {
|
||||
}
|
||||
|
||||
public void createSegmentList(final PointList listPoint) {
|
||||
for (List<Point> it : listPoint.data) {
|
||||
for (final 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));
|
||||
@ -80,45 +88,52 @@ public class SegmentList {
|
||||
}
|
||||
}
|
||||
|
||||
public void createSegmentListStroke(final PointList listPoint, final float width, final CapMode cap, final JoinMode join, final float miterLimit) {
|
||||
for (List<Point> itListPoint : listPoint.data) {
|
||||
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) {
|
||||
// generate for every point all the orthogonal elements
|
||||
//
|
||||
// normal edge * end path
|
||||
// (mitter) * | * * * * * * * * * * * * * *
|
||||
// * |<--*----this | *
|
||||
// * | * this -->| *
|
||||
// * * * | *
|
||||
// * . | . * . . . . . . . . * *
|
||||
// * . | . * | *
|
||||
// * A . | . B * | *
|
||||
// . * . | *
|
||||
// . * * . * * * * * * * * * * * * *
|
||||
// * *
|
||||
// * *
|
||||
for (int idPevious = itListPoint.size() - 1, idCurrent = 0, idNext = 1; idCurrent < itListPoint.size(); idPevious = idCurrent++, idNext++) {
|
||||
//
|
||||
// normal edge * end path
|
||||
// (mitter) * | * * * * * * * * * * * * * *
|
||||
// * |<--*----this | *
|
||||
// * | * this -->| *
|
||||
// * * * | *
|
||||
// * . | . * . . . . . . . . * *
|
||||
// * . | . * | *
|
||||
// * A . | . B * | *
|
||||
// . * . | *
|
||||
// . * * . * * * * * * * * * * * * *
|
||||
// * *
|
||||
// * *
|
||||
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) {
|
||||
Log.error("an error occure a previous ID is < 0.... ");
|
||||
LOGGER.error("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
if (idNext >= itListPoint.size()) {
|
||||
Log.error("an error occure a next ID is >= nbPoint len .... ");
|
||||
LOGGER.error("an error occure a next ID is >= nbPoint len .... ");
|
||||
continue;
|
||||
}
|
||||
//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);
|
||||
//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);
|
||||
Vector2f vecA = itListPoint.get(idCurrent).pos.less(itListPoint.get(idPevious).pos);
|
||||
//Log.debug("JOIN : vecA : " + vecA);
|
||||
//LOGGER.debug("JOIN : vecA : " + vecA);
|
||||
vecA = vecA.safeNormalize();
|
||||
Vector2f vecB = itListPoint.get(idNext).pos.less(itListPoint.get(idCurrent).pos);
|
||||
//Log.debug("JOIN : vecB : " + vecB);
|
||||
//LOGGER.debug("JOIN : vecB : " + vecB);
|
||||
vecB = vecB.safeNormalize();
|
||||
Vector2f vecC = vecA.less(vecB);
|
||||
//Log.debug("JOIN : vecC : " + vecC);
|
||||
//LOGGER.debug("JOIN : vecC : " + vecC);
|
||||
if (vecC.isZero()) {
|
||||
// special case: 1 line ...
|
||||
itListPoint.get(idCurrent).miterAxe = new Vector2f(vecA.y(), vecA.x());
|
||||
@ -134,7 +149,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());
|
||||
//Log.debug("JOIN : miterAxe " + itListPoint.get(idCurrent).miterAxe);
|
||||
//LOGGER.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);
|
||||
@ -144,7 +159,7 @@ public class SegmentList {
|
||||
itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe;
|
||||
} else if (itListPoint.get(idCurrent).type == PointType.stop) {
|
||||
if (idPevious < 0) {
|
||||
Log.error("an error occure a previous ID is < 0.... ");
|
||||
LOGGER.error("an error occure a previous ID is < 0.... ");
|
||||
continue;
|
||||
}
|
||||
itListPoint.get(idCurrent).posPrevious = itListPoint.get(idPevious).pos;
|
||||
@ -154,25 +169,27 @@ public class SegmentList {
|
||||
itListPoint.get(idCurrent).orthoAxePrevious = itListPoint.get(idCurrent).miterAxe;
|
||||
itListPoint.get(idCurrent).orthoAxeNext = itListPoint.get(idCurrent).miterAxe;
|
||||
} else {
|
||||
Log.todo("Unsupported type of point ....");
|
||||
LOGGER.info("TODO: Unsupported type of point ....");
|
||||
}
|
||||
}
|
||||
// create segment list:
|
||||
boolean haveStartLine = false;
|
||||
|
||||
Dynamic<Vector2f> leftPoint = new Dynamic<Vector2f>(Vector2f.ZERO);
|
||||
final Dynamic<Vector2f> leftPoint = new Dynamic<>(Vector2f.ZERO);
|
||||
|
||||
Dynamic<Vector2f> rightPoint = new Dynamic<Vector2f>(Vector2f.ZERO);
|
||||
final Dynamic<Vector2f> rightPoint = new Dynamic<>(Vector2f.ZERO);
|
||||
if (itListPoint.size() > 0) {
|
||||
if (itListPoint.get(0).type == PointType.join) {
|
||||
Point it = itListPoint.get(itListPoint.size() - 1);
|
||||
final 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));
|
||||
@ -180,12 +197,14 @@ public class SegmentList {
|
||||
// project on the miter Axis ...
|
||||
switch (join) {
|
||||
case MITER: {
|
||||
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);
|
||||
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);
|
||||
// Check the miter limit:
|
||||
float limitRight = (left.less(it.pos)).length() / width * 2.0f;
|
||||
float limitLeft = (right.less(it.pos)).length() / width * 2.0f;
|
||||
Log.verbose(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit);
|
||||
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);
|
||||
if (limitRight <= miterLimit && limitLeft <= miterLimit) {
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
@ -194,14 +213,16 @@ public class SegmentList {
|
||||
}
|
||||
case ROUND:
|
||||
case BEVEL: {
|
||||
Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
|
||||
Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
|
||||
float cross = axePrevious.cross(axeNext);
|
||||
final Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
|
||||
final Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
|
||||
final 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;
|
||||
@ -210,106 +231,112 @@ public class SegmentList {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Log.error("Start list point with a join, but last lement is not a join");
|
||||
LOGGER.error("Start list point with a join, but last lement is not a join");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Point it : itListPoint) {
|
||||
for (final Point it : itListPoint) {
|
||||
switch (it.type) {
|
||||
case single:
|
||||
// just do nothing ....
|
||||
Log.verbose("Find Single " + it.pos);
|
||||
LOGGER.trace("Find Single " + it.pos);
|
||||
break;
|
||||
case start:
|
||||
Log.verbose("Find Start " + it.pos);
|
||||
LOGGER.trace("Find Start " + it.pos);
|
||||
if (haveStartLine) {
|
||||
// close previous :
|
||||
Log.warning(" find a non close path ...");
|
||||
LOGGER.warn(" find a non close path ...");
|
||||
addSegment(leftPoint.value, rightPoint.value);
|
||||
}
|
||||
haveStartLine = true;
|
||||
startStopPoint(leftPoint, rightPoint, it, cap, width, true);
|
||||
break;
|
||||
case stop:
|
||||
Log.verbose("Find Stop " + it.pos);
|
||||
LOGGER.trace("Find Stop " + it.pos);
|
||||
if (!haveStartLine) {
|
||||
Log.warning("find close path without start part ...");
|
||||
LOGGER.warn("find close path without start part ...");
|
||||
break;
|
||||
}
|
||||
haveStartLine = false;
|
||||
startStopPoint(leftPoint, rightPoint, it, cap, width, false);
|
||||
break;
|
||||
case interpolation: {
|
||||
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);
|
||||
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);
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
}
|
||||
break;
|
||||
case join:
|
||||
Log.verbose("Find join " + it.pos);
|
||||
LOGGER.trace("Find join " + it.pos);
|
||||
switch (join) {
|
||||
case MITER: {
|
||||
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);
|
||||
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);
|
||||
// Check the miter limit:
|
||||
float limitRight = left.less(it.pos).length() / width * 2.0f;
|
||||
float limitLeft = right.less(it.pos).length() / width * 2.0f;
|
||||
Log.verbose(" miter Limit: " + limitRight + " " + limitLeft + " <= " + miterLimit);
|
||||
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);
|
||||
if (limitRight <= miterLimit && limitLeft <= miterLimit) {
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
break;
|
||||
}
|
||||
Log.verbose(" Find miter Limit ... ==> create BEVEL");
|
||||
LOGGER.trace(" Find miter Limit ... ==> create BEVEL");
|
||||
}
|
||||
case ROUND:
|
||||
case BEVEL: {
|
||||
Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
|
||||
Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
|
||||
float cross = axePrevious.cross(axeNext);
|
||||
final Vector2f axePrevious = (it.pos.less(it.posPrevious)).safeNormalize();
|
||||
final Vector2f axeNext = (it.posNext.less(it.pos)).safeNormalize();
|
||||
final float cross = axePrevious.cross(axeNext);
|
||||
if (cross > 0.0f) {
|
||||
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));
|
||||
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));
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left1);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left1);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left1);
|
||||
if (join != JoinMode.ROUND) {
|
||||
// Miter and bevel:
|
||||
addSegment(left1, left2);
|
||||
Log.verbose(" segment :" + left1 + " . " + left2);
|
||||
LOGGER.trace(" segment :" + left1 + " . " + left2);
|
||||
} else {
|
||||
createSegmentListStroke(left1, left2, it.pos, width, false);
|
||||
}
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
leftPoint.value = left2;
|
||||
rightPoint.value = right;
|
||||
} else {
|
||||
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));
|
||||
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));
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right1, rightPoint.value);
|
||||
Log.verbose(" segment :" + right1 + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right1 + " . " + rightPoint);
|
||||
if (join != JoinMode.ROUND) {
|
||||
// Miter and bevel:
|
||||
addSegment(right2, right1);
|
||||
Log.verbose(" segment :" + right2 + " . " + right1);
|
||||
LOGGER.trace(" segment :" + right2 + " . " + right1);
|
||||
} else {
|
||||
createSegmentListStroke(right1, right2, it.pos, width, true);
|
||||
}
|
||||
@ -330,15 +357,21 @@ 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;
|
||||
}
|
||||
float angleToDraw = FMath.acos((point1.less(center)).safeNormalize().dot((point2.less(center)).safeNormalize()));
|
||||
float baseAngle = angleToDraw / nbDot;
|
||||
final float angleToDraw = FMath
|
||||
.acos((point1.less(center)).safeNormalize().dot((point2.less(center)).safeNormalize()));
|
||||
final float baseAngle = angleToDraw / nbDot;
|
||||
float iii;
|
||||
Vector2f axe = (point1.less(center)).safeNormalize();
|
||||
final Vector2f axe = (point1.less(center)).safeNormalize();
|
||||
|
||||
Vector2f ppp1 = point1;
|
||||
|
||||
@ -350,68 +383,74 @@ public class SegmentList {
|
||||
} else {
|
||||
tmpMat = Matrix2x3f.createRotate(iii);
|
||||
}
|
||||
Vector2f axeRotate = tmpMat.multiply(axe);
|
||||
final Vector2f axeRotate = tmpMat.multiply(axe);
|
||||
ppp2 = center.add(axeRotate.multiply(width * 0.5f));
|
||||
if (isStart) {
|
||||
addSegment(ppp2, ppp1);
|
||||
Log.verbose(" segment :" + ppp2 + " . " + ppp1);
|
||||
LOGGER.trace(" segment :" + ppp2 + " . " + ppp1);
|
||||
} else {
|
||||
addSegment(ppp1, ppp2);
|
||||
Log.verbose(" segment :" + ppp1 + " . " + ppp2);
|
||||
LOGGER.trace(" segment :" + ppp1 + " . " + ppp2);
|
||||
}
|
||||
ppp1 = ppp2;
|
||||
}
|
||||
if (isStart) {
|
||||
addSegment(point2, ppp1);
|
||||
Log.verbose(" segment :" + point2 + " . " + ppp1);
|
||||
LOGGER.trace(" segment :" + point2 + " . " + ppp1);
|
||||
} else {
|
||||
addSegment(ppp1, point2);
|
||||
Log.verbose(" segment :" + ppp1 + " . " + point2);
|
||||
LOGGER.trace(" segment :" + ppp1 + " . " + point2);
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<Vector2f, Vector2f> getViewPort() {
|
||||
|
||||
Pair<Vector2f, Vector2f> out = new Pair<>(Vector2f.MAX_VALUE, Vector2f.MIN_VALUE);
|
||||
for (Segment it : this.data) {
|
||||
for (final 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: {
|
||||
Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
|
||||
Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
|
||||
final Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
|
||||
final Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
|
||||
if (!isStart) {
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
}
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
}
|
||||
if (!isStart) {
|
||||
addSegment(leftPoint.value, rightPoint.value);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
|
||||
} else {
|
||||
addSegment(rightPoint.value, leftPoint.value);
|
||||
Log.verbose(" segment :" + rightPoint + " . " + leftPoint);
|
||||
LOGGER.trace(" segment :" + rightPoint + " . " + leftPoint);
|
||||
}
|
||||
break;
|
||||
case ROUND: {
|
||||
if (!isStart) {
|
||||
Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
|
||||
Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
|
||||
final Vector2f left = point.pos.add(point.miterAxe.multiply(width * 0.5f));
|
||||
final Vector2f right = point.pos.less(point.miterAxe.multiply(width * 0.5f));
|
||||
if (!isStart) {
|
||||
//Draw from previous point:
|
||||
addSegment(leftPoint.value, left);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
}
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
@ -434,30 +473,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));
|
||||
Matrix2x3f tmpMat = Matrix2x3f.createTranslate(nextAxe.safeNormalize().multiply(width * -0.5f));
|
||||
final 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);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + left);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + left);
|
||||
addSegment(right, rightPoint.value);
|
||||
Log.verbose(" segment :" + right + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + right + " . " + rightPoint);
|
||||
}
|
||||
leftPoint.value = left;
|
||||
rightPoint.value = right;
|
||||
if (!isStart) {
|
||||
addSegment(leftPoint.value, rightPoint.value);
|
||||
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
|
||||
} else {
|
||||
addSegment(rightPoint.value, leftPoint.value);
|
||||
Log.verbose(" segment :" + rightPoint + " . " + leftPoint);
|
||||
LOGGER.trace(" segment :" + rightPoint + " . " + leftPoint);
|
||||
}
|
||||
Log.verbose(" segment :" + leftPoint + " . " + rightPoint);
|
||||
LOGGER.trace(" segment :" + leftPoint + " . " + rightPoint);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.error(" Undefined CAP TYPE");
|
||||
LOGGER.error(" Undefined CAP TYPE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4,27 +4,29 @@ 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;
|
||||
|
||||
|
||||
// constructor :
|
||||
public Weight() {
|
||||
this.size = Vector2i.ZERO;
|
||||
}
|
||||
|
||||
|
||||
public Weight(final Vector2i size) {
|
||||
this.size = size;
|
||||
resize(size);
|
||||
}
|
||||
|
||||
|
||||
public void append(final int posY, final Scanline data) {
|
||||
if (posY >= 0 && posY < this.size.y()) {
|
||||
for (int xxx = 0; xxx < this.size.x(); ++xxx) {
|
||||
@ -32,28 +34,29 @@ public class Weight {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear(final float fill) {
|
||||
ArraysTools.fill2(this.data, fill);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void generate(final Vector2i size, final int subSamplingCount, final SegmentList listSegment) {
|
||||
resize(size);
|
||||
// for each lines:
|
||||
for (int yyy = 0; yyy < size.y(); ++yyy) {
|
||||
Log.verbose("Weighting ... " + yyy + " / " + size.y());
|
||||
LOGGER.trace("Weighting ... " + yyy + " / " + size.y());
|
||||
// Reduce the number of lines in the subsampling parsing:
|
||||
List<Segment> availlableSegmentPixel = new ArrayList<Segment>();
|
||||
for (Segment it : listSegment.data) {
|
||||
final List<Segment> availlableSegmentPixel = new ArrayList<>();
|
||||
for (final Segment it : listSegment.data) {
|
||||
if (it.p0.y() < yyy + 1 && it.p1.y() > (yyy)) {
|
||||
availlableSegmentPixel.add(it);
|
||||
}
|
||||
@ -61,20 +64,21 @@ public class Weight {
|
||||
if (availlableSegmentPixel.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
Log.verbose(" Find Basic segments " + availlableSegmentPixel.size());
|
||||
LOGGER.trace(" Find Basic segments " + availlableSegmentPixel.size());
|
||||
// This represent the pondaration on the subSampling
|
||||
float deltaSize = 1.0f / subSamplingCount;
|
||||
final float deltaSize = 1.0f / subSamplingCount;
|
||||
for (int kkk = 0; kkk < subSamplingCount; ++kkk) {
|
||||
Log.verbose(" Scanline ... " + kkk + " / " + subSamplingCount);
|
||||
Scanline scanline = new Scanline(size.x());
|
||||
LOGGER.trace(" Scanline ... " + kkk + " / " + subSamplingCount);
|
||||
final Scanline scanline = new Scanline(size.x());
|
||||
//find all the segment that cross the middle of the line of the center of the pixel line:
|
||||
float subSamplingCenterPos = yyy + deltaSize * 0.5f + deltaSize * kkk;
|
||||
List<Segment> availlableSegment = new ArrayList<>();
|
||||
final float subSamplingCenterPos = yyy + deltaSize * 0.5f + deltaSize * kkk;
|
||||
final List<Segment> availlableSegment = new ArrayList<>();
|
||||
// find in the subList ...
|
||||
for (Segment it : availlableSegmentPixel) {
|
||||
for (final 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 {
|
||||
@ -82,27 +86,27 @@ public class Weight {
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.verbose(" Availlable Segment " + availlableSegment.size());
|
||||
LOGGER.trace(" Availlable Segment " + availlableSegment.size());
|
||||
if (availlableSegment.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
for (Segment it : availlableSegment) {
|
||||
Log.verbose(" Availlable Segment " + it.p0 + " . " + it.p1 + " dir=" + it.direction);
|
||||
for (final Segment it : availlableSegment) {
|
||||
LOGGER.trace(" Availlable Segment " + it.p0 + " . " + it.p1 + " dir=" + it.direction);
|
||||
}
|
||||
// x position, angle
|
||||
List<Pair<Float, Integer>> listPosition = new ArrayList<>();
|
||||
for (Segment it : availlableSegment) {
|
||||
Vector2f delta = it.p0.less(it.p1);
|
||||
final List<Pair<Float, Integer>> listPosition = new ArrayList<>();
|
||||
for (final Segment it : availlableSegment) {
|
||||
final Vector2f delta = it.p0.less(it.p1);
|
||||
// x = coefficent*y+bbb;
|
||||
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));
|
||||
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));
|
||||
}
|
||||
Log.verbose(" List position " + listPosition.size());
|
||||
LOGGER.trace(" List position " + listPosition.size());
|
||||
// now we order position of the xPosition:
|
||||
Collections.sort(listPosition, (e1, e2) -> ((int) (e1.first - e2.first)));
|
||||
|
||||
|
||||
// move through all element in the point:
|
||||
int lastState = 0;
|
||||
float currentValue = 0.0f;
|
||||
@ -111,30 +115,30 @@ public class Weight {
|
||||
// * current pos
|
||||
// * pos ...
|
||||
// TODO Code the Odd/even and non-zero ...
|
||||
for (Pair<Float, Integer> it : listPosition) {
|
||||
for (final Pair<Float, Integer> it : listPosition) {
|
||||
if (currentPos != it.first.intValue()) {
|
||||
// fill to the new pos -1:
|
||||
float endValue = FMath.min(1.0f, FMath.abs(lastState)) * deltaSize;
|
||||
final 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;
|
||||
}
|
||||
int oldState = lastState;
|
||||
final int oldState = lastState;
|
||||
lastState += it.second;
|
||||
if (oldState == 0) {
|
||||
// nothing to draw before ...
|
||||
float ratio = 1.0f - (it.first - it.first.intValue());
|
||||
final float ratio = 1.0f - (it.first - it.first.intValue());
|
||||
currentValue += ratio * deltaSize;
|
||||
} else if (lastState == 0) {
|
||||
// something new to draw ...
|
||||
float ratio = 1.0f - (it.first - it.first.intValue());
|
||||
final float ratio = 1.0f - (it.first - it.first.intValue());
|
||||
currentValue -= ratio * deltaSize;
|
||||
} else {
|
||||
// nothing to do ...
|
||||
}
|
||||
|
||||
|
||||
if (currentPos == it.first.intValue()) {
|
||||
scanline.set(currentPos, currentValue);
|
||||
}
|
||||
@ -142,7 +146,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 ...
|
||||
Log.error("end of Path whith no end ... " + currentPos + " . " + size.x());
|
||||
LOGGER.error("end of Path whith no end ... " + currentPos + " . " + size.x());
|
||||
for (int xxx = currentPos; xxx < size.x(); ++xxx) {
|
||||
scanline.set(xxx, 100.0f);
|
||||
}
|
||||
@ -151,50 +155,50 @@ public class Weight {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public float get(final int xxx, final int yyy) {
|
||||
if (this.data == null) {
|
||||
return 0;
|
||||
}
|
||||
return this.data[yyy][xxx];
|
||||
}
|
||||
|
||||
|
||||
public float get(final Vector2i pos) {
|
||||
if (this.data == null) {
|
||||
return 0;
|
||||
}
|
||||
return this.data[pos.y()][pos.x()];
|
||||
}
|
||||
|
||||
|
||||
public int getHeight() {
|
||||
return this.size.y();
|
||||
}
|
||||
|
||||
|
||||
public Vector2i getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
|
||||
public int getWidth() {
|
||||
return this.size.x();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------
|
||||
// -- basic tools :
|
||||
// -----------------------------------------------
|
||||
public void resize(final Vector2i size) {
|
||||
this.size = size;
|
||||
if (this.size.x() <= 0) {
|
||||
Log.error("Error in the Weight size : " + this.size);
|
||||
LOGGER.error("Error in the Weight size : " + this.size);
|
||||
this.size = this.size.withX(1);
|
||||
}
|
||||
if (this.size.y() <= 0) {
|
||||
Log.error("Error in the Weight size : " + this.size);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
public void set(final int posY, final Scanline data) {
|
||||
if (posY >= 0 && posY < this.size.y()) {
|
||||
for (int xxx = 0; xxx < this.size.x(); ++xxx) {
|
||||
@ -202,9 +206,9 @@ public class Weight {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void set(final Vector2i pos, final float newColor) {
|
||||
this.data[pos.y()][pos.x()] = newColor;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
package test.atriasoft.esvg;
|
||||
|
||||
import org.atriasoft.egami.ImageFloatRGBA;
|
||||
import org.atriasoft.egami.Image;
|
||||
import org.atriasoft.egami.ImageFloatRGBA;
|
||||
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) {
|
||||
Image data = doc.renderImageFloatRGBA(null, ConfigTest.VISUAL_DEBUG);
|
||||
final Image data = doc.renderImageFloatRGBA(null, ConfigTest.VISUAL_DEBUG);
|
||||
if (data == null) {
|
||||
Log.critical("No data generated ...");
|
||||
LOGGER.error("No data generated ...");
|
||||
}
|
||||
Log.warning("Save file in " + uri.getPath());
|
||||
byte[] outElem = new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toBytes();
|
||||
Log.warning("outsize = " + outElem.length);
|
||||
LOGGER.warn("Save file in " + uri.getPath());
|
||||
final byte[] outElem = new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toBytes();
|
||||
LOGGER.warn("outsize = " + outElem.length);
|
||||
new PngEncoder().withBufferedImage(data).withCompressionLevel(9).toFile(uri.getPath());
|
||||
}
|
||||
|
||||
|
||||
public static void generateAnImage(final Weight weight, final Uri uri) {
|
||||
ImageFloatRGBA image = new ImageFloatRGBA(weight.getWidth() + 2, weight.getHeight() + 2);
|
||||
final 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++) {
|
||||
float elem = weight.get(new Vector2i(xxx, yyy));
|
||||
final float elem = weight.get(new Vector2i(xxx, yyy));
|
||||
image.setColorFloat(xxx, yyy, 1.0f, 1.0f, 1.0f, elem);
|
||||
}
|
||||
}
|
||||
@ -42,11 +43,11 @@ public class ConfigTest {
|
||||
image.setColor(xxx, 0, Color.ORANGE);
|
||||
image.setColor(xxx, weight.getHeight() + 1, Color.ORANGE);
|
||||
}
|
||||
Log.warning("Save file in " + uri.getPath());
|
||||
byte[] outElem = new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toBytes();
|
||||
Log.warning("outsize = " + outElem.length);
|
||||
LOGGER.warn("Save file in " + uri.getPath());
|
||||
final byte[] outElem = new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toBytes();
|
||||
LOGGER.warn("outsize = " + outElem.length);
|
||||
new PngEncoder().withBufferedImage(image).withCompressionLevel(9).toFile(uri.getPath());
|
||||
}
|
||||
|
||||
|
||||
private ConfigTest() {}
|
||||
}
|
||||
|
@ -2,140 +2,187 @@ 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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.svg"), data.replace("'", "\"")));
|
||||
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCapsquareVert.png"));
|
||||
}
|
||||
}
|
||||
|
@ -2,37 +2,50 @@ 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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
Assertions.assertDoesNotThrow(
|
||||
() -> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.svg"), data.replace("'", "\"")));
|
||||
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestCirclestroke.png"));
|
||||
}
|
||||
}
|
@ -2,7 +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;
|
||||
|
||||
@ -10,251 +9,405 @@ 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";
|
||||
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
|
||||
EsvgDocument doc = new EsvgDocument();
|
||||
final EsvgDocument doc = new EsvgDocument();
|
||||
doc.parse(data);
|
||||
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1.svg"), data.replace("'", "\"")));
|
||||
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
|
||||
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";
|
||||
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
|
||||
EsvgDocument doc = new EsvgDocument();
|
||||
final EsvgDocument doc = new EsvgDocument();
|
||||
doc.parse(data);
|
||||
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLineardiag1Partiel.svg"), data.replace("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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
|
||||
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";
|
||||
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
|
||||
EsvgDocument doc = new EsvgDocument();
|
||||
final EsvgDocument doc = new EsvgDocument();
|
||||
doc.parse(data);
|
||||
Assertions.assertDoesNotThrow(()-> Uri.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearhorizontal.svg"), data.replace("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
Assertions.assertDoesNotThrow(() -> Uri
|
||||
.writeAll(new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.svg"), data.replace("'", "\"")));
|
||||
ConfigTest.generateAnImage(doc, new Uri(ConfigTest.BASE_PATH + "TestGradientLinearvertical.png"));
|
||||
}
|
||||
}
|
||||
|
@ -2,217 +2,387 @@ 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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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"));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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"));
|
||||
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() {
|
||||
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();
|
||||
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("'", "\"")));
|
||||
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() {
|
||||
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();
|
||||
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"));
|
||||
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() {
|
||||
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();
|
||||
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"));
|
||||
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() {
|
||||
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();
|
||||
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"));
|
||||
Assertions.assertDoesNotThrow(() -> Uri.writeAll(
|
||||
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.svg"),
|
||||
data.replace("'", "\"")));
|
||||
ConfigTest.generateAnImage(doc,
|
||||
new Uri(ConfigTest.BASE_PATH + "TestGradientRadialunitUserspreadRepeatunCenter2.png"));
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user