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.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/LICENSE +662 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +2 -0
  6. data/Rakefile +37 -0
  7. data/examples/README.md +7 -0
  8. data/examples/data/FreeSans.ttf +0 -0
  9. data/examples/data/ReplicaBold.ttf +0 -0
  10. data/examples/data/bot1.svg +160 -0
  11. data/examples/hello_svg_to_pdf.rb +26 -0
  12. data/examples/hello_world.rb +23 -0
  13. data/examples/physics_type.rb +77 -0
  14. data/examples/rotate_first_letter.rb +28 -0
  15. data/geomerative.gemspec +32 -0
  16. data/lib/geomerative.rb +12 -0
  17. data/lib/geomerative/version.rb +3 -0
  18. data/pom.xml +110 -0
  19. data/src/geomerative/FastRClip.java +2715 -0
  20. data/src/geomerative/RClip.java +2892 -0
  21. data/src/geomerative/RClosest.java +64 -0
  22. data/src/geomerative/RCommand.java +1941 -0
  23. data/src/geomerative/RContour.java +348 -0
  24. data/src/geomerative/RFont.java +583 -0
  25. data/src/geomerative/RG.java +753 -0
  26. data/src/geomerative/RGeomElem.java +1075 -0
  27. data/src/geomerative/RGroup.java +888 -0
  28. data/src/geomerative/RMatrix.java +401 -0
  29. data/src/geomerative/RMesh.java +420 -0
  30. data/src/geomerative/RPath.java +1095 -0
  31. data/src/geomerative/RPoint.java +419 -0
  32. data/src/geomerative/RPolygon.java +1110 -0
  33. data/src/geomerative/RRectangle.java +91 -0
  34. data/src/geomerative/RSVG.java +976 -0
  35. data/src/geomerative/RShape.java +2045 -0
  36. data/src/geomerative/RStrip.java +221 -0
  37. data/src/geomerative/RStyle.java +469 -0
  38. data/src/org/apache/batik/svggen/font/.SVGFont.java.swp +0 -0
  39. data/src/org/apache/batik/svggen/font/Font.java +188 -0
  40. data/src/org/apache/batik/svggen/font/Glyph.java +113 -0
  41. data/src/org/apache/batik/svggen/font/Messages.java.bak +72 -0
  42. data/src/org/apache/batik/svggen/font/Point.java +38 -0
  43. data/src/org/apache/batik/svggen/font/RandomAccessFileEmulator.java +15 -0
  44. data/src/org/apache/batik/svggen/font/table/ClassDef.java +42 -0
  45. data/src/org/apache/batik/svggen/font/table/ClassDefFormat1.java +55 -0
  46. data/src/org/apache/batik/svggen/font/table/ClassDefFormat2.java +49 -0
  47. data/src/org/apache/batik/svggen/font/table/CmapFormat.java +81 -0
  48. data/src/org/apache/batik/svggen/font/table/CmapFormat0.java +60 -0
  49. data/src/org/apache/batik/svggen/font/table/CmapFormat2.java +48 -0
  50. data/src/org/apache/batik/svggen/font/table/CmapFormat4.java +147 -0
  51. data/src/org/apache/batik/svggen/font/table/CmapFormat6.java +60 -0
  52. data/src/org/apache/batik/svggen/font/table/CmapIndexEntry.java +84 -0
  53. data/src/org/apache/batik/svggen/font/table/CmapTable.java +87 -0
  54. data/src/org/apache/batik/svggen/font/table/Coverage.java +50 -0
  55. data/src/org/apache/batik/svggen/font/table/CoverageFormat1.java +59 -0
  56. data/src/org/apache/batik/svggen/font/table/CoverageFormat2.java +56 -0
  57. data/src/org/apache/batik/svggen/font/table/CvtTable.java +48 -0
  58. data/src/org/apache/batik/svggen/font/table/Device.java +63 -0
  59. data/src/org/apache/batik/svggen/font/table/DirectoryEntry.java +73 -0
  60. data/src/org/apache/batik/svggen/font/table/Feature.java +56 -0
  61. data/src/org/apache/batik/svggen/font/table/FeatureList.java +70 -0
  62. data/src/org/apache/batik/svggen/font/table/FeatureRecord.java +52 -0
  63. data/src/org/apache/batik/svggen/font/table/FeatureTags.java +30 -0
  64. data/src/org/apache/batik/svggen/font/table/FpgmTable.java +38 -0
  65. data/src/org/apache/batik/svggen/font/table/GlyfCompositeComp.java +165 -0
  66. data/src/org/apache/batik/svggen/font/table/GlyfCompositeDescript.java +160 -0
  67. data/src/org/apache/batik/svggen/font/table/GlyfDescript.java +79 -0
  68. data/src/org/apache/batik/svggen/font/table/GlyfSimpleDescript.java +155 -0
  69. data/src/org/apache/batik/svggen/font/table/GlyfTable.java +111 -0
  70. data/src/org/apache/batik/svggen/font/table/GlyphDescription.java +39 -0
  71. data/src/org/apache/batik/svggen/font/table/GposTable.java +80 -0
  72. data/src/org/apache/batik/svggen/font/table/GsubTable.java +118 -0
  73. data/src/org/apache/batik/svggen/font/table/HeadTable.java +159 -0
  74. data/src/org/apache/batik/svggen/font/table/HheaTable.java +109 -0
  75. data/src/org/apache/batik/svggen/font/table/HmtxTable.java +99 -0
  76. data/src/org/apache/batik/svggen/font/table/KernSubtable.java +58 -0
  77. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat0.java +65 -0
  78. data/src/org/apache/batik/svggen/font/table/KernSubtableFormat2.java +56 -0
  79. data/src/org/apache/batik/svggen/font/table/KernTable.java +64 -0
  80. data/src/org/apache/batik/svggen/font/table/KerningPair.java +53 -0
  81. data/src/org/apache/batik/svggen/font/table/LangSys.java +58 -0
  82. data/src/org/apache/batik/svggen/font/table/LangSysRecord.java +52 -0
  83. data/src/org/apache/batik/svggen/font/table/Ligature.java +57 -0
  84. data/src/org/apache/batik/svggen/font/table/LigatureSet.java +55 -0
  85. data/src/org/apache/batik/svggen/font/table/LigatureSubst.java +40 -0
  86. data/src/org/apache/batik/svggen/font/table/LigatureSubstFormat1.java +63 -0
  87. data/src/org/apache/batik/svggen/font/table/LocaTable.java +72 -0
  88. data/src/org/apache/batik/svggen/font/table/Lookup.java +77 -0
  89. data/src/org/apache/batik/svggen/font/table/LookupList.java +68 -0
  90. data/src/org/apache/batik/svggen/font/table/LookupSubtable.java +27 -0
  91. data/src/org/apache/batik/svggen/font/table/LookupSubtableFactory.java +31 -0
  92. data/src/org/apache/batik/svggen/font/table/MaxpTable.java +124 -0
  93. data/src/org/apache/batik/svggen/font/table/NameRecord.java +98 -0
  94. data/src/org/apache/batik/svggen/font/table/NameTable.java +67 -0
  95. data/src/org/apache/batik/svggen/font/table/Os2Table.java +232 -0
  96. data/src/org/apache/batik/svggen/font/table/Panose.java +108 -0
  97. data/src/org/apache/batik/svggen/font/table/PostTable.java +379 -0
  98. data/src/org/apache/batik/svggen/font/table/PrepTable.java +38 -0
  99. data/src/org/apache/batik/svggen/font/table/Program.java +49 -0
  100. data/src/org/apache/batik/svggen/font/table/RangeRecord.java +57 -0
  101. data/src/org/apache/batik/svggen/font/table/Script.java +72 -0
  102. data/src/org/apache/batik/svggen/font/table/ScriptList.java +78 -0
  103. data/src/org/apache/batik/svggen/font/table/ScriptRecord.java +52 -0
  104. data/src/org/apache/batik/svggen/font/table/ScriptTags.java +28 -0
  105. data/src/org/apache/batik/svggen/font/table/SingleSubst.java +47 -0
  106. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat1.java +67 -0
  107. data/src/org/apache/batik/svggen/font/table/SingleSubstFormat2.java +67 -0
  108. data/src/org/apache/batik/svggen/font/table/Table.java +204 -0
  109. data/src/org/apache/batik/svggen/font/table/TableDirectory.java +94 -0
  110. data/src/org/apache/batik/svggen/font/table/TableFactory.java +121 -0
  111. 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
+ }