geomerative 0.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/LICENSE +662 -0
- data/LICENSE.md +9 -0
- data/README.md +2 -0
- data/Rakefile +37 -0
- data/examples/README.md +7 -0
- data/examples/data/FreeSans.ttf +0 -0
- data/examples/data/ReplicaBold.ttf +0 -0
- data/examples/data/bot1.svg +160 -0
- data/examples/hello_svg_to_pdf.rb +26 -0
- data/examples/hello_world.rb +23 -0
- data/examples/physics_type.rb +77 -0
- data/examples/rotate_first_letter.rb +28 -0
- data/geomerative.gemspec +32 -0
- data/lib/geomerative.rb +12 -0
- data/lib/geomerative/version.rb +3 -0
- data/pom.xml +110 -0
- data/src/geomerative/FastRClip.java +2715 -0
- data/src/geomerative/RClip.java +2892 -0
- data/src/geomerative/RClosest.java +64 -0
- data/src/geomerative/RCommand.java +1941 -0
- data/src/geomerative/RContour.java +348 -0
- data/src/geomerative/RFont.java +583 -0
- data/src/geomerative/RG.java +753 -0
- data/src/geomerative/RGeomElem.java +1075 -0
- data/src/geomerative/RGroup.java +888 -0
- data/src/geomerative/RMatrix.java +401 -0
- data/src/geomerative/RMesh.java +420 -0
- data/src/geomerative/RPath.java +1095 -0
- data/src/geomerative/RPoint.java +419 -0
- data/src/geomerative/RPolygon.java +1110 -0
- data/src/geomerative/RRectangle.java +91 -0
- data/src/geomerative/RSVG.java +976 -0
- data/src/geomerative/RShape.java +2045 -0
- data/src/geomerative/RStrip.java +221 -0
- data/src/geomerative/RStyle.java +469 -0
- data/src/org/apache/batik/svggen/font/.SVGFont.java.swp +0 -0
- data/src/org/apache/batik/svggen/font/Font.java +188 -0
- data/src/org/apache/batik/svggen/font/Glyph.java +113 -0
- data/src/org/apache/batik/svggen/font/Messages.java.bak +72 -0
- data/src/org/apache/batik/svggen/font/Point.java +38 -0
- data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +15 -0
- data/src/org/apache/batik/svggen/font/table/ClassDef.java +42 -0
- data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +55 -0
- data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +49 -0
- data/src/org/apache/batik/svggen/font/table/CmapFormat.java +81 -0
- data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +60 -0
- data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +48 -0
- data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +147 -0
- data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +60 -0
- data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +84 -0
- data/src/org/apache/batik/svggen/font/table/CmapTable.java +87 -0
- data/src/org/apache/batik/svggen/font/table/Coverage.java +50 -0
- data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +59 -0
- data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +56 -0
- data/src/org/apache/batik/svggen/font/table/CvtTable.java +48 -0
- data/src/org/apache/batik/svggen/font/table/Device.java +63 -0
- data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +73 -0
- data/src/org/apache/batik/svggen/font/table/Feature.java +56 -0
- data/src/org/apache/batik/svggen/font/table/FeatureList.java +70 -0
- data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +52 -0
- data/src/org/apache/batik/svggen/font/table/FeatureTags.java +30 -0
- data/src/org/apache/batik/svggen/font/table/FpgmTable.java +38 -0
- data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +165 -0
- data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +160 -0
- data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +79 -0
- data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +155 -0
- data/src/org/apache/batik/svggen/font/table/GlyfTable.java +111 -0
- data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +39 -0
- data/src/org/apache/batik/svggen/font/table/GposTable.java +80 -0
- data/src/org/apache/batik/svggen/font/table/GsubTable.java +118 -0
- data/src/org/apache/batik/svggen/font/table/HeadTable.java +159 -0
- data/src/org/apache/batik/svggen/font/table/HheaTable.java +109 -0
- data/src/org/apache/batik/svggen/font/table/HmtxTable.java +99 -0
- data/src/org/apache/batik/svggen/font/table/KernSubtable.java +58 -0
- data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +65 -0
- data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +56 -0
- data/src/org/apache/batik/svggen/font/table/KernTable.java +64 -0
- data/src/org/apache/batik/svggen/font/table/KerningPair.java +53 -0
- data/src/org/apache/batik/svggen/font/table/LangSys.java +58 -0
- data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +52 -0
- data/src/org/apache/batik/svggen/font/table/Ligature.java +57 -0
- data/src/org/apache/batik/svggen/font/table/LigatureSet.java +55 -0
- data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +40 -0
- data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +63 -0
- data/src/org/apache/batik/svggen/font/table/LocaTable.java +72 -0
- data/src/org/apache/batik/svggen/font/table/Lookup.java +77 -0
- data/src/org/apache/batik/svggen/font/table/LookupList.java +68 -0
- data/src/org/apache/batik/svggen/font/table/LookupSubtable.java +27 -0
- data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +31 -0
- data/src/org/apache/batik/svggen/font/table/MaxpTable.java +124 -0
- data/src/org/apache/batik/svggen/font/table/NameRecord.java +98 -0
- data/src/org/apache/batik/svggen/font/table/NameTable.java +67 -0
- data/src/org/apache/batik/svggen/font/table/Os2Table.java +232 -0
- data/src/org/apache/batik/svggen/font/table/Panose.java +108 -0
- data/src/org/apache/batik/svggen/font/table/PostTable.java +379 -0
- data/src/org/apache/batik/svggen/font/table/PrepTable.java +38 -0
- data/src/org/apache/batik/svggen/font/table/Program.java +49 -0
- data/src/org/apache/batik/svggen/font/table/RangeRecord.java +57 -0
- data/src/org/apache/batik/svggen/font/table/Script.java +72 -0
- data/src/org/apache/batik/svggen/font/table/ScriptList.java +78 -0
- data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +52 -0
- data/src/org/apache/batik/svggen/font/table/ScriptTags.java +28 -0
- data/src/org/apache/batik/svggen/font/table/SingleSubst.java +47 -0
- data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +67 -0
- data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +67 -0
- data/src/org/apache/batik/svggen/font/table/Table.java +204 -0
- data/src/org/apache/batik/svggen/font/table/TableDirectory.java +94 -0
- data/src/org/apache/batik/svggen/font/table/TableFactory.java +121 -0
- metadata +206 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
|
|
3
|
+
|
|
4
|
+
This file is part of Geomerative.
|
|
5
|
+
|
|
6
|
+
Geomerative is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
Geomerative is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with Geomerative. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
package geomerative ;
|
|
21
|
+
|
|
22
|
+
public class RRectangle
|
|
23
|
+
{
|
|
24
|
+
RPoint topLeft;
|
|
25
|
+
RPoint bottomRight;
|
|
26
|
+
|
|
27
|
+
public RRectangle()
|
|
28
|
+
{
|
|
29
|
+
topLeft = new RPoint();
|
|
30
|
+
bottomRight = new RPoint();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public RRectangle(float x,float y,float w,float h)
|
|
34
|
+
{
|
|
35
|
+
topLeft = new RPoint(x,y);
|
|
36
|
+
bottomRight = new RPoint(x+w,y+h);
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public RRectangle(RPoint _topLeft,RPoint _bottomRight)
|
|
41
|
+
{
|
|
42
|
+
this.topLeft = _topLeft;
|
|
43
|
+
this.bottomRight = _bottomRight;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
RPoint[] getPoints() {
|
|
47
|
+
RPoint[] ps = new RPoint[4];
|
|
48
|
+
|
|
49
|
+
ps[0] = new RPoint(topLeft);
|
|
50
|
+
|
|
51
|
+
ps[1] = new RPoint(topLeft);
|
|
52
|
+
ps[1].x = bottomRight.x;
|
|
53
|
+
|
|
54
|
+
ps[2] = new RPoint(bottomRight);
|
|
55
|
+
|
|
56
|
+
ps[3] = new RPoint(bottomRight);
|
|
57
|
+
ps[3].x = topLeft.x;
|
|
58
|
+
|
|
59
|
+
return ps;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
float getMaxX()
|
|
63
|
+
{
|
|
64
|
+
//return (topLeft.x > bottomRight.x) ? topLeft.x : bottomRight.x;
|
|
65
|
+
return bottomRight.x;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
float getMaxY()
|
|
69
|
+
{
|
|
70
|
+
//return (topLeft.y > bottomRight.y) ? topLeft.y : bottomRight.y;
|
|
71
|
+
return bottomRight.y;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
float getMinX()
|
|
75
|
+
{
|
|
76
|
+
//return (topLeft.x < bottomRight.x) ? topLeft.x : bottomRight.x;
|
|
77
|
+
return topLeft.x;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
float getMinY()
|
|
81
|
+
{
|
|
82
|
+
//return (topLeft.y < bottomRight.y) ? topLeft.y : bottomRight.y;
|
|
83
|
+
return topLeft.y;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Override
|
|
87
|
+
public String toString()
|
|
88
|
+
{
|
|
89
|
+
return "";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,976 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright 2004-2008 Ricard Marxer <email@ricardmarxer.com>
|
|
3
|
+
|
|
4
|
+
This file is part of Geomerative.
|
|
5
|
+
|
|
6
|
+
Geomerative is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
Geomerative is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with Geomerative. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
package geomerative;
|
|
21
|
+
|
|
22
|
+
import processing.core.*;
|
|
23
|
+
import processing.data.*;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @extended
|
|
27
|
+
*/
|
|
28
|
+
public class RSVG
|
|
29
|
+
{
|
|
30
|
+
public void draw(String filename, PGraphics g)
|
|
31
|
+
{
|
|
32
|
+
this.toGroup(filename).draw(g);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void draw(String filename, PApplet p)
|
|
36
|
+
{
|
|
37
|
+
this.toGroup(filename).draw(p);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public void draw(String filename)
|
|
41
|
+
{
|
|
42
|
+
this.toGroup(filename).draw();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public void saveShape(String filename, RShape shp) {
|
|
46
|
+
String str = fromShape(shp);
|
|
47
|
+
String[] strs = PApplet.split(str, "\n");
|
|
48
|
+
RG.parent().saveStrings(filename, strs);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public String fromShape(RShape shape) {
|
|
52
|
+
String header = "<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg width=\"100%\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n";
|
|
53
|
+
|
|
54
|
+
return header + shapeToString(shape) + "</svg>";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public void saveGroup(String filename, RGroup grp) {
|
|
58
|
+
String str = fromGroup(grp);
|
|
59
|
+
String[] strs = PApplet.split(str, "\n");
|
|
60
|
+
RG.parent().saveStrings(filename, strs);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public String fromGroup(RGroup group) {
|
|
64
|
+
String header = "<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<svg width=\"100%\" height=\"100%\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n";
|
|
65
|
+
|
|
66
|
+
return header + groupToString(group) + "</svg>";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
public RGroup toGroup(String filename)
|
|
72
|
+
{
|
|
73
|
+
XML svg;
|
|
74
|
+
|
|
75
|
+
svg = RG.parent().loadXML(filename);
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
if (svg == null) return new RGroup();
|
|
79
|
+
|
|
80
|
+
if (!svg.getName().equals("svg")) {
|
|
81
|
+
throw new RuntimeException("root is not <svg>, it's <" + svg.getName() + ">");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return elemToGroup(svg);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public float unitsToPixels(String units, float originalPxSize) {
|
|
88
|
+
// TODO: check if it is possible to know the dpi of a given PGraphics or device
|
|
89
|
+
return unitsToPixels(units, originalPxSize, 72.0f/*Toolkit.getDefaultToolkit().getScreenResolution()*/);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public float unitsToPixels(String units, float originalPxSize, float dpi) {
|
|
93
|
+
int chars = 0;
|
|
94
|
+
float multiplier = 1.0f;
|
|
95
|
+
|
|
96
|
+
if (units.endsWith("em")) {
|
|
97
|
+
chars = 2;
|
|
98
|
+
multiplier = 1.0f;
|
|
99
|
+
} else if (units.endsWith("ex")) {
|
|
100
|
+
chars = 2;
|
|
101
|
+
multiplier = 1.0f;
|
|
102
|
+
} else if (units.endsWith("px")) {
|
|
103
|
+
chars = 2;
|
|
104
|
+
multiplier = 1.0f;
|
|
105
|
+
} else if (units.endsWith("pt")) {
|
|
106
|
+
chars = 2;
|
|
107
|
+
multiplier = 1.25f;
|
|
108
|
+
} else if (units.endsWith("pc")) {
|
|
109
|
+
chars = 2;
|
|
110
|
+
multiplier = 15f;
|
|
111
|
+
} else if (units.endsWith("cm")) {
|
|
112
|
+
chars = 2;
|
|
113
|
+
multiplier = 35.43307f / 90.0f * dpi;
|
|
114
|
+
} else if (units.endsWith("mm")) {
|
|
115
|
+
chars = 2;
|
|
116
|
+
multiplier = 3.543307f / 90.0f * dpi;
|
|
117
|
+
} else if (units.endsWith("in")) {
|
|
118
|
+
chars = 2;
|
|
119
|
+
multiplier = dpi;
|
|
120
|
+
} else if (units.endsWith("%")) {
|
|
121
|
+
chars = 1;
|
|
122
|
+
multiplier = originalPxSize / 100.0f;
|
|
123
|
+
} else {
|
|
124
|
+
chars = 0;
|
|
125
|
+
multiplier = 1.0f;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return Float.parseFloat(units.substring(0, units.length()-chars)) * multiplier;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public RShape toShape(String filename)
|
|
132
|
+
{
|
|
133
|
+
XML svg;
|
|
134
|
+
|
|
135
|
+
svg = RG.parent().loadXML(filename);
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if (svg == null) return new RShape();
|
|
139
|
+
|
|
140
|
+
if ( !svg.getName().equals("svg") )
|
|
141
|
+
{
|
|
142
|
+
throw new RuntimeException("root is not <svg>, it's <" + svg.getName() + ">");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
RShape result = elemToCompositeShape(svg);
|
|
146
|
+
|
|
147
|
+
result.origWidth = result.getWidth();
|
|
148
|
+
result.origHeight = result.getHeight();
|
|
149
|
+
|
|
150
|
+
if (svg.hasAttribute("width") && svg.hasAttribute("height")) {
|
|
151
|
+
String widthStr = svg.getString("width").trim();
|
|
152
|
+
String heightStr = svg.getString("height").trim();
|
|
153
|
+
|
|
154
|
+
result.width = unitsToPixels(widthStr, result.origWidth);
|
|
155
|
+
result.height = unitsToPixels(heightStr, result.origHeight);
|
|
156
|
+
} else {
|
|
157
|
+
result.width = result.origWidth;
|
|
158
|
+
result.height = result.origHeight;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public RPolygon toPolygon(String filename)
|
|
165
|
+
{
|
|
166
|
+
return toGroup(filename).toPolygon();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public RMesh toMesh(String filename)
|
|
170
|
+
{
|
|
171
|
+
return toGroup(filename).toMesh();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public String groupToString(RGroup grp) {
|
|
175
|
+
String result = "";
|
|
176
|
+
result += "<g ";
|
|
177
|
+
result += styleToString(grp.getStyle());
|
|
178
|
+
result += ">\n";
|
|
179
|
+
|
|
180
|
+
for(int i=0;i<grp.countElements();i++) {
|
|
181
|
+
switch(grp.elements[i].getType()){
|
|
182
|
+
case RGeomElem.GROUP:
|
|
183
|
+
result += groupToString((RGroup)grp.elements[i]);
|
|
184
|
+
break;
|
|
185
|
+
|
|
186
|
+
case RGeomElem.POLYGON:
|
|
187
|
+
result += polygonToString((RPolygon)grp.elements[i]);
|
|
188
|
+
break;
|
|
189
|
+
|
|
190
|
+
case RGeomElem.SHAPE:
|
|
191
|
+
result += shapeToString((RShape)grp.elements[i]);
|
|
192
|
+
break;
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
result += "</g>\n";
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public String polygonToString(RPolygon poly) {
|
|
202
|
+
String result = "";
|
|
203
|
+
result += shapeToString(poly.toShape());
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public String shapeToString(RShape shp) {
|
|
208
|
+
String result = "";
|
|
209
|
+
|
|
210
|
+
// If it has children it is a group
|
|
211
|
+
result += "<g ";
|
|
212
|
+
result += styleToString(shp.getStyle());
|
|
213
|
+
result += ">\n";
|
|
214
|
+
|
|
215
|
+
if (shp.countPaths() > 0) {
|
|
216
|
+
result += "<path ";
|
|
217
|
+
result += "d=\"";
|
|
218
|
+
|
|
219
|
+
for(int i=0; i<shp.countPaths(); i++) {
|
|
220
|
+
RPath sushp = shp.paths[i];
|
|
221
|
+
boolean init = true;
|
|
222
|
+
for ( int j = 0; j < sushp.countCommands(); j++ ) {
|
|
223
|
+
RCommand cmd = sushp.commands[j];
|
|
224
|
+
|
|
225
|
+
if (init) {
|
|
226
|
+
result += "M" + cmd.startPoint.x + " " + cmd.startPoint.y + " ";
|
|
227
|
+
init = false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
switch( cmd.getCommandType() )
|
|
231
|
+
{
|
|
232
|
+
case RCommand.LINETO:
|
|
233
|
+
result += "L" + cmd.endPoint.x + " " + cmd.endPoint.y + " ";
|
|
234
|
+
break;
|
|
235
|
+
|
|
236
|
+
case RCommand.QUADBEZIERTO:
|
|
237
|
+
result += "Q" + cmd.controlPoints[0].x + " " + cmd.controlPoints[0].y + cmd.endPoint.x + " " + cmd.endPoint.y + " ";
|
|
238
|
+
break;
|
|
239
|
+
|
|
240
|
+
case RCommand.CUBICBEZIERTO:
|
|
241
|
+
result += "C" + cmd.controlPoints[0].x + " " + cmd.controlPoints[0].y + " " + cmd.controlPoints[1].x + " " + cmd.controlPoints[1].y + " " + cmd.endPoint.x + " " + cmd.endPoint.y + " ";
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (sushp.closed) {
|
|
247
|
+
result += "Z ";
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
result += "\"/>\n";
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
for (int i=0; i<shp.countChildren(); i++) {
|
|
255
|
+
result+=shapeToString(shp.children[i]);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
result += "</g>\n";
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public String styleToString(RStyle style) {
|
|
263
|
+
String result = " style=\"";
|
|
264
|
+
|
|
265
|
+
if (style.fillDef) {
|
|
266
|
+
if (!style.fill) {
|
|
267
|
+
result += "fill:none;";
|
|
268
|
+
} else {
|
|
269
|
+
result += "fill:#" + PApplet.hex(style.fillColor, 6) + ";";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (style.fillAlphaDef) {
|
|
274
|
+
result += "fill-opacity:" + style.fillAlpha/255.0f + ";";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (style.strokeDef) {
|
|
278
|
+
if (!style.stroke) {
|
|
279
|
+
result += "stroke:none;";
|
|
280
|
+
} else {
|
|
281
|
+
result += "stroke:#" + PApplet.hex(style.strokeColor, 6) + ";";
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (style.strokeAlphaDef) {
|
|
286
|
+
result += "stroke-opacity:" + style.strokeAlpha/255.0f + ";";
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (style.strokeWeightDef) {
|
|
290
|
+
result += "stroke-width:" + style.strokeWeight + ";";
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
if(style.strokeCapDef) {
|
|
295
|
+
result += "stroke-linecap:";
|
|
296
|
+
|
|
297
|
+
switch (style.strokeCap) {
|
|
298
|
+
case RG.PROJECT:
|
|
299
|
+
result += "butt";
|
|
300
|
+
break;
|
|
301
|
+
case RG.ROUND:
|
|
302
|
+
result += "round";
|
|
303
|
+
break;
|
|
304
|
+
case RG.SQUARE:
|
|
305
|
+
result += "square";
|
|
306
|
+
break;
|
|
307
|
+
|
|
308
|
+
default:
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
result += ";";
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if(style.strokeJoinDef) {
|
|
316
|
+
result += "stroke-linejoin:";
|
|
317
|
+
|
|
318
|
+
switch (style.strokeJoin) {
|
|
319
|
+
case RG.MITER:
|
|
320
|
+
result += "miter";
|
|
321
|
+
break;
|
|
322
|
+
case RG.ROUND:
|
|
323
|
+
result += "round";
|
|
324
|
+
break;
|
|
325
|
+
case RG.BEVEL:
|
|
326
|
+
result += "bevel";
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
default:
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
result += ";";
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
result += "\" ";
|
|
337
|
+
return result;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* @param elem
|
|
342
|
+
* @return
|
|
343
|
+
* @invisible
|
|
344
|
+
*/
|
|
345
|
+
public RGroup elemToGroup(XML elem)
|
|
346
|
+
{
|
|
347
|
+
RGroup grp = new RGroup();
|
|
348
|
+
|
|
349
|
+
// Set the defaults SVG styles for the root
|
|
350
|
+
if(elem.getName().toLowerCase().equals("svg")){
|
|
351
|
+
grp.setFill(0); // By default in SVG it's black
|
|
352
|
+
grp.setFillAlpha(255); // By default in SVG it's 1
|
|
353
|
+
grp.setStroke(false); // By default in SVG it's none
|
|
354
|
+
grp.setStrokeWeight(1F); // By default in SVG it's none
|
|
355
|
+
grp.setStrokeCap("butt"); // By default in SVG it's 'butt'
|
|
356
|
+
grp.setStrokeJoin("miter"); // By default in SVG it's 'miter'
|
|
357
|
+
grp.setStrokeAlpha(255); // By default in SVG it's 1
|
|
358
|
+
grp.setAlpha(255); // By default in SVG it's 1F
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
XML elems[] = elem.getChildren();
|
|
362
|
+
for (XML elem1 : elems) {
|
|
363
|
+
String name = elem1.getName().toLowerCase();
|
|
364
|
+
XML element = elem1;
|
|
365
|
+
// Parse and create the geometrical element
|
|
366
|
+
RGeomElem geomElem = null;
|
|
367
|
+
switch (name) {
|
|
368
|
+
case "g":
|
|
369
|
+
geomElem = elemToGroup(element);
|
|
370
|
+
break;
|
|
371
|
+
case "path":
|
|
372
|
+
geomElem = elemToShape(element);
|
|
373
|
+
break;
|
|
374
|
+
case "polygon":
|
|
375
|
+
geomElem = elemToPolygon(element);
|
|
376
|
+
break;
|
|
377
|
+
case "polyline":
|
|
378
|
+
geomElem = elemToPolyline(element);
|
|
379
|
+
break;
|
|
380
|
+
case "circle":
|
|
381
|
+
geomElem = elemToCircle(element);
|
|
382
|
+
break;
|
|
383
|
+
case "ellipse":
|
|
384
|
+
geomElem = elemToEllipse(element);
|
|
385
|
+
break;
|
|
386
|
+
case "rect":
|
|
387
|
+
geomElem = elemToRect(element);
|
|
388
|
+
break;
|
|
389
|
+
case "line":
|
|
390
|
+
geomElem = elemToLine(element);
|
|
391
|
+
break;
|
|
392
|
+
case "defs":
|
|
393
|
+
break;
|
|
394
|
+
default:
|
|
395
|
+
PApplet.println("Element '" + name + "' not know. Ignoring it.");
|
|
396
|
+
break; // If the geometrical element has been correctly created
|
|
397
|
+
}
|
|
398
|
+
if((geomElem != null)){
|
|
399
|
+
// Transform geometrical element
|
|
400
|
+
if(element.hasAttribute("transform")){
|
|
401
|
+
String transformString = element.getString("transform");
|
|
402
|
+
RMatrix transf = new RMatrix(transformString);
|
|
403
|
+
geomElem.transform(transf);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Get the id for the geometrical element
|
|
407
|
+
if(element.hasAttribute("id")){
|
|
408
|
+
geomElem.name = element.getString("id");
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Get the style for the geometrical element
|
|
412
|
+
if(element.hasAttribute("style")){
|
|
413
|
+
geomElem.setStyle(element.getString("style"));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Get the fill for the geometrical element
|
|
417
|
+
if(element.hasAttribute("fill")){
|
|
418
|
+
geomElem.setFill(element.getString("fill"));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Get the fill-linejoin for the geometrical element
|
|
422
|
+
if(element.hasAttribute("fill-opacity")){
|
|
423
|
+
geomElem.setFillAlpha(element.getString("fill-opacity"));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Get the stroke for the geometrical element
|
|
427
|
+
if(element.hasAttribute("stroke")){
|
|
428
|
+
geomElem.setStroke(element.getString("stroke"));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Get the stroke-width for the geometrical element
|
|
432
|
+
if(element.hasAttribute("stroke-width")){
|
|
433
|
+
geomElem.setStrokeWeight(element.getString("stroke-width"));
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Get the stroke-linecap for the geometrical element
|
|
437
|
+
if(element.hasAttribute("stroke-linecap")){
|
|
438
|
+
geomElem.setStrokeCap(element.getString("stroke-linecap"));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Get the stroke-linejoin for the geometrical element
|
|
442
|
+
if(element.hasAttribute("stroke-linejoin")){
|
|
443
|
+
geomElem.setStrokeJoin(element.getString("stroke-linejoin"));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Get the stroke-linejoin for the geometrical element
|
|
447
|
+
if(element.hasAttribute("stroke-opacity")){
|
|
448
|
+
geomElem.setStrokeAlpha(element.getString("stroke-opacity"));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Get the opacity for the geometrical element
|
|
452
|
+
if(element.hasAttribute("opacity")){
|
|
453
|
+
geomElem.setAlpha(element.getString("opacity"));
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Get the style for the geometrical element
|
|
457
|
+
grp.addElement(geomElem);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Set the original width and height
|
|
462
|
+
grp.updateOrigParams();
|
|
463
|
+
|
|
464
|
+
return grp;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @param elem
|
|
469
|
+
* @return
|
|
470
|
+
* @invisible
|
|
471
|
+
*/
|
|
472
|
+
public RShape elemToCompositeShape( XML elem )
|
|
473
|
+
{
|
|
474
|
+
RShape shp = new RShape();
|
|
475
|
+
|
|
476
|
+
// Set the defaults SVG styles for the root
|
|
477
|
+
if (elem.getName().toLowerCase().equals("svg"))
|
|
478
|
+
{
|
|
479
|
+
shp.setFill(0); // By default in SVG it's black
|
|
480
|
+
shp.setFillAlpha(255); // By default in SVG it's 1
|
|
481
|
+
shp.setStroke(false); // By default in SVG it's none
|
|
482
|
+
shp.setStrokeWeight(1F); // By default in SVG it's none
|
|
483
|
+
shp.setStrokeCap("butt"); // By default in SVG it's 'butt'
|
|
484
|
+
shp.setStrokeJoin("miter"); // By default in SVG it's 'miter'
|
|
485
|
+
shp.setStrokeAlpha(255); // By default in SVG it's 1
|
|
486
|
+
shp.setAlpha(255); // By default in SVG it's 1F
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
XML elems[] = elem.getChildren();
|
|
490
|
+
|
|
491
|
+
for (XML elem1 : elems) {
|
|
492
|
+
String name = elem1.getName();
|
|
493
|
+
if ( name == null ) continue;
|
|
494
|
+
name = name.toLowerCase();
|
|
495
|
+
XML element = elem1;
|
|
496
|
+
// Parse and create the geometrical element
|
|
497
|
+
RShape geomElem = null;
|
|
498
|
+
switch (name) {
|
|
499
|
+
case "g":
|
|
500
|
+
geomElem = elemToCompositeShape(element);
|
|
501
|
+
break;
|
|
502
|
+
case "path":
|
|
503
|
+
geomElem = elemToShape(element);
|
|
504
|
+
break;
|
|
505
|
+
case "polygon":
|
|
506
|
+
geomElem = elemToPolygon(element);
|
|
507
|
+
break;
|
|
508
|
+
case "polyline":
|
|
509
|
+
geomElem = elemToPolyline(element);
|
|
510
|
+
break;
|
|
511
|
+
case "circle":
|
|
512
|
+
geomElem = elemToCircle(element);
|
|
513
|
+
break;
|
|
514
|
+
case "ellipse":
|
|
515
|
+
geomElem = elemToEllipse(element);
|
|
516
|
+
break;
|
|
517
|
+
case "rect":
|
|
518
|
+
geomElem = elemToRect(element);
|
|
519
|
+
break;
|
|
520
|
+
case "line":
|
|
521
|
+
geomElem = elemToLine(element);
|
|
522
|
+
break;
|
|
523
|
+
case "defs":
|
|
524
|
+
break;
|
|
525
|
+
default:
|
|
526
|
+
PApplet.println("Element '" + name + "' not know. Ignoring it.");
|
|
527
|
+
break; // If the geometrical element has been correctly created
|
|
528
|
+
}
|
|
529
|
+
if((geomElem != null)){
|
|
530
|
+
// Transform geometrical element
|
|
531
|
+
if(element.hasAttribute("transform")){
|
|
532
|
+
String transformString = element.getString("transform");
|
|
533
|
+
RMatrix transf = new RMatrix(transformString);
|
|
534
|
+
geomElem.transform(transf);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Get the id for the geometrical element
|
|
538
|
+
if(element.hasAttribute("id")){
|
|
539
|
+
geomElem.name = element.getString("id");
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Get the style for the geometrical element
|
|
543
|
+
if(element.hasAttribute("style")){
|
|
544
|
+
geomElem.setStyle(element.getString("style"));
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Get the fill for the geometrical element
|
|
548
|
+
if(element.hasAttribute("fill")){
|
|
549
|
+
geomElem.setFill(element.getString("fill"));
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Get the fill-linejoin for the geometrical element
|
|
553
|
+
if(element.hasAttribute("fill-opacity")){
|
|
554
|
+
geomElem.setFillAlpha(element.getString("fill-opacity"));
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Get the stroke for the geometrical element
|
|
558
|
+
if(element.hasAttribute("stroke")){
|
|
559
|
+
geomElem.setStroke(element.getString("stroke"));
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Get the stroke-width for the geometrical element
|
|
563
|
+
if(element.hasAttribute("stroke-width")){
|
|
564
|
+
geomElem.setStrokeWeight(element.getString("stroke-width"));
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Get the stroke-linecap for the geometrical element
|
|
568
|
+
if(element.hasAttribute("stroke-linecap")){
|
|
569
|
+
geomElem.setStrokeCap(element.getString("stroke-linecap"));
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Get the stroke-linejoin for the geometrical element
|
|
573
|
+
if(element.hasAttribute("stroke-linejoin")){
|
|
574
|
+
geomElem.setStrokeJoin(element.getString("stroke-linejoin"));
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Get the stroke-linejoin for the geometrical element
|
|
578
|
+
if(element.hasAttribute("stroke-opacity")){
|
|
579
|
+
geomElem.setStrokeAlpha(element.getString("stroke-opacity"));
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Get the opacity for the geometrical element
|
|
583
|
+
if(element.hasAttribute("opacity")){
|
|
584
|
+
geomElem.setAlpha(element.getString("opacity"));
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Get the style for the geometrical element
|
|
588
|
+
shp.addChild(geomElem);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
shp.updateOrigParams();
|
|
593
|
+
|
|
594
|
+
return shp;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* @param elem
|
|
599
|
+
* @return
|
|
600
|
+
* @invisible
|
|
601
|
+
*/
|
|
602
|
+
public RShape elemToPolyline(XML elem)
|
|
603
|
+
{
|
|
604
|
+
RShape shp = getPolyline(elem.getString("points").trim());
|
|
605
|
+
|
|
606
|
+
shp.updateOrigParams();
|
|
607
|
+
|
|
608
|
+
return shp;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* @param elem
|
|
613
|
+
* @return
|
|
614
|
+
* @invisible
|
|
615
|
+
*/
|
|
616
|
+
public RShape elemToPolygon(XML elem)
|
|
617
|
+
{
|
|
618
|
+
RShape poly = elemToPolyline(elem);
|
|
619
|
+
|
|
620
|
+
poly.addClose();
|
|
621
|
+
|
|
622
|
+
poly.updateOrigParams();
|
|
623
|
+
|
|
624
|
+
return poly;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* @param elem
|
|
629
|
+
* @return
|
|
630
|
+
* @invisible
|
|
631
|
+
*/
|
|
632
|
+
public RShape elemToRect(XML elem)
|
|
633
|
+
{
|
|
634
|
+
|
|
635
|
+
RShape shp = getRect(elem.getFloat("x"), elem.getFloat("y"), elem.getFloat("width"), elem.getFloat("height"));
|
|
636
|
+
|
|
637
|
+
shp.updateOrigParams();
|
|
638
|
+
|
|
639
|
+
return shp;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* @param elem
|
|
644
|
+
* @return
|
|
645
|
+
* @invisible
|
|
646
|
+
*/
|
|
647
|
+
public RShape elemToLine(XML elem)
|
|
648
|
+
{
|
|
649
|
+
RShape shp = getLine(elem.getFloat("x1"), elem.getFloat("y1"), elem.getFloat("x2"), elem.getFloat("y2"));
|
|
650
|
+
|
|
651
|
+
shp.updateOrigParams();
|
|
652
|
+
|
|
653
|
+
return shp;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* @param elem
|
|
659
|
+
* @return
|
|
660
|
+
* @invisible
|
|
661
|
+
*/
|
|
662
|
+
public RShape elemToEllipse(XML elem)
|
|
663
|
+
{
|
|
664
|
+
RShape shp = getEllipse(elem.getFloat("cx"), elem.getFloat("cy"), elem.getFloat("rx"), elem.getFloat("ry"));
|
|
665
|
+
|
|
666
|
+
shp.updateOrigParams();
|
|
667
|
+
|
|
668
|
+
return shp;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* @param elem
|
|
674
|
+
* @return
|
|
675
|
+
* @invisible
|
|
676
|
+
*/
|
|
677
|
+
public RShape elemToCircle(XML elem)
|
|
678
|
+
{
|
|
679
|
+
float r = elem.getFloat("r");
|
|
680
|
+
RShape shp = getEllipse(elem.getFloat("cx"), elem.getFloat("cy"), r, r);
|
|
681
|
+
|
|
682
|
+
shp.updateOrigParams();
|
|
683
|
+
|
|
684
|
+
return shp;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* @param elem
|
|
689
|
+
* @return
|
|
690
|
+
* @invisible
|
|
691
|
+
*/
|
|
692
|
+
public RShape elemToShape(XML elem)
|
|
693
|
+
{
|
|
694
|
+
RShape shp = getShape(elem.getString("d"));
|
|
695
|
+
|
|
696
|
+
shp.updateOrigParams();
|
|
697
|
+
|
|
698
|
+
return shp;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* @invisible
|
|
703
|
+
*/
|
|
704
|
+
private RShape getRect(float x, float y, float w, float h)
|
|
705
|
+
{
|
|
706
|
+
RShape shp = RShape.createRectangle(x, y, w, h);
|
|
707
|
+
|
|
708
|
+
shp.updateOrigParams();
|
|
709
|
+
|
|
710
|
+
return shp;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* @invisible
|
|
715
|
+
*/
|
|
716
|
+
private RShape getLine(float x1, float y1, float x2, float y2)
|
|
717
|
+
{
|
|
718
|
+
RShape shp = new RShape();
|
|
719
|
+
|
|
720
|
+
shp.addMoveTo(x1, y1);
|
|
721
|
+
shp.addLineTo(x2, y2);
|
|
722
|
+
|
|
723
|
+
return shp;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* @invisible
|
|
729
|
+
*/
|
|
730
|
+
private RShape getEllipse(float cx, float cy, float rx, float ry)
|
|
731
|
+
{
|
|
732
|
+
// RShape createEllipse takes as input the width and height of the ellipses
|
|
733
|
+
return RShape.createEllipse(cx, cy, rx*2F, ry*2F);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* @invisible
|
|
738
|
+
*/
|
|
739
|
+
private RShape getPolyline(String s)
|
|
740
|
+
{
|
|
741
|
+
RShape poly = new RShape();
|
|
742
|
+
boolean first = true;
|
|
743
|
+
|
|
744
|
+
//format string to usable format
|
|
745
|
+
char charline[]=s.toCharArray();
|
|
746
|
+
for(int i=0;i<charline.length;i++)
|
|
747
|
+
{
|
|
748
|
+
switch(charline[i])
|
|
749
|
+
{
|
|
750
|
+
case '-':
|
|
751
|
+
if(charline[i-1] != 'e' && charline[i-1] != 'E'){
|
|
752
|
+
charline=PApplet.splice(charline,' ',i);
|
|
753
|
+
i++;
|
|
754
|
+
}
|
|
755
|
+
break;
|
|
756
|
+
case ',':
|
|
757
|
+
case '\n':
|
|
758
|
+
case '\r':
|
|
759
|
+
case '\t':
|
|
760
|
+
charline[i]=' ';
|
|
761
|
+
break;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
String formatted=new String(charline);
|
|
765
|
+
String tags[]=PApplet.splitTokens(formatted,", ");
|
|
766
|
+
for(int i=0;i<tags.length;i++){
|
|
767
|
+
float x = PApplet.parseFloat(tags[i]);
|
|
768
|
+
float y = PApplet.parseFloat(tags[i+1]);
|
|
769
|
+
i++;
|
|
770
|
+
if(first){
|
|
771
|
+
poly.addMoveTo(x,y);
|
|
772
|
+
first = false;
|
|
773
|
+
}else{
|
|
774
|
+
poly.addLineTo(x,y);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return poly;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* @invisible
|
|
782
|
+
*/
|
|
783
|
+
private RShape getShape(String s)
|
|
784
|
+
{
|
|
785
|
+
RShape shp = new RShape();
|
|
786
|
+
|
|
787
|
+
if(s == null){
|
|
788
|
+
return shp;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
//format string to usable format
|
|
792
|
+
char charline[] = s.toCharArray();
|
|
793
|
+
for( int i = 0 ; i < charline.length ; i++)
|
|
794
|
+
{
|
|
795
|
+
switch(charline[i])
|
|
796
|
+
{
|
|
797
|
+
case 'M':
|
|
798
|
+
case 'm':
|
|
799
|
+
case 'Z':
|
|
800
|
+
case 'z':
|
|
801
|
+
case 'C':
|
|
802
|
+
case 'c':
|
|
803
|
+
case 'S':
|
|
804
|
+
case 's':
|
|
805
|
+
case 'L':
|
|
806
|
+
case 'l':
|
|
807
|
+
case 'H':
|
|
808
|
+
case 'h':
|
|
809
|
+
case 'V':
|
|
810
|
+
case 'v':
|
|
811
|
+
charline = PApplet.splice(charline,' ',i);
|
|
812
|
+
i ++;
|
|
813
|
+
charline = PApplet.splice(charline,' ',i+1);
|
|
814
|
+
i ++;
|
|
815
|
+
break;
|
|
816
|
+
|
|
817
|
+
case '-':
|
|
818
|
+
if(i>0 && charline[i-1] != 'e' && charline[i-1] != 'E'){
|
|
819
|
+
charline=PApplet.splice(charline,' ',i);
|
|
820
|
+
i++;
|
|
821
|
+
}
|
|
822
|
+
break;
|
|
823
|
+
case ',':
|
|
824
|
+
case '\n':
|
|
825
|
+
case '\r':
|
|
826
|
+
case '\t':
|
|
827
|
+
charline[i] = ' ';
|
|
828
|
+
break;
|
|
829
|
+
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
String formatted = new String(charline);
|
|
833
|
+
String[] tags = PApplet.splitTokens(formatted);
|
|
834
|
+
|
|
835
|
+
//PApplet.println("formatted: " + formatted);
|
|
836
|
+
//PApplet.println("tags: ");
|
|
837
|
+
//PApplet.println(tags);
|
|
838
|
+
|
|
839
|
+
//build points
|
|
840
|
+
RPoint curp = new RPoint();
|
|
841
|
+
RPoint relp = new RPoint();
|
|
842
|
+
RPoint refp = new RPoint();
|
|
843
|
+
RPoint strp = new RPoint();
|
|
844
|
+
|
|
845
|
+
char command = 'a';
|
|
846
|
+
|
|
847
|
+
for (int i=0;i<tags.length;i++)
|
|
848
|
+
{
|
|
849
|
+
char nextChar = tags[i].charAt(0);
|
|
850
|
+
switch(nextChar)
|
|
851
|
+
{
|
|
852
|
+
case 'm':
|
|
853
|
+
case 'M':
|
|
854
|
+
case 'c':
|
|
855
|
+
case 'C':
|
|
856
|
+
case 's':
|
|
857
|
+
case 'S':
|
|
858
|
+
case 'l':
|
|
859
|
+
case 'L':
|
|
860
|
+
case 'h':
|
|
861
|
+
case 'H':
|
|
862
|
+
case 'v':
|
|
863
|
+
case 'V':
|
|
864
|
+
i += 1;
|
|
865
|
+
case 'z':
|
|
866
|
+
case 'Z':
|
|
867
|
+
command = nextChar;
|
|
868
|
+
break;
|
|
869
|
+
default:
|
|
870
|
+
if (command == 'm') {
|
|
871
|
+
command = 'l';
|
|
872
|
+
} else if (command == 'M') {
|
|
873
|
+
command = 'L';
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
relp.setLocation(0F, 0F);
|
|
878
|
+
|
|
879
|
+
switch(command)
|
|
880
|
+
{
|
|
881
|
+
case 'm':
|
|
882
|
+
relp.setLocation(curp.x, curp.y);
|
|
883
|
+
case 'M':
|
|
884
|
+
i = move(shp, curp, relp, refp, strp, tags, i);
|
|
885
|
+
break;
|
|
886
|
+
|
|
887
|
+
case 'z':
|
|
888
|
+
relp.setLocation(curp.x, curp.y);
|
|
889
|
+
case 'Z':
|
|
890
|
+
shp.addClose();
|
|
891
|
+
break;
|
|
892
|
+
|
|
893
|
+
case 'c':
|
|
894
|
+
relp.setLocation(curp.x, curp.y);
|
|
895
|
+
case 'C':
|
|
896
|
+
i = curve(shp, curp, relp, refp, strp, tags, i);
|
|
897
|
+
break;
|
|
898
|
+
|
|
899
|
+
case 's':
|
|
900
|
+
relp.setLocation(curp.x, curp.y);
|
|
901
|
+
case 'S':
|
|
902
|
+
i = smooth(shp, curp, relp, refp, strp, tags, i);
|
|
903
|
+
break;
|
|
904
|
+
|
|
905
|
+
case 'l':
|
|
906
|
+
relp.setLocation(curp.x, curp.y);
|
|
907
|
+
case 'L':
|
|
908
|
+
i = line(shp, curp, relp, refp, strp, tags, i);
|
|
909
|
+
break;
|
|
910
|
+
|
|
911
|
+
case 'h':
|
|
912
|
+
relp.setLocation(curp.x, curp.y);
|
|
913
|
+
case 'H':
|
|
914
|
+
i = horizontal(shp, curp, relp, refp, strp, tags, i);
|
|
915
|
+
break;
|
|
916
|
+
|
|
917
|
+
case 'v':
|
|
918
|
+
relp.setLocation(curp.x, curp.y);
|
|
919
|
+
case 'V':
|
|
920
|
+
i = vertical(shp, curp, relp, refp, strp, tags, i);
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return shp;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
private int move(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
928
|
+
shp.addMoveTo(PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y);
|
|
929
|
+
|
|
930
|
+
curp.setLocation(PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y);
|
|
931
|
+
refp.setLocation(curp.x,curp.y);
|
|
932
|
+
strp.setLocation(curp.x,curp.y);
|
|
933
|
+
//relp.setLocation(0F, 0F);
|
|
934
|
+
return i + 1;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
private int curve(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
938
|
+
shp.addBezierTo(PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y, PApplet.parseFloat(tags[i+2])+relp.x, PApplet.parseFloat(tags[i+3])+relp.y, PApplet.parseFloat(tags[i+4])+relp.x, PApplet.parseFloat(tags[i+5])+relp.y);
|
|
939
|
+
|
|
940
|
+
curp.setLocation(PApplet.parseFloat(tags[i+4])+relp.x, PApplet.parseFloat(tags[i+5])+relp.y);
|
|
941
|
+
refp.setLocation(2.0f*curp.x-(PApplet.parseFloat(tags[i+2])+relp.x), 2.0f*curp.y-(PApplet.parseFloat(tags[i+3])+relp.y));
|
|
942
|
+
return i + 5;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
private int smooth(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
946
|
+
shp.addBezierTo(refp.x, refp.y, PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y, PApplet.parseFloat(tags[i+2])+relp.x, PApplet.parseFloat(tags[i+3])+relp.y);
|
|
947
|
+
|
|
948
|
+
curp.setLocation(PApplet.parseFloat(tags[i+2])+relp.x, PApplet.parseFloat(tags[i+3])+relp.y);
|
|
949
|
+
refp.setLocation(2.0f*curp.x-(PApplet.parseFloat(tags[i])+relp.x), 2.0f*curp.y-(PApplet.parseFloat(tags[i+1])+relp.y));
|
|
950
|
+
return i + 3;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
private int line(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
954
|
+
shp.addLineTo(PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y);
|
|
955
|
+
|
|
956
|
+
curp.setLocation(PApplet.parseFloat(tags[i])+relp.x, PApplet.parseFloat(tags[i+1])+relp.y);
|
|
957
|
+
refp.setLocation(curp.x, curp.y);
|
|
958
|
+
return i + 1;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
private int horizontal(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
962
|
+
shp.addLineTo(PApplet.parseFloat(tags[i])+relp.x, curp.y);
|
|
963
|
+
|
|
964
|
+
curp.setLocation(PApplet.parseFloat(tags[i])+relp.x, curp.y);
|
|
965
|
+
refp.setLocation(curp.x, curp.y);
|
|
966
|
+
return i;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
private int vertical(RShape shp, RPoint curp, RPoint relp, RPoint refp, RPoint strp, String[] tags, int i){
|
|
970
|
+
shp.addLineTo(curp.x, PApplet.parseFloat(tags[i])+relp.y);
|
|
971
|
+
|
|
972
|
+
curp.setLocation(curp.x, PApplet.parseFloat(tags[i])+relp.y);
|
|
973
|
+
refp.setLocation(curp.x, curp.y);
|
|
974
|
+
return i;
|
|
975
|
+
}
|
|
976
|
+
}
|