swfmill 0.0.1

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 (131) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/.swfmill +240 -0
  4. data/LICENSE +340 -0
  5. data/README.rdoc +37 -0
  6. data/Rakefile +59 -0
  7. data/VERSION +1 -0
  8. data/ext/.gitignore +5 -0
  9. data/ext/extconf.rb +86 -0
  10. data/ext/swfmill/.gitignore +27 -0
  11. data/ext/swfmill/AUTHORS +9 -0
  12. data/ext/swfmill/COPYING +340 -0
  13. data/ext/swfmill/Makefile.am +14 -0
  14. data/ext/swfmill/Makefile.in +635 -0
  15. data/ext/swfmill/NEWS +189 -0
  16. data/ext/swfmill/README +170 -0
  17. data/ext/swfmill/TODO +33 -0
  18. data/ext/swfmill/aclocal.m4 +7712 -0
  19. data/ext/swfmill/autogen.sh +7 -0
  20. data/ext/swfmill/compile +142 -0
  21. data/ext/swfmill/config.guess +1516 -0
  22. data/ext/swfmill/config.sub +1626 -0
  23. data/ext/swfmill/configure +21868 -0
  24. data/ext/swfmill/configure.ac +55 -0
  25. data/ext/swfmill/depcomp +589 -0
  26. data/ext/swfmill/install-sh +519 -0
  27. data/ext/swfmill/ltmain.sh +6964 -0
  28. data/ext/swfmill/missing +367 -0
  29. data/ext/swfmill/src/Geom.cpp +107 -0
  30. data/ext/swfmill/src/Geom.h +100 -0
  31. data/ext/swfmill/src/Makefile.am +86 -0
  32. data/ext/swfmill/src/Makefile.in +1025 -0
  33. data/ext/swfmill/src/SWF.h +11941 -0
  34. data/ext/swfmill/src/SWFAction.cpp +41 -0
  35. data/ext/swfmill/src/SWFAction.h +19 -0
  36. data/ext/swfmill/src/SWFBasic.h +7 -0
  37. data/ext/swfmill/src/SWFFile.cpp +406 -0
  38. data/ext/swfmill/src/SWFFile.h +34 -0
  39. data/ext/swfmill/src/SWFFilter.cpp +25 -0
  40. data/ext/swfmill/src/SWFFilter.h +15 -0
  41. data/ext/swfmill/src/SWFGlyphList.cpp +262 -0
  42. data/ext/swfmill/src/SWFGlyphList.h +34 -0
  43. data/ext/swfmill/src/SWFIdItem.h +85 -0
  44. data/ext/swfmill/src/SWFIdItems.h +16 -0
  45. data/ext/swfmill/src/SWFItem.cpp +235 -0
  46. data/ext/swfmill/src/SWFItem.h +60 -0
  47. data/ext/swfmill/src/SWFList.h +179 -0
  48. data/ext/swfmill/src/SWFReader.cpp +352 -0
  49. data/ext/swfmill/src/SWFReader.h +73 -0
  50. data/ext/swfmill/src/SWFShapeItem.cpp +220 -0
  51. data/ext/swfmill/src/SWFShapeItem.h +45 -0
  52. data/ext/swfmill/src/SWFShapeMaker.cpp +401 -0
  53. data/ext/swfmill/src/SWFShapeMaker.h +128 -0
  54. data/ext/swfmill/src/SWFTag.cpp +49 -0
  55. data/ext/swfmill/src/SWFTag.h +20 -0
  56. data/ext/swfmill/src/SWFTrait.cpp +35 -0
  57. data/ext/swfmill/src/SWFTrait.h +22 -0
  58. data/ext/swfmill/src/SWFWriter.cpp +312 -0
  59. data/ext/swfmill/src/SWFWriter.h +84 -0
  60. data/ext/swfmill/src/base64.c +110 -0
  61. data/ext/swfmill/src/base64.h +15 -0
  62. data/ext/swfmill/src/codegen/Makefile.am +15 -0
  63. data/ext/swfmill/src/codegen/Makefile.in +346 -0
  64. data/ext/swfmill/src/codegen/basic.xsl +45 -0
  65. data/ext/swfmill/src/codegen/basics.xsl +235 -0
  66. data/ext/swfmill/src/codegen/dumper.xsl +109 -0
  67. data/ext/swfmill/src/codegen/header.xsl +131 -0
  68. data/ext/swfmill/src/codegen/mk.xsl +26 -0
  69. data/ext/swfmill/src/codegen/parser.xsl +196 -0
  70. data/ext/swfmill/src/codegen/parsexml.xsl +312 -0
  71. data/ext/swfmill/src/codegen/size.xsl +189 -0
  72. data/ext/swfmill/src/codegen/source.xml +2197 -0
  73. data/ext/swfmill/src/codegen/writer.xsl +190 -0
  74. data/ext/swfmill/src/codegen/writexml.xsl +138 -0
  75. data/ext/swfmill/src/swfmill.cpp +482 -0
  76. data/ext/swfmill/src/swft/Makefile.am +55 -0
  77. data/ext/swfmill/src/swft/Makefile.in +717 -0
  78. data/ext/swfmill/src/swft/Parser.cpp +76 -0
  79. data/ext/swfmill/src/swft/Parser.h +37 -0
  80. data/ext/swfmill/src/swft/SVGAttributeParser.cpp +78 -0
  81. data/ext/swfmill/src/swft/SVGAttributeParser.h +35 -0
  82. data/ext/swfmill/src/swft/SVGColor.cpp +116 -0
  83. data/ext/swfmill/src/swft/SVGColor.h +37 -0
  84. data/ext/swfmill/src/swft/SVGColors.h +167 -0
  85. data/ext/swfmill/src/swft/SVGGradient.cpp +258 -0
  86. data/ext/swfmill/src/swft/SVGGradient.h +81 -0
  87. data/ext/swfmill/src/swft/SVGPathParser.cpp +155 -0
  88. data/ext/swfmill/src/swft/SVGPathParser.h +126 -0
  89. data/ext/swfmill/src/swft/SVGPointsParser.cpp +51 -0
  90. data/ext/swfmill/src/swft/SVGPointsParser.h +25 -0
  91. data/ext/swfmill/src/swft/SVGStyle.cpp +181 -0
  92. data/ext/swfmill/src/swft/SVGStyle.h +80 -0
  93. data/ext/swfmill/src/swft/SVGTransformParser.cpp +72 -0
  94. data/ext/swfmill/src/swft/SVGTransformParser.h +32 -0
  95. data/ext/swfmill/src/swft/readpng.c +305 -0
  96. data/ext/swfmill/src/swft/readpng.h +92 -0
  97. data/ext/swfmill/src/swft/swft.cpp +251 -0
  98. data/ext/swfmill/src/swft/swft.h +64 -0
  99. data/ext/swfmill/src/swft/swft_document.cpp +57 -0
  100. data/ext/swfmill/src/swft/swft_import.cpp +38 -0
  101. data/ext/swfmill/src/swft/swft_import_binary.cpp +82 -0
  102. data/ext/swfmill/src/swft/swft_import_jpeg.cpp +255 -0
  103. data/ext/swfmill/src/swft/swft_import_mp3.cpp +268 -0
  104. data/ext/swfmill/src/swft/swft_import_png.cpp +231 -0
  105. data/ext/swfmill/src/swft/swft_import_ttf.cpp +519 -0
  106. data/ext/swfmill/src/swft/swft_import_wav.cpp +255 -0
  107. data/ext/swfmill/src/swft/swft_path.cpp +178 -0
  108. data/ext/swfmill/src/xslt/Makefile.am +51 -0
  109. data/ext/swfmill/src/xslt/Makefile.in +536 -0
  110. data/ext/swfmill/src/xslt/README +19 -0
  111. data/ext/swfmill/src/xslt/assemble.xsl +38 -0
  112. data/ext/swfmill/src/xslt/simple-deprecated.xslt +62 -0
  113. data/ext/swfmill/src/xslt/simple-elements.xslt +627 -0
  114. data/ext/swfmill/src/xslt/simple-import.xslt +565 -0
  115. data/ext/swfmill/src/xslt/simple-svg.xslt +383 -0
  116. data/ext/swfmill/src/xslt/simple-tools.xslt +255 -0
  117. data/ext/swfmill/src/xslt/simple.cpp +1686 -0
  118. data/ext/swfmill/src/xslt/simple.xml +7 -0
  119. data/ext/swfmill/src/xslt/xslt.h +7 -0
  120. data/ext/swfmill/test/Makefile.am +1 -0
  121. data/ext/swfmill/test/Makefile.in +490 -0
  122. data/ext/swfmill/test/xml/Makefile.am +20 -0
  123. data/ext/swfmill/test/xml/Makefile.in +353 -0
  124. data/ext/swfmill/test/xml/test-xml +21 -0
  125. data/ext/swfmill_ext.cc +375 -0
  126. data/lib/swfmill.rb +30 -0
  127. data/spec/data/swfmill-banner1.swf +0 -0
  128. data/spec/spec.opts +1 -0
  129. data/spec/spec_helper.rb +14 -0
  130. data/spec/swfmill_spec.rb +125 -0
  131. metadata +206 -0
