swfmill 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/.swfmill +240 -0
- data/LICENSE +340 -0
- data/README.rdoc +37 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/ext/.gitignore +5 -0
- data/ext/extconf.rb +86 -0
- data/ext/swfmill/.gitignore +27 -0
- data/ext/swfmill/AUTHORS +9 -0
- data/ext/swfmill/COPYING +340 -0
- data/ext/swfmill/Makefile.am +14 -0
- data/ext/swfmill/Makefile.in +635 -0
- data/ext/swfmill/NEWS +189 -0
- data/ext/swfmill/README +170 -0
- data/ext/swfmill/TODO +33 -0
- data/ext/swfmill/aclocal.m4 +7712 -0
- data/ext/swfmill/autogen.sh +7 -0
- data/ext/swfmill/compile +142 -0
- data/ext/swfmill/config.guess +1516 -0
- data/ext/swfmill/config.sub +1626 -0
- data/ext/swfmill/configure +21868 -0
- data/ext/swfmill/configure.ac +55 -0
- data/ext/swfmill/depcomp +589 -0
- data/ext/swfmill/install-sh +519 -0
- data/ext/swfmill/ltmain.sh +6964 -0
- data/ext/swfmill/missing +367 -0
- data/ext/swfmill/src/Geom.cpp +107 -0
- data/ext/swfmill/src/Geom.h +100 -0
- data/ext/swfmill/src/Makefile.am +86 -0
- data/ext/swfmill/src/Makefile.in +1025 -0
- data/ext/swfmill/src/SWF.h +11941 -0
- data/ext/swfmill/src/SWFAction.cpp +41 -0
- data/ext/swfmill/src/SWFAction.h +19 -0
- data/ext/swfmill/src/SWFBasic.h +7 -0
- data/ext/swfmill/src/SWFFile.cpp +406 -0
- data/ext/swfmill/src/SWFFile.h +34 -0
- data/ext/swfmill/src/SWFFilter.cpp +25 -0
- data/ext/swfmill/src/SWFFilter.h +15 -0
- data/ext/swfmill/src/SWFGlyphList.cpp +262 -0
- data/ext/swfmill/src/SWFGlyphList.h +34 -0
- data/ext/swfmill/src/SWFIdItem.h +85 -0
- data/ext/swfmill/src/SWFIdItems.h +16 -0
- data/ext/swfmill/src/SWFItem.cpp +235 -0
- data/ext/swfmill/src/SWFItem.h +60 -0
- data/ext/swfmill/src/SWFList.h +179 -0
- data/ext/swfmill/src/SWFReader.cpp +352 -0
- data/ext/swfmill/src/SWFReader.h +73 -0
- data/ext/swfmill/src/SWFShapeItem.cpp +220 -0
- data/ext/swfmill/src/SWFShapeItem.h +45 -0
- data/ext/swfmill/src/SWFShapeMaker.cpp +401 -0
- data/ext/swfmill/src/SWFShapeMaker.h +128 -0
- data/ext/swfmill/src/SWFTag.cpp +49 -0
- data/ext/swfmill/src/SWFTag.h +20 -0
- data/ext/swfmill/src/SWFTrait.cpp +35 -0
- data/ext/swfmill/src/SWFTrait.h +22 -0
- data/ext/swfmill/src/SWFWriter.cpp +312 -0
- data/ext/swfmill/src/SWFWriter.h +84 -0
- data/ext/swfmill/src/base64.c +110 -0
- data/ext/swfmill/src/base64.h +15 -0
- data/ext/swfmill/src/codegen/Makefile.am +15 -0
- data/ext/swfmill/src/codegen/Makefile.in +346 -0
- data/ext/swfmill/src/codegen/basic.xsl +45 -0
- data/ext/swfmill/src/codegen/basics.xsl +235 -0
- data/ext/swfmill/src/codegen/dumper.xsl +109 -0
- data/ext/swfmill/src/codegen/header.xsl +131 -0
- data/ext/swfmill/src/codegen/mk.xsl +26 -0
- data/ext/swfmill/src/codegen/parser.xsl +196 -0
- data/ext/swfmill/src/codegen/parsexml.xsl +312 -0
- data/ext/swfmill/src/codegen/size.xsl +189 -0
- data/ext/swfmill/src/codegen/source.xml +2197 -0
- data/ext/swfmill/src/codegen/writer.xsl +190 -0
- data/ext/swfmill/src/codegen/writexml.xsl +138 -0
- data/ext/swfmill/src/swfmill.cpp +482 -0
- data/ext/swfmill/src/swft/Makefile.am +55 -0
- data/ext/swfmill/src/swft/Makefile.in +717 -0
- data/ext/swfmill/src/swft/Parser.cpp +76 -0
- data/ext/swfmill/src/swft/Parser.h +37 -0
- data/ext/swfmill/src/swft/SVGAttributeParser.cpp +78 -0
- data/ext/swfmill/src/swft/SVGAttributeParser.h +35 -0
- data/ext/swfmill/src/swft/SVGColor.cpp +116 -0
- data/ext/swfmill/src/swft/SVGColor.h +37 -0
- data/ext/swfmill/src/swft/SVGColors.h +167 -0
- data/ext/swfmill/src/swft/SVGGradient.cpp +258 -0
- data/ext/swfmill/src/swft/SVGGradient.h +81 -0
- data/ext/swfmill/src/swft/SVGPathParser.cpp +155 -0
- data/ext/swfmill/src/swft/SVGPathParser.h +126 -0
- data/ext/swfmill/src/swft/SVGPointsParser.cpp +51 -0
- data/ext/swfmill/src/swft/SVGPointsParser.h +25 -0
- data/ext/swfmill/src/swft/SVGStyle.cpp +181 -0
- data/ext/swfmill/src/swft/SVGStyle.h +80 -0
- data/ext/swfmill/src/swft/SVGTransformParser.cpp +72 -0
- data/ext/swfmill/src/swft/SVGTransformParser.h +32 -0
- data/ext/swfmill/src/swft/readpng.c +305 -0
- data/ext/swfmill/src/swft/readpng.h +92 -0
- data/ext/swfmill/src/swft/swft.cpp +251 -0
- data/ext/swfmill/src/swft/swft.h +64 -0
- data/ext/swfmill/src/swft/swft_document.cpp +57 -0
- data/ext/swfmill/src/swft/swft_import.cpp +38 -0
- data/ext/swfmill/src/swft/swft_import_binary.cpp +82 -0
- data/ext/swfmill/src/swft/swft_import_jpeg.cpp +255 -0
- data/ext/swfmill/src/swft/swft_import_mp3.cpp +268 -0
- data/ext/swfmill/src/swft/swft_import_png.cpp +231 -0
- data/ext/swfmill/src/swft/swft_import_ttf.cpp +519 -0
- data/ext/swfmill/src/swft/swft_import_wav.cpp +255 -0
- data/ext/swfmill/src/swft/swft_path.cpp +178 -0
- data/ext/swfmill/src/xslt/Makefile.am +51 -0
- data/ext/swfmill/src/xslt/Makefile.in +536 -0
- data/ext/swfmill/src/xslt/README +19 -0
- data/ext/swfmill/src/xslt/assemble.xsl +38 -0
- data/ext/swfmill/src/xslt/simple-deprecated.xslt +62 -0
- data/ext/swfmill/src/xslt/simple-elements.xslt +627 -0
- data/ext/swfmill/src/xslt/simple-import.xslt +565 -0
- data/ext/swfmill/src/xslt/simple-svg.xslt +383 -0
- data/ext/swfmill/src/xslt/simple-tools.xslt +255 -0
- data/ext/swfmill/src/xslt/simple.cpp +1686 -0
- data/ext/swfmill/src/xslt/simple.xml +7 -0
- data/ext/swfmill/src/xslt/xslt.h +7 -0
- data/ext/swfmill/test/Makefile.am +1 -0
- data/ext/swfmill/test/Makefile.in +490 -0
- data/ext/swfmill/test/xml/Makefile.am +20 -0
- data/ext/swfmill/test/xml/Makefile.in +353 -0
- data/ext/swfmill/test/xml/test-xml +21 -0
- data/ext/swfmill_ext.cc +375 -0
- data/lib/swfmill.rb +30 -0
- data/spec/data/swfmill-banner1.swf +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/swfmill_spec.rb +125 -0
- 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
|