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,348 @@
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 it under
7
+ * the terms of the GNU General Public License as published by the Free Software
8
+ * Foundation, either version 3 of the License, or (at your option) any later
9
+ * version.
10
+ *
11
+ * Geomerative is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ * details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along with
17
+ * Geomerative. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ package geomerative;
20
+
21
+ import processing.core.*;
22
+
23
+ import java.util.List;
24
+
25
+ /**
26
+ * RContour is a reduced interface for creating, holding and drawing contours.
27
+ * Contours are ordered lists of points (RPoint) which define the outlines of
28
+ * polygons. Contours can be self-intersecting.
29
+ *
30
+ * @eexample RContour
31
+ * @usage Geometry
32
+ * @related RPoint
33
+ * @related RPolygon
34
+ * @extended
35
+ */
36
+ public class RContour extends RGeomElem {
37
+
38
+ /**
39
+ * @invisible
40
+ */
41
+ public int type = RGeomElem.CONTOUR;
42
+
43
+ /**
44
+ * Array of RPoint objects holding the points of the contour.
45
+ *
46
+ * @eexample points
47
+ * @related RPoint
48
+ * @related countPoints ( )
49
+ * @related addPoint ( )
50
+ */
51
+ public RPoint[] points;
52
+ boolean isContributing = true;
53
+ boolean isHole = false;
54
+ boolean closed = true;
55
+
56
+ /**
57
+ * Use this method to count the number of points in the contour.
58
+ *
59
+ * @eexample countPoints
60
+ * @return int, the number points in the contour
61
+ */
62
+ public int countPoints() {
63
+ if (this.points == null) {
64
+ return 0;
65
+ }
66
+
67
+ return this.points.length;
68
+ }
69
+
70
+ /**
71
+ * Create a countour given an array of points.
72
+ *
73
+ * @param contourpoints the points of the new contour
74
+ * @invisible
75
+ */
76
+ public RContour(RPoint[] contourpoints) {
77
+ this.points = contourpoints;
78
+ }
79
+
80
+ public RContour() {
81
+ }
82
+
83
+ public RContour(RContour c) {
84
+ for (int i = 0; i < c.countPoints(); i++) {
85
+ this.append(new RPoint(c.points[i]));
86
+ }
87
+ isHole = c.isHole;
88
+ isContributing = c.isContributing;
89
+
90
+ setStyle(c);
91
+ }
92
+
93
+ /**
94
+ * Use this method to draw the contour.
95
+ *
96
+ * @eexample drawContour
97
+ * @param g PGraphics, the graphics object on which to draw the contour
98
+ */
99
+ @Override
100
+ public void draw(PGraphics g) {
101
+ int numPoints = countPoints();
102
+ boolean beforeFill = g.fill;
103
+ g.noFill();
104
+ g.beginShape();
105
+ for (int i = 0; i < numPoints; i++) {
106
+ g.vertex(points[i].x, points[i].y);
107
+ }
108
+ g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
109
+ if (beforeFill) {
110
+ g.fill(g.fillColor);
111
+ }
112
+ }
113
+
114
+ @Override
115
+ public void draw(PApplet g) {
116
+ int numPoints = countPoints();
117
+ boolean beforeFill = g.g.fill;
118
+ g.noFill();
119
+ g.beginShape();
120
+ for (int i = 0; i < numPoints; i++) {
121
+ g.vertex(points[i].x, points[i].y);
122
+ }
123
+ g.endShape(closed ? PConstants.CLOSE : PConstants.OPEN);
124
+ if (beforeFill) {
125
+ g.fill(g.g.fillColor);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Use this method to add new points to the contour.
131
+ *
132
+ * @param p
133
+ * @eexample addPoint ( )
134
+ */
135
+ public void addPoint(RPoint p) {
136
+ this.append(p);
137
+ }
138
+
139
+ public void addPoint(float x, float y) {
140
+ this.append(new RPoint(x, y));
141
+ }
142
+
143
+ /**
144
+ * Efficiently add an array of points to the contour.
145
+ *
146
+ * @param morePoints
147
+ */
148
+ public void addPoints(RPoint[] morePoints) {
149
+ if (points == null) {
150
+ this.points = morePoints;
151
+ } else {
152
+ RPoint[] newPoints = new RPoint[this.points.length + morePoints.length];
153
+ System.arraycopy(this.points, 0, newPoints, 0, this.points.length);
154
+ System.arraycopy(morePoints, 0, newPoints, this.points.length, morePoints.length);
155
+ this.points = newPoints;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Efficiently add a list of points to the contour.
161
+ *
162
+ * @param morePoints
163
+ */
164
+ public void addPoints(List<RPoint> morePoints) {
165
+ int start = 0;
166
+ if (points == null) {
167
+ this.points = new RPoint[morePoints.size()];
168
+ } else {
169
+ RPoint[] newPoints = new RPoint[this.points.length + morePoints.size()];
170
+ System.arraycopy(this.points, 0, newPoints, 0, this.points.length);
171
+ this.points = newPoints;
172
+ start = morePoints.size();
173
+ }
174
+ // it would be nice to be able to access the ArrayList's internal array!
175
+ for (int i = start, j = 0; i < points.length; i++) {
176
+ points[i] = morePoints.get(j);
177
+ j++;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Use this to return the points of the contour. It returns the points in
183
+ * the way of an array of RPoint.
184
+ *
185
+ * @eexample RContour_getHandles
186
+ * @return RPoint[], the points returned in an array.
187
+ *
188
+ */
189
+ @Override
190
+ public RPoint[] getHandles() {
191
+ return points;
192
+ }
193
+
194
+ /**
195
+ * Use this to return the points of the contour. It returns the points in
196
+ * the way of an array of RPoint.
197
+ *
198
+ * @eexample RContour_getPoints
199
+ * @return RPoint[], the points returned in an array.
200
+ *
201
+ */
202
+ @Override
203
+ public RPoint[] getPoints() {
204
+ return points;
205
+ }
206
+
207
+ /**
208
+ *
209
+ * @param t
210
+ * @return
211
+ */
212
+ @Override
213
+ public RPoint getPoint(float t) {
214
+ PApplet.println("Feature not yet implemented for this class.");
215
+ return null;
216
+ }
217
+
218
+ @Override
219
+ public RPoint getTangent(float t) {
220
+ PApplet.println("Feature not yet implemented for this class.");
221
+ return null;
222
+ }
223
+
224
+ @Override
225
+ public RPoint[] getTangents() {
226
+ PApplet.println("Feature not yet implemented for this class.");
227
+ return null;
228
+ }
229
+
230
+ @Override
231
+ public RPoint[][] getPointsInPaths() {
232
+ PApplet.println("Feature not yet implemented for this class.");
233
+ return null;
234
+ }
235
+
236
+ /**
237
+ *
238
+ * @return
239
+ */
240
+ @Override
241
+ public RPoint[][] getHandlesInPaths() {
242
+ PApplet.println("Feature not yet implemented for this class.");
243
+ return null;
244
+ }
245
+
246
+ @Override
247
+ public RPoint[][] getTangentsInPaths() {
248
+ PApplet.println("Feature not yet implemented for this class.");
249
+ return null;
250
+ }
251
+
252
+ /**
253
+ *
254
+ * @param p
255
+ * @return
256
+ */
257
+ @Override
258
+ public boolean contains(RPoint p) {
259
+ PApplet.println("Feature not yet implemented for this class.");
260
+ return false;
261
+ }
262
+
263
+ /**
264
+ * Use this method to know if the contour is a hole. Remember to use the
265
+ * method update() on the polygon before using this method.
266
+ *
267
+ * @eexample RPolygon_isHole
268
+ * @return boolean, true if it is a hole
269
+ * @related update ( )
270
+ */
271
+ public boolean isHole() {
272
+ return isHole;
273
+ }
274
+
275
+ /**
276
+ *
277
+ */
278
+ @Override
279
+ public void print() {
280
+ System.out.println("contour: ");
281
+ for (int i = 0; i < countPoints(); i++) {
282
+ System.out.println("--- point " + i + " ---");
283
+ points[i].print();
284
+ System.out.println("---------------");
285
+ }
286
+ }
287
+
288
+ public void addClose() {
289
+ if (points == null) {
290
+ return;
291
+ }
292
+
293
+ if ((points[0].x == points[points.length - 1].x) && (points[0].y == points[points.length - 1].y)) {
294
+ return;
295
+ }
296
+
297
+ addPoint(new RPoint(points[0].x, points[0].y));
298
+ closed = true;
299
+ }
300
+
301
+ /**
302
+ * @return @invisible
303
+ */
304
+ @Override
305
+ public RPolygon toPolygon() {
306
+ return new RPolygon(this);
307
+ }
308
+
309
+ /**
310
+ * @return @invisible
311
+ */
312
+ @Override
313
+ public RShape toShape() throws RuntimeException {
314
+ throw new RuntimeException("Transforming a Contour to a Shape is not yet implemented.");
315
+ }
316
+
317
+ /**
318
+ * @return @invisible
319
+ */
320
+ @Override
321
+ public RMesh toMesh() {
322
+ return this.toPolygon().toMesh();
323
+ }
324
+
325
+ /**
326
+ * Use this method to get the type of element this is.
327
+ *
328
+ * @eexample RPolygon_getType
329
+ * @return int, will allways return RGeomElem.POLYGON
330
+ */
331
+ @Override
332
+ public int getType() {
333
+ return type;
334
+ }
335
+
336
+ final void append(RPoint nextpoint) {
337
+ RPoint[] newpoints;
338
+ if (points == null) {
339
+ newpoints = new RPoint[1];
340
+ newpoints[0] = nextpoint;
341
+ } else {
342
+ newpoints = new RPoint[this.points.length + 1];
343
+ System.arraycopy(this.points, 0, newpoints, 0, this.points.length);
344
+ newpoints[this.points.length] = nextpoint;
345
+ }
346
+ this.points = newpoints;
347
+ }
348
+ }
@@ -0,0 +1,583 @@
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
+ import processing.core.*;
22
+
23
+ import org.apache.batik.svggen.font.*;
24
+ import org.apache.batik.svggen.font.table.*;
25
+
26
+ /**
27
+ * RShape is a reduced interface for creating, holding and drawing text from TrueType Font files. It's a basic interpreter of TrueType fonts enabling to access any String in the form of a group of shapes. Enabling us in this way to access their geometry.
28
+ * @eexample RFont
29
+ * @usage Geometry
30
+ * @related RGroup
31
+ *
32
+ * @extended
33
+ */
34
+ public class RFont implements PConstants{
35
+ Font f;
36
+ float scaleFactor = 0.2F;
37
+ //int scaleFactorFixed = 1;
38
+
39
+ /**
40
+ * The point size of the font.
41
+ * @eexample size
42
+ * @related setSize ( )
43
+ * @related RFont
44
+ */
45
+ public int size = DEFAULT_SIZE;
46
+
47
+ /**
48
+ * The alignment of the font. This property can take the following values: RFont.LEFT, RFont.CENTER and RFont.RIGHT
49
+ * @eexample align
50
+ * @related setAlign ( )
51
+ * @related RFont
52
+ */
53
+ public int align = DEFAULT_ALIGN;
54
+
55
+ final static int DEFAULT_SIZE = 48;
56
+ final static int DEFAULT_RESOLUTION = 72;
57
+ final static int DEFAULT_ALIGN = RFont.LEFT;
58
+
59
+ /**
60
+ * Should we try to use ASCII, rather than Unicode?
61
+ */
62
+ public boolean forceAscii = false;
63
+
64
+
65
+ /**
66
+ * The constructor of the RFont object. Use this in order to create a font with which we will be able to draw and obtain outlines of text.
67
+ * @eexample RFont
68
+ * @param fontPath String, the name of the TrueType Font file which should be situated in the data folder of the sketch.
69
+ * @param size int, the point size of the font in points.
70
+ * @param align int, this can only take the following values: RFont.LEFT, RFont.CENTER and RFont.RIGHT.
71
+ * @related toGroup ( )
72
+ * @related toShape ( )
73
+ * @related toPolygon ( )
74
+ * @related toMesh ( )
75
+ * @related draw ( )
76
+ */
77
+ public RFont(String fontPath, int size, int align) throws RuntimeException{
78
+ // Try to find the font as font path
79
+ byte[] bs = RG.parent().loadBytes(fontPath);
80
+ f = Font.create(bs);
81
+
82
+ setSize(size);
83
+ setAlign(align);
84
+ }
85
+
86
+ public RFont(String fontPath, int size) throws RuntimeException{
87
+ this(fontPath, size, DEFAULT_ALIGN);
88
+ }
89
+
90
+ public RFont(String fontPath) throws RuntimeException{
91
+ this(fontPath, DEFAULT_SIZE, DEFAULT_ALIGN);
92
+ }
93
+
94
+ /**
95
+ * Use this method to reset the point size of the font.
96
+ * @eexample setSize
97
+ * @param size int, the point size of the font in points.
98
+ * @related size
99
+ * @related RFont
100
+ */
101
+ public void setSize(int size){
102
+ short unitsPerEm = f.getHeadTable().getUnitsPerEm();
103
+ int resolution = RG.dpi();
104
+ this.scaleFactor = ((float)size * (float)resolution) / (72F * (float)unitsPerEm);
105
+ //this.scaleFactorFixed = (int)(this.scaleFactor * 65536F);
106
+ //System.out.println(scaleFactor);
107
+ //System.out.println(scaleFactorFixed);
108
+ }
109
+
110
+ public float getLineSpacing() {
111
+ // More info at:
112
+ // http://fontforge.sourceforge.net/faq.html#linespace
113
+ // http://typophile.com/node/13081
114
+ short unitsPerEm = f.getHeadTable().getUnitsPerEm();
115
+ System.out.println("UnitsPerEm (emsize): " + unitsPerEm);
116
+
117
+ // HHEA table method:
118
+ float hheaLineGap = (f.getHheaTable().getAscender() - f.getHheaTable().getDescender() + f.getHheaTable().getLineGap()) * this.scaleFactor;
119
+ System.out.println("HHEA lineGap: " + hheaLineGap);
120
+
121
+ // OS2 table typographic line gap method:
122
+ float os2TypoLineGap = (f.getOS2Table().getTypoAscender() - f.getOS2Table().getTypoDescender() + f.getOS2Table().getTypoLineGap()) * this.scaleFactor;
123
+ System.out.println("Os2 Typo lineGap: " + os2TypoLineGap);
124
+
125
+ // OS2 table win line gap method:
126
+ float os2WinLineGap = (f.getOS2Table().getWinAscent() + f.getOS2Table().getWinDescent()) * this.scaleFactor;
127
+ System.out.println("Os2 Win lineGap: " + os2WinLineGap);
128
+
129
+ // Automatic calculation
130
+ float autoLineGap = f.getHeadTable().getUnitsPerEm() * 1.25f * this.scaleFactor;
131
+ System.out.println("Automatic lineGap: " + autoLineGap);
132
+
133
+ return hheaLineGap;
134
+ }
135
+
136
+ /**
137
+ * Use this method to reset the alignment of the font. This property can take the following values: RFont.LEFT, RFont.CENTER and RFont.RIGHT
138
+ * @eexample setAlign
139
+ * @param align int, this can only take the following values: RFont.LEFT, RFont.CENTER and RFont.RIGHT.
140
+ * @related align
141
+ * @related RFont
142
+ */
143
+ public void setAlign(int align) throws RuntimeException{
144
+ if(align!=LEFT && align!=CENTER && align!=RIGHT){
145
+ throw new RuntimeException("Alignment unknown. The only accepted values are: RFont.LEFT, RFont.CENTER and RFont.RIGHT");
146
+ }
147
+ this.align = align;
148
+ }
149
+
150
+ /**
151
+ * @invisible
152
+ **/
153
+ public String getFamily(){
154
+ return f.getNameTable().getRecord(org.apache.batik.svggen.font.table.Table.nameFontFamilyName);
155
+ }
156
+
157
+ /**
158
+ * Use this method to get the outlines of a character in the form of an RShape.
159
+ * @eexample RFont_toShape
160
+ * @param character char, the character we want the outline from.
161
+ * @return RShape, the outline of the character.
162
+ * @related toGroup ( )
163
+ * @related toPolygon ( )
164
+ * @related draw ( )
165
+ */
166
+ public RShape toShape(char character){
167
+ RGroup grp = toGroup(Character.toString(character));
168
+ if(grp.countElements()>0) return (RShape)(grp.elements[0]);
169
+ return new RShape();
170
+ }
171
+
172
+ /**
173
+ * Use this method to get the outlines of a character in the form of an RPolygon.
174
+ * @eexample RFont_toPolygon
175
+ * @param character char, the character we want the outline from.
176
+ * @return RPolygon, the outline of the character.
177
+ * @related toGroup ( )
178
+ * @related toShape ( )
179
+ * @related draw ( )
180
+ */
181
+ public RPolygon toPolygon(char character) {
182
+ return toShape(character).toPolygon();
183
+ }
184
+
185
+
186
+ private CmapFormat getCmapFormat() {
187
+ if (forceAscii) {
188
+ // We've been asked to use the ASCII/Macintosh cmap format
189
+ return f.getCmapTable().getCmapFormat(
190
+ org.apache.batik.svggen.font.table.Table.platformMacintosh,
191
+ org.apache.batik.svggen.font.table.Table.encodingRoman );
192
+ } else {
193
+ short[] platforms = new short[] {
194
+ org.apache.batik.svggen.font.table.Table.platformMicrosoft,
195
+ org.apache.batik.svggen.font.table.Table.platformAppleUnicode,
196
+ org.apache.batik.svggen.font.table.Table.platformMacintosh
197
+ };
198
+ short[] encodings = new short[] {
199
+ org.apache.batik.svggen.font.table.Table.encodingUGL,
200
+ org.apache.batik.svggen.font.table.Table.encodingKorean,
201
+ org.apache.batik.svggen.font.table.Table.encodingHebrew,
202
+ org.apache.batik.svggen.font.table.Table.encodingUndefined
203
+ };
204
+
205
+ CmapFormat cmapFmt;
206
+ for(int i = 0; i < encodings.length; i++) {
207
+ for(int j = 0; j < platforms.length; j++) {
208
+
209
+ cmapFmt = f.getCmapTable().getCmapFormat(platforms[j], encodings[i]);
210
+ if (cmapFmt != null) {
211
+ return cmapFmt;
212
+ }
213
+ }
214
+ }
215
+ return null;
216
+ }
217
+ }
218
+
219
+
220
+ /**
221
+ * Use this method to get the outlines of a string in the form of an RGroup. All the elements of the group will be RShapes.
222
+ * @eexample RFont_toGroup
223
+ * @param text String, the string we want the outlines from.
224
+ * @return RGroup, the group of outlines of the character. All the elements are RShapes.
225
+ * @related toShape ( )
226
+ * @related draw ( )
227
+ */
228
+ public RGroup toGroup(String text) throws RuntimeException{
229
+ RGroup result = new RGroup();
230
+
231
+ // Decide upon a cmap table to use for our character to glyph look-up
232
+ CmapFormat cmapFmt = getCmapFormat();
233
+
234
+ if (cmapFmt == null) {
235
+ throw new RuntimeException("Cannot find a suitable cmap table");
236
+ }
237
+
238
+ // If this font includes arabic script, we want to specify
239
+ // substitutions for initial, medial, terminal & isolated
240
+ // cases.
241
+ /*
242
+ GsubTable gsub = (GsubTable) f.getTable(Table.GSUB);
243
+ SingleSubst initialSubst = null;
244
+ SingleSubst medialSubst = null;
245
+ SingleSubst terminalSubst = null;
246
+ if (gsub != null) {
247
+ Script s = gsub.getScriptList().findScript(ScriptTags.SCRIPT_TAG_ARAB);
248
+ if (s != null) {
249
+ LangSys ls = s.getDefaultLangSys();
250
+ if (ls != null) {
251
+ Feature init = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_INIT);
252
+ Feature medi = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_MEDI);
253
+ Feature fina = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_FINA);
254
+
255
+ initialSubst = (SingleSubst)
256
+ gsub.getLookupList().getLookup(init, 0).getSubtable(0);
257
+ medialSubst = (SingleSubst)
258
+ gsub.getLookupList().getLookup(medi, 0).getSubtable(0);
259
+ terminalSubst = (SingleSubst)
260
+ gsub.getLookupList().getLookup(fina, 0).getSubtable(0);
261
+ }
262
+ }
263
+ }*/
264
+
265
+ int x = 0;
266
+ for (short i = 0; i < text.length(); i++) {
267
+ int glyphIndex = cmapFmt.mapCharCode(text.charAt(i));
268
+ Glyph glyph = f.getGlyph(glyphIndex);
269
+ int default_advance_x = f.getHmtxTable().getAdvanceWidth(glyphIndex);
270
+ if (glyph != null) {
271
+ glyph.scale(scaleFactor);
272
+ // Add the Glyph to the Shape with an horizontal offset of x
273
+ result.addElement(getGlyphAsShape(f,glyph, glyphIndex,x));
274
+ x += glyph.getAdvanceWidth();
275
+ }else{
276
+ x += (int)((float)default_advance_x*scaleFactor);
277
+ }
278
+
279
+ }
280
+
281
+ if(align!=LEFT && align!=CENTER && align!=RIGHT){
282
+ throw new RuntimeException("Alignment unknown. The only accepted values are: RFont.LEFT, RFont.CENTER and RFont.RIGHT");
283
+ }
284
+
285
+ RRectangle r;
286
+ RMatrix mattrans;
287
+
288
+ switch(this.align){
289
+ case RFont.CENTER:
290
+ r = result.getBounds();
291
+ mattrans = new RMatrix();
292
+ mattrans.translate((r.getMinX()-r.getMaxX())/2,0);
293
+ result.transform(mattrans);
294
+ break;
295
+ case RFont.RIGHT:
296
+ r = result.getBounds();
297
+ mattrans = new RMatrix();
298
+ mattrans.translate((r.getMinX()-r.getMaxX()),0);
299
+ result.transform(mattrans);
300
+ break;
301
+ case RFont.LEFT:
302
+ break;
303
+ }
304
+ return result;
305
+ }
306
+
307
+ public RShape toShape(String text) throws RuntimeException{
308
+ RShape result = new RShape();
309
+
310
+ // Decide upon a cmap table to use for our character to glyph look-up
311
+ CmapFormat cmapFmt = getCmapFormat();
312
+
313
+ if (cmapFmt == null) {
314
+ throw new RuntimeException("Cannot find a suitable cmap table");
315
+ }
316
+
317
+ // If this font includes arabic script, we want to specify
318
+ // substitutions for initial, medial, terminal & isolated
319
+ // cases.
320
+ /*
321
+ GsubTable gsub = (GsubTable) f.getTable(Table.GSUB);
322
+ SingleSubst initialSubst = null;
323
+ SingleSubst medialSubst = null;
324
+ SingleSubst terminalSubst = null;
325
+ if (gsub != null) {
326
+ Script s = gsub.getScriptList().findScript(ScriptTags.SCRIPT_TAG_ARAB);
327
+ if (s != null) {
328
+ LangSys ls = s.getDefaultLangSys();
329
+ if (ls != null) {
330
+ Feature init = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_INIT);
331
+ Feature medi = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_MEDI);
332
+ Feature fina = gsub.getFeatureList().findFeature(ls, FeatureTags.FEATURE_TAG_FINA);
333
+
334
+ initialSubst = (SingleSubst)
335
+ gsub.getLookupList().getLookup(init, 0).getSubtable(0);
336
+ medialSubst = (SingleSubst)
337
+ gsub.getLookupList().getLookup(medi, 0).getSubtable(0);
338
+ terminalSubst = (SingleSubst)
339
+ gsub.getLookupList().getLookup(fina, 0).getSubtable(0);
340
+ }
341
+ }
342
+ }*/
343
+
344
+ int x = 0;
345
+ for (short i = 0; i < text.length(); i++) {
346
+ int glyphIndex = cmapFmt.mapCharCode(text.charAt(i));
347
+ Glyph glyph = f.getGlyph(glyphIndex);
348
+ int default_advance_x = f.getHmtxTable().getAdvanceWidth(glyphIndex);
349
+ if (glyph != null) {
350
+ glyph.scale(scaleFactor);
351
+ // Add the Glyph to the Shape with an horizontal offset of x
352
+ result.addChild(getGlyphAsShape(f,glyph, glyphIndex,x));
353
+ x += glyph.getAdvanceWidth();
354
+ }else{
355
+ x += (int)((float)default_advance_x*scaleFactor);
356
+ }
357
+
358
+ }
359
+
360
+ if(align!=LEFT && align!=CENTER && align!=RIGHT){
361
+ throw new RuntimeException("Alignment unknown. The only accepted values are: RFont.LEFT, RFont.CENTER and RFont.RIGHT");
362
+ }
363
+
364
+ RRectangle r;
365
+ RMatrix mattrans;
366
+
367
+ switch(this.align){
368
+ case RFont.CENTER:
369
+ r = result.getBounds();
370
+ mattrans = new RMatrix();
371
+ mattrans.translate((r.getMinX()-r.getMaxX())/2,0);
372
+ result.transform(mattrans);
373
+ break;
374
+ case RFont.RIGHT:
375
+ r = result.getBounds();
376
+ mattrans = new RMatrix();
377
+ mattrans.translate((r.getMinX()-r.getMaxX()),0);
378
+ result.transform(mattrans);
379
+ break;
380
+ case RFont.LEFT:
381
+ break;
382
+ }
383
+ return result;
384
+ }
385
+
386
+ /**
387
+ * Use this method to draw a character on a certain canvas.
388
+ * @eexample RFont_draw
389
+ * @param character the character to be drawn
390
+ * @param g the canvas where to draw
391
+ * @related toShape ( )
392
+ * @related toGroup ( )
393
+ */
394
+ public void draw(char character, PGraphics g) throws RuntimeException{
395
+ this.toShape(character).draw(g);
396
+ }
397
+
398
+ /**
399
+ * Use this method to draw a character on a certain canvas.
400
+ * @eexample RFont_draw
401
+ * @param text the string to be drawn
402
+ * @param g the canvas where to draw
403
+ * @related toShape ( )
404
+ * @related toGroup ( )
405
+ */
406
+ public void draw(String text, PGraphics g) throws RuntimeException{
407
+ this.toGroup(text).draw(g);
408
+ }
409
+
410
+ /**
411
+ * Use this method to draw a character on a certain canvas.
412
+ * @eexample RFont_draw
413
+ * @param character char, the character to be drawn
414
+ * @param g the canvas where to draw
415
+ * @related toShape ( )
416
+ * @related toGroup ( )
417
+ */
418
+ public void draw(char character, PApplet g) throws RuntimeException{
419
+ this.toShape(character).draw(g);
420
+ }
421
+
422
+ /**
423
+ * Use this method to draw a character on a certain canvas.
424
+ * @eexample RFont_draw
425
+ * @param text the string to be drawn
426
+ * @param g the canvas where to draw
427
+ * @related toShape ( )
428
+ * @related toGroup ( )
429
+ */
430
+ public void draw(String text, PApplet g) throws RuntimeException{
431
+ this.toGroup(text).draw(g);
432
+ }
433
+
434
+ public void draw(String text) throws RuntimeException{
435
+ this.toGroup(text).draw();
436
+ }
437
+
438
+ public void draw(char character) throws RuntimeException{
439
+ this.toShape(character).draw();
440
+ }
441
+
442
+
443
+
444
+ private static float midValue(float a, float b) {
445
+ return a + (b - a)/2;
446
+ }
447
+
448
+ protected static RShape getContourAsShape(Glyph glyph, int startIndex, int count) {
449
+ return getContourAsShape(glyph, startIndex, count, 0);
450
+ }
451
+
452
+ protected static RShape getContourAsShape(Glyph glyph, int startIndex, int count, float xadv) {
453
+
454
+ // If this is a single point on it's own, weSystem.out.println("Value of pointx: "+pointx); can't do anything with it
455
+ if (glyph.getPoint(startIndex).endOfContour) {
456
+ return new RShape();
457
+ }
458
+
459
+ RShape result = new RShape();
460
+ int offset = 0;
461
+ //float originx = 0F,originy = 0F;
462
+
463
+ while (offset < count) {
464
+ Point point = glyph.getPoint(startIndex + offset%count);
465
+ Point point_plus1 = glyph.getPoint(startIndex + (offset+1)%count);
466
+ Point point_plus2 = glyph.getPoint(startIndex + (offset+2)%count);
467
+
468
+ float pointx = ((float)point.x + xadv);
469
+ float pointy = ((float)point.y);
470
+ float point_plus1x = ((float)point_plus1.x + xadv);
471
+ float point_plus1y = ((float)point_plus1.y);
472
+ float point_plus2x = ((float)point_plus2.x + xadv);
473
+ float point_plus2y = ((float)point_plus2.y);
474
+
475
+ if (offset == 0) {
476
+ // move command
477
+ result.addMoveTo(pointx,pointy);
478
+ }
479
+
480
+ if (point.onCurve && point_plus1.onCurve) {
481
+ // line command
482
+ result.addLineTo(point_plus1x,point_plus1y);
483
+ offset++;
484
+ } else if (point.onCurve && !point_plus1.onCurve && point_plus2.onCurve) {
485
+ // This is a curve with no implied points
486
+ // quadratic bezier command
487
+ result.addQuadTo(point_plus1x, point_plus1y, point_plus2x, point_plus2y);
488
+ offset+=2;
489
+ } else if (point.onCurve && !point_plus1.onCurve && !point_plus2.onCurve) {
490
+ // This is a curve with one implied point
491
+ // quadratic bezier command avec le endPoint implicit
492
+ result.addQuadTo(point_plus1x, point_plus1y, midValue(point_plus1x, point_plus2x), midValue(point_plus1y, point_plus2y));
493
+ offset+=2;
494
+ } else if (!point.onCurve && !point_plus1.onCurve) {
495
+ // This is a curve with two implied points
496
+ // quadratic bezier with
497
+ result.addQuadTo(pointx, pointy, midValue(pointx, point_plus1x), midValue(pointy, point_plus1y));
498
+ offset++;
499
+ } else if (!point.onCurve && point_plus1.onCurve) {
500
+ // This is a curve with no implied points
501
+ result.addQuadTo(pointx, pointy, point_plus1x, point_plus1y);
502
+ offset++;
503
+ } else {
504
+ System.out.println("drawGlyph case not catered for!!");
505
+ break;
506
+ }
507
+ }
508
+ result.addClose();
509
+ return result;
510
+ }
511
+
512
+ protected static RShape getGlyphAsShape(Font font, Glyph glyph, int glyphIndex) {
513
+ return getGlyphAsShape(font,glyph,glyphIndex,0);
514
+ }
515
+
516
+ protected static RShape getGlyphAsShape(Font font, Glyph glyph, int glyphIndex,float xadv) {
517
+
518
+ RShape result = new RShape();
519
+ int firstIndex = 0;
520
+ int count = 0;
521
+ int i;
522
+
523
+ if (glyph != null) {
524
+ for (i = 0; i < glyph.getPointCount(); i++) {
525
+ count++;
526
+ if (glyph.getPoint(i).endOfContour) {
527
+ result.addShape(getContourAsShape(glyph, firstIndex, count, xadv));
528
+ firstIndex = i + 1;
529
+ count = 0;
530
+ }
531
+ }
532
+ }
533
+
534
+ return result;
535
+ }
536
+
537
+ protected static RShape getGlyphAsShape(Font font, Glyph glyph, int glyphIndex, SingleSubst arabInitSubst, SingleSubst arabMediSubst, SingleSubst arabTermSubst) {
538
+ return getGlyphAsShape(font, glyph, glyphIndex, arabInitSubst, arabMediSubst, arabTermSubst, 0);
539
+ }
540
+
541
+ protected static RShape getGlyphAsShape(Font font, Glyph glyph, int glyphIndex, SingleSubst arabInitSubst, SingleSubst arabMediSubst, SingleSubst arabTermSubst, float xadv) {
542
+
543
+ RShape result = new RShape();
544
+ boolean substituted = false;
545
+
546
+ // arabic = "initial | medial | terminal | isolated"
547
+ int arabInitGlyphIndex = glyphIndex;
548
+ int arabMediGlyphIndex = glyphIndex;
549
+ int arabTermGlyphIndex = glyphIndex;
550
+ if (arabInitSubst != null) {
551
+ arabInitGlyphIndex = arabInitSubst.substitute(glyphIndex);
552
+ }
553
+ if (arabMediSubst != null) {
554
+ arabMediGlyphIndex = arabMediSubst.substitute(glyphIndex);
555
+ }
556
+ if (arabTermSubst != null) {
557
+ arabTermGlyphIndex = arabTermSubst.substitute(glyphIndex);
558
+ }
559
+
560
+ if (arabInitGlyphIndex != glyphIndex) {
561
+ result.addShape(getGlyphAsShape(font,font.getGlyph(arabInitGlyphIndex),arabInitGlyphIndex));
562
+ substituted = true;
563
+ }
564
+
565
+ if (arabMediGlyphIndex != glyphIndex) {
566
+ result.addShape(getGlyphAsShape(font,font.getGlyph(arabMediGlyphIndex),arabMediGlyphIndex));
567
+ substituted = true;
568
+ }
569
+
570
+ if (arabTermGlyphIndex != glyphIndex) {
571
+ result.addShape(getGlyphAsShape(font,font.getGlyph(arabTermGlyphIndex),arabTermGlyphIndex));
572
+ substituted = true;
573
+ }
574
+
575
+ if (substituted) {
576
+ result.addShape(getGlyphAsShape(font,glyph,glyphIndex));
577
+ } else {
578
+ result.addShape(getGlyphAsShape(font,glyph,glyphIndex));
579
+ }
580
+
581
+ return result;
582
+ }
583
+ }