@@ -0,0 +1,45 @@
1
+ #ifndef SWF_SHAPEITEM_H
2
+ #define SWF_SHAPEITEM_H
3
+
4
+ #include <SWFItem.h>
5
+
6
+ namespace SWF {
7
+
8
+ class ShapeItem : public Item {
9
+ public:
10
+ ShapeItem();
11
+ void setType( unsigned char t ) { type = t; }
12
+ unsigned char type;
13
+
14
+ int getHeaderSize( int size );
15
+ void writeHeader( Writer *w, Context *ctx, size_t len );
16
+
17
+ bool isEnd();
18
+
19
+ // static stuff
20
+ public:
21
+ static ShapeItem* get( Reader *r, int end, Context *ctx );
22
+ static ShapeItem* getByName( const char *name );
23
+ };
24
+
25
+ class LineTo : public ShapeItem {
26
+ /* plain edges are a bit hairy, so we do them manually */
27
+ public:
28
+ LineTo();
29
+ virtual bool parse( Reader *r, int end, Context *ctx );
30
+ virtual void dump( int indent, Context *ctx );
31
+ virtual size_t calcSize( Context *ctx, int start_at );
32
+ virtual void write( Writer *w, Context *ctx );
33
+ virtual void writeXML( xmlNodePtr node, Context *ctx );
34
+ virtual void parseXML( xmlNodePtr node, Context *ctx );
35
+
36
+ void setx( int x );
37
+ void sety( int y );
38
+
39
+ protected:
40
+ int bits;
41
+ int x, y;
42
+ };
43
+
44
+ }
45
+ #endif
@@ -0,0 +1,401 @@
1
+ #include "SWFShapeMaker.h"
2
+ #include <stdarg.h>
3
+ #include "SWFShapeItem.h"
4
+ #include "SWFItem.h"
5
+ #include "SWF.h"
6
+
7
+ #define TMP_STRLEN 0xFF
8
+
9
+ namespace SWF {
10
+
11
+ // TODO assure bits is representable in 4 bits!
12
+ ShapeMaker::ShapeMaker( List<ShapeItem>* e, double fx, double fy, double ofsx, double ofsy ) {
13
+ edges = e;
14
+ factorx = fx;
15
+ factory = fy;
16
+ offsetx = ofsx;
17
+ offsety = ofsy;
18
+ diffx = diffy = 0;
19
+ lastx = lasty = 0;
20
+ smoothx = smoothy = 0;
21
+ have_first = false;
22
+
23
+ fillStyle0 = lineStyle = fillStyle1 = -1;
24
+
25
+ roundReset();
26
+ }
27
+
28
+ void ShapeMaker::doSetup( double _x, double _y, bool hasMoveTo, int _fillStyle0, int _fillStyle1, int _lineStyle ) {
29
+ // append shapesetup (whithout styles, this is glyph only for now)
30
+ ShapeSetup *setup = new ShapeSetup;
31
+
32
+
33
+ if( _fillStyle0 != -1 ) {
34
+ setup->setfillStyle0( _fillStyle0 );
35
+ setup->sethasFillStyle0( 1 );
36
+ }
37
+ if( _fillStyle1 != -1 ) {
38
+ setup->setfillStyle1( _fillStyle1 );
39
+ setup->sethasFillStyle1( 1 );
40
+ }
41
+ if( _lineStyle != -1 ) {
42
+ setup->setlineStyle( _lineStyle );
43
+ setup->sethasLineStyle( 1 );
44
+ }
45
+
46
+ if( hasMoveTo ) {
47
+ roundReset();
48
+ int x = roundX(factorx * ( _x ) );
49
+ int y = roundY(factory * ( _y ) );
50
+
51
+ diffx = diffy = 0;
52
+
53
+ setup->setxybits( SWFMaxBitsNeeded( true, 2, x, y ) );
54
+
55
+ setup->sethasMoveTo( 1 );
56
+ setup->setx( x );
57
+ setup->sety( y );
58
+
59
+ minmax( x, y );
60
+
61
+ lastx = _x; lasty = _y;
62
+ lastsetupx = _x; lastsetupy = _y;
63
+ }
64
+
65
+ edges->append( setup );
66
+
67
+ // fprintf(stderr,"setup %i/%i\n", x, y );
68
+ }
69
+
70
+ void ShapeMaker::lineToR( double _x, double _y ) {
71
+ int x = roundX(factorx * ( _x ) );
72
+ int y = roundY(factory * ( _y ) );
73
+
74
+ diffx += x; diffy += y;
75
+
76
+ SWF::LineTo *segment = new SWF::LineTo;
77
+ segment->setType(1);
78
+ //segment->setbits( maxBitsNeeded( true, 2, x, y ) );
79
+ segment->setx( x );
80
+ segment->sety( y );
81
+ edges->append( segment );
82
+ minmax( x+(lastx*factorx), y+(lasty*factory) );
83
+
84
+ lastx += _x; lasty += _y;
85
+ }
86
+
87
+ void ShapeMaker::curveToR( double _cx, double _cy, double ax, double ay ) {
88
+ int cx = roundX(factorx * ( _cx ) );
89
+ int cy = roundY(factory * ( _cy ) );
90
+ int x = roundX(factorx * ( ax - _cx ) );
91
+ int y = roundY(factory * ( ay - _cy) );
92
+
93
+ smoothx = lastx + _cx;
94
+ smoothy = lasty + _cy;
95
+
96
+ diffx += cx + x; diffy += cy + y;
97
+
98
+ CurveTo *segment = new CurveTo;
99
+ segment->setType(2);
100
+ segment->setbits( SWFMaxBitsNeeded( true, 4, x, y, cx, cy ) );
101
+ segment->setx1( cx );
102
+ segment->sety1( cy );
103
+ segment->setx2( x );
104
+ segment->sety2( y );
105
+ edges->append( segment );
106
+ minmax( x+cx+(lastx*factorx), y+cy+(lasty*factory) );
107
+
108
+ lastx += ax; lasty += ay;
109
+
110
+ smoothx = ax - _cx;
111
+ smoothy = ay - _cy;
112
+ }
113
+
114
+ void ShapeMaker::curveTo( double cx, double cy, double ax, double ay ) {
115
+ curveToR( cx - lastx, cy - lasty, ax - lastx, ay - lasty );
116
+ }
117
+
118
+ void ShapeMaker::smoothCurveToR( double ax, double ay ) {
119
+ curveToR( smoothx, smoothy, ax, ay );
120
+
121
+ }
122
+
123
+ void ShapeMaker::smoothCurveTo( double ax, double ay ) {
124
+ curveTo( lastx + smoothx, lasty + smoothy, ax, ay );
125
+ }
126
+
127
+ // cubic to quadratic bezier functions
128
+ // thanks to Robert Penner
129
+
130
+ Point intersectLines( Point p1, Point p2, Point p3, Point p4 ) {
131
+ double x1 = p1.x, y1 = p1.y;
132
+ double x4 = p4.x, y4 = p4.y;
133
+ double dx1 = p2.x-x1;
134
+ double dx2 = p3.x-x4;
135
+ if( dx1 == 0 && dx2 == 0 ) return Point(p1.x + ((p4.x-p1.x)/2), p1.y + ((p4.y-p1.y)/2));
136
+ double m1 = (p2.y-y1)/dx1;
137
+ double m2 = (p3.y-y4)/dx2;
138
+
139
+ if( !dx1 ) {
140
+ return Point( x1, (m2*(x1-x4))+y4 );
141
+ } else if( !dx2 ) {
142
+ return Point( x4, (m1*(x4-x1))+y1 );
143
+ } else if( fabs( m1-m2 ) < .001 ) {
144
+ return Point( x4, (m1*(x4-x1))+y1 );
145
+ }
146
+ double x = ((-m2 * x4) + y4 + (m1 * x1) - y1) / (m1-m2);
147
+ Point p( x, (m1 * (x-x1)) + y1 );
148
+
149
+ /*
150
+ if( fabs(p.y) > 100 ) {
151
+ fprintf(stderr,"p1/2: %f/%f %f/%f %f/%f %f/%f\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y );
152
+ fprintf(stderr,"S: %f/%f m1/2: %f/%f\n", p.x, p.y, m1, m2 );
153
+ }
154
+ */
155
+ return p;
156
+ }
157
+
158
+ Point midLine( const Point& a, const Point& b ) {
159
+ Point p( ((a.x+b.x)/2), ((a.y+b.y)/2) );
160
+ return p;
161
+ }
162
+
163
+ void bezierSplit( const Bezier& b, Bezier* b0, Bezier* b1 ) {
164
+ Point p01 = midLine( b.p0, b.p1 );
165
+ Point p12 = midLine( b.p1, b.p2 );
166
+ Point p23 = midLine( b.p2, b.p3 );
167
+ Point p02 = midLine( p01, p12 );
168
+ Point p13 = midLine( p12, p23 );
169
+ Point p03 = midLine( p02, p13 );
170
+
171
+ b0->set( b.p0, p01, p02, p03 );
172
+ b1->set( p03, p13, p23, b.p3 );
173
+ }
174
+
175
+ void ShapeMaker::cubicToRec( const Point& a, const Point& b, const Point& c, const Point& d, double k, int iteration ) {
176
+ Point s = intersectLines( a, b, c, d );
177
+ double dx = (a.x+d.x+s.x*4-(b.x+c.x)*3)*.125;
178
+ double dy = (a.y+d.y+s.y*4-(b.y+c.y)*3)*.125;
179
+ Bezier bz( a, b, c, d );
180
+ Bezier b0, b1;
181
+ if( dx*dx + dy*dy > k && iteration<10 ) {
182
+ // fprintf(stderr,"[%03i] split: %f\n", iteration, dx*dx + dy*dy);
183
+ bezierSplit( bz, &b0, &b1 );
184
+ // recurse
185
+ iteration++;
186
+ cubicToRec( a, b0.p1, b0.p2, b0.p3, k, iteration );
187
+ //lineTo( b0.p3.x, b0.p3.y );
188
+
189
+ cubicToRec( b1.p0, b1.p1, b1.p2, d, k, iteration );
190
+ //lineTo( b1.p1.x, b1.p1.y );
191
+ //lineTo( b1.p2.x, b1.p2.y );
192
+ //lineTo( d.x, d.y );
193
+ } else {
194
+ // fprintf(stderr,"#### %i %i %i %i\n", (int)s.x, (int)s.y, (int)d.x, (int)d.y );
195
+ //lineTo( (int)s.x, (int)s.y );
196
+ //lineTo( (int)d.x, (int)d.y );
197
+ curveTo( s.x, s.y, d.x, d.y );
198
+ }
199
+ }
200
+
201
+ void ShapeMaker::cubicTo( double x1, double y1, double x2, double y2, double ax, double ay ) {
202
+ Point a(lastx,lasty);
203
+ Point b(x1,y1);
204
+ Point c(x2,y2);
205
+ Point d(ax,ay);
206
+
207
+ cubicToRec( a, b, c, d, .01 );
208
+
209
+ lastx = ax; lasty = ay;
210
+ smoothx = ax - x2;
211
+ smoothy = ay - y2;
212
+ }
213
+
214
+ void ShapeMaker::cubicToR( double x1, double y1, double x2, double y2, double ax, double ay ) {
215
+ cubicTo(lastx + x1, lasty + y1,
216
+ lastx + x2, lasty + y2,
217
+ lastx + ax, lasty + ay);
218
+ }
219
+
220
+ void ShapeMaker::smoothCubicTo( double x2, double y2, double ax, double ay ) {
221
+ cubicTo( lastx + smoothx, lasty + smoothy, x2, y2, ax, ay );
222
+
223
+ }
224
+
225
+ void ShapeMaker::smoothCubicToR( double x2, double y2, double ax, double ay ) {
226
+ cubicToR( smoothx, smoothy, x2, y2, ax, ay );
227
+ }
228
+
229
+ void ShapeMaker::close(bool stroke) {
230
+ // diffx/diffy captures rounding errors. they can accumulate a bit! FIXME
231
+
232
+ if( diffx || diffy ) {
233
+ /*fprintf(stderr,"WARNING: shape not closed; closing (%f/%f).\n", diffx, diffy);
234
+ fprintf(stderr,"DEBUG: accumulated rounding error (%f/%f).\n", roundx, roundy);*/
235
+
236
+ if(!stroke) {
237
+ doSetup( 0, 0, false, -1, -1, 0 );
238
+ }
239
+
240
+ // closing line
241
+ LineTo *segment = new LineTo;
242
+ segment->setType(1);
243
+ //segment->setbits( maxBitsNeeded( true, 2, x, y ) );
244
+ segment->setx( (int)-diffx );
245
+ segment->sety( (int)-diffy );
246
+ edges->append( segment );
247
+
248
+ if(!stroke) {
249
+ doSetup( 0, 0, false, -1, -1, lineStyle );
250
+ }
251
+
252
+ diffx = diffy = 0;
253
+ if(stroke) {
254
+ lastx = lastsetupx; lasty = lastsetupy;
255
+ }
256
+ }
257
+ }
258
+
259
+ void ShapeMaker::finish() {
260
+ // end shape
261
+ ShapeSetup *setup = new ShapeSetup;
262
+ edges->append( setup );
263
+ }
264
+
265
+ void ShapeMaker::setupR( double x, double y ) {
266
+ x += lastx; y += lasty;
267
+ doSetup( x, y, true, fillStyle0, fillStyle1, lineStyle );
268
+ }
269
+
270
+ void ShapeMaker::setup( double x, double y ) {
271
+ x += offsetx; y += offsety;
272
+ doSetup( x, y, true, fillStyle0, fillStyle1, lineStyle );
273
+ }
274
+
275
+ void ShapeMaker::lineTo( double x, double y ) {
276
+ x += offsetx; y += offsety;
277
+ lineToR( x - lastx, y - lasty );
278
+ }
279
+
280
+ void ShapeMaker::rect( double x, double y, double w, double h, double rx, double ry ) {
281
+ if(rx > 0 || ry > 0) {
282
+ setup(x + rx, y);
283
+ lineTo(x + w - rx, y);
284
+ arcTo(rx, ry, 0, false, true, x + w, y + ry);
285
+ lineTo(x + w, y + h - ry);
286
+ arcTo(rx, ry, 0, false, true, x + w - rx, y + h);
287
+ lineTo(x + rx, y + h);
288
+ arcTo(rx, ry, 0, false, true, x, y + h - ry);
289
+ lineTo(x, y + ry);
290
+ arcTo(rx, ry, 0, false, true, x + rx, y);
291
+ close();
292
+ } else {
293
+ setup(x, y);
294
+ lineToR(0, h);
295
+ lineToR(w, 0);
296
+ lineToR(0, -h);
297
+ lineToR(-w, 0);
298
+ close();
299
+ }
300
+ }
301
+
302
+ #define ELLIPSE_SEGMENTS 8
303
+ #define ELLIPSE_ANGLE ( M_PI * 2 / ELLIPSE_SEGMENTS )
304
+
305
+ void ShapeMaker::ellipseSegment( double cx, double cy, double rx, double ry, double phi, double theta, double dTheta) {
306
+ double a1 = theta + dTheta / 2;
307
+ double a2 = theta + dTheta;
308
+ double f = cos(dTheta / 2);
309
+
310
+ Point p1(cos(a1) * rx / f, sin(a1) * ry / f);
311
+ Point p2(cos(a2) * rx, sin(a2) * ry);
312
+ p1.rotate(phi);
313
+ p2.rotate(phi);
314
+
315
+ curveTo(cx + p1.x, cy + p1.y, cx + p2.x, cy + p2.y);
316
+ }
317
+
318
+ void ShapeMaker::ellipse( double cx, double cy, double rx, double ry ) {
319
+ setup(cx + rx, cy);
320
+ for(int i = 0; i < ELLIPSE_SEGMENTS; i++) {
321
+ ellipseSegment(cx, cy, rx, ry, 0, ELLIPSE_ANGLE * i, ELLIPSE_ANGLE);
322
+ }
323
+ close();
324
+ }
325
+
326
+ void ShapeMaker::arcTo( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y ) {
327
+ double a, f, lambda, theta, dTheta;
328
+
329
+ a = rotation / 180 * M_PI;
330
+
331
+ Point A(lastx, lasty);
332
+ Point B(x, y);
333
+
334
+ Point P = (A - B) / 2;
335
+ P.rotate(-a);
336
+
337
+ lambda = pow(P.x, 2) / pow(rx, 2) + pow(P.y, 2) / pow(ry, 2);
338
+ if(lambda > 1) {
339
+ rx *= sqrt(lambda);
340
+ ry *= sqrt(lambda);
341
+ }
342
+
343
+ f = (pow(rx, 2)*pow(ry, 2)-pow(rx, 2)*pow(P.y, 2)-pow(ry, 2)*pow(P.x, 2))/(pow(rx, 2)*pow(P.y, 2)+pow(ry, 2)*pow(P.x, 2));
344
+ if(f < 0) {
345
+ f = 0;
346
+ } else {
347
+ f = sqrt(f);
348
+ }
349
+ if(largeArcFlag == sweepFlag) f *= -1;
350
+
351
+ Point C_(rx / ry * P.y, -ry / rx * P.x);
352
+ C_ = C_ * f;
353
+
354
+ Point C = C_;
355
+ C.rotate(a);
356
+ C = C + (A + B) / 2;
357
+
358
+ theta = atan2((P.y-C_.y)/ry, (P.x-C_.x)/rx);
359
+ dTheta = atan2((-P.y-C_.y)/ry, (-P.x-C_.x)/rx) - theta;
360
+
361
+ if(sweepFlag && dTheta < 0)
362
+ dTheta += 2 * M_PI;
363
+
364
+ if(!sweepFlag && dTheta > 0)
365
+ dTheta -= 2 * M_PI;
366
+
367
+ double dThetaAbs = (dTheta < 0 ? -dTheta : dTheta);
368
+ int segments = (int)ceil(dThetaAbs / ELLIPSE_ANGLE);
369
+
370
+ for(int i = 0; i < segments; i++) {
371
+ ellipseSegment(C.x, C.y, rx, ry, a, dTheta / segments * i + theta, dTheta / segments);
372
+ }
373
+ }
374
+
375
+ void ShapeMaker::arcToR( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y ) {
376
+ arcTo(rx, ry, rotation, largeArcFlag, sweepFlag, lastx + x, lasty + y);
377
+ }
378
+
379
+ void ShapeMaker::boundsWriteXML( xmlNodePtr parent, double border ) {
380
+ char tmp[TMP_STRLEN];
381
+ xmlNodePtr node;
382
+
383
+ if(border >= 0) {
384
+ node = xmlNewChild(parent, NULL, (const xmlChar *)"bounds", NULL);
385
+ } else {
386
+ node = xmlNewChild(parent, NULL, (const xmlChar *)"strokeBounds", NULL);
387
+ border = 0;
388
+ }
389
+
390
+ node = xmlNewChild(node, NULL, (const xmlChar *)"Rectangle", NULL);
391
+ snprintf(tmp, TMP_STRLEN, "%f", minx - border * 20);
392
+ xmlSetProp(node, (const xmlChar *)"left", (const xmlChar *)&tmp);
393
+ snprintf(tmp, TMP_STRLEN,"%f", miny - border * 20);
394
+ xmlSetProp(node, (const xmlChar *)"top", (const xmlChar *)&tmp);
395
+ snprintf(tmp,TMP_STRLEN,"%f", maxx + border * 20);
396
+ xmlSetProp(node, (const xmlChar *)"right", (const xmlChar *)&tmp);
397
+ snprintf(tmp,TMP_STRLEN,"%f", maxy + border * 20);
398
+ xmlSetProp(node, (const xmlChar *)"bottom", (const xmlChar *)&tmp);
399
+ }
400
+
401
+ }
@@ -0,0 +1,128 @@
1
+ #ifndef SWF_SHAPEMAKER_H
2
+ #define SWF_SHAPEMAKER_H
3
+
4
+ #include "Geom.h"
5
+ #include <cstdio>
6
+ #include <libxml/tree.h>
7
+ #include <cmath>
8
+
9
+ namespace SWF {
10
+
11
+ class ShapeItem;
12
+ template <class T> class List;
13
+
14
+ class Bezier {
15
+ public:
16
+ Point p0, p1, p2, p3;
17
+ Bezier() { ; }
18
+ Bezier( const Point& _p0, const Point& _p1, const Point& _p2, const Point& _p3 )
19
+ : p0(_p0), p1(_p1), p2(_p2), p3(_p3) { ; }
20
+ Bezier &set( const Point& _p0, const Point& _p1, const Point& _p2, const Point& _p3 ) {
21
+ p0 = _p0; p1 = _p1; p2 = _p2; p3 = _p3;
22
+ return *this;
23
+ }
24
+ };
25
+
26
+ class ShapeMaker {
27
+ public:
28
+ ShapeMaker( List<ShapeItem>* edges, double fx = 1, double fy = 1, double ofsx = 0, double ofsy = 0 );
29
+
30
+ void setStyle( int _fillStyle0=-1, int _fillStyle1=-1, int _lineStyle=-1 ) {
31
+ fillStyle0 = _fillStyle0;
32
+ fillStyle1 = _fillStyle1;
33
+ lineStyle = _lineStyle;
34
+ }
35
+
36
+ void setup( double x = 0, double y = 0 );
37
+ void setupR( double x = 0, double y = 0 );
38
+
39
+ void lineTo( double x, double y );
40
+ void lineToR( double x, double y );
41
+
42
+ void curveTo( double cx, double cy, double ax, double ay );
43
+ void curveToR( double cx, double cy, double ax, double ay );
44
+
45
+ void smoothCurveTo( double ax, double ay );
46
+ void smoothCurveToR( double ax, double ay );
47
+
48
+ void cubicTo( double x1, double y1, double x2, double y2, double ax, double ay );
49
+ void cubicToR( double x1, double y1, double x2, double y2, double ax, double ay );
50
+
51
+ void smoothCubicTo( double x2, double y2, double ax, double ay );
52
+ void smoothCubicToR( double x2, double y2, double ax, double ay );
53
+
54
+ void close(bool stroke = true);
55
+ void finish();
56
+
57
+ void rect( double x, double y, double width, double height, double rx = 0, double ry = 0 );
58
+ void ellipse( double cx, double cy, double rx, double ry );
59
+
60
+ void arcTo( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y );
61
+ void arcToR( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y );
62
+
63
+ void boundsWriteXML( xmlNodePtr node, double border = -1 );
64
+
65
+ double getLastX() { return lastx; }
66
+ double getLastY() { return lasty; }
67
+
68
+ double getSmoothX() { return smoothx; }
69
+ double getSmoothY() { return smoothy; }
70
+
71
+ Rect getBounds() { return Rect(minx, miny, maxx, maxy); }
72
+
73
+ protected:
74
+ void cubicToRec( const Point& a, const Point& b, const Point& c, const Point& d, double k, int iteration=0 );
75
+
76
+ void doSetup( double _x=0, double _y=0, bool hasMoveTo=true, int _fillStyle0=-1, int _fillStyle1=-1, int _lineStyle=-1);
77
+
78
+ void ellipseSegment( double cx, double cy, double rx, double ry, double phi, double theta, double dTheta);
79
+
80
+ void minmax( double x, double y ) {
81
+ if( !have_first ) {
82
+ have_first = true;
83
+ minx = x; maxx=x; miny=y; maxy=y;
84
+ } else {
85
+ if( x < minx ) minx=x;
86
+ if( y < miny ) miny=y;
87
+ if( x > maxx ) maxx=x;
88
+ if( y > maxy ) maxy=y;
89
+ }
90
+ }
91
+
92
+ List<ShapeItem>* edges;
93
+ double factorx, factory;
94
+ double offsetx, offsety;
95
+ double diffx, diffy;
96
+ double lastx, lasty;
97
+ double lastsetupx, lastsetupy;
98
+ double minx, miny, maxx, maxy;
99
+ double smoothx, smoothy;
100
+ bool have_first;
101
+
102
+ int fillStyle0, fillStyle1, lineStyle;
103
+
104
+ // rounding error accumulation compensation
105
+ double roundx, roundy;
106
+ int roundX( double x ) { return round( x, &roundx ); }
107
+ int roundY( double y ) { return round( y, &roundy ); }
108
+ int round( double v, double *acc ) {
109
+ int r = (int)v;
110
+ *acc += v-(double)r;
111
+ while( *acc >= .5 ) {
112
+ *acc -= 1.0;
113
+ r++;
114
+ }
115
+ while( *acc <= -.5 ) {
116
+ *acc += 1.0;
117
+ r--;
118
+ }
119
+ return r;
120
+ }
121
+ void roundReset() {
122
+ roundx = roundy = 0;
123
+ }
124
+ };
125
+
126
+
127
+ }
128
+ #endif