2 Implements generation of swf files using the rfxswf lib. The routines
3 in this file are called from pdf2swf.
5 This file is part of swftools.
7 Swftools is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Swftools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with swftools; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24 #include "../config.h"
33 #include "swfoutput.h"
36 #include "../lib/log.h"
37 #include "../lib/rfxswf.h"
41 int ignoredraworder
=0;
44 int storeallcharacters
=0;
49 int fontsplinemaxerror
=1;
51 static char storefont
= 0;
52 static int flag_protected
= 0;
54 typedef unsigned char u8
;
55 typedef unsigned short int u16
;
56 typedef unsigned long int u32
;
59 static char* filename
= 0;
62 static int currentswfid
= 0;
64 static int startdepth
= 1;
67 static int shapeid
= -1;
68 static int textid
= -1;
70 static int fillstyleid
;
71 static int linestyleid
;
72 static int swflastx
=0;
73 static int swflasty
=0;
74 static int lastwasfill
= 0;
75 static int shapeisempty
= 1;
87 char fillstylechanged
= 0;
89 static void startshape(struct swfoutput
* obj
);
90 static void starttext(struct swfoutput
* obj
);
91 static void endshape();
92 static void endtext();
94 // matrix multiplication. changes p0
95 static void transform (plotxy
*p0
,struct swfmatrix
*m
)
98 x
= m
->m11
*p0
->x
+m
->m12
*p0
->y
;
99 y
= m
->m21
*p0
->x
+m
->m22
*p0
->y
;
104 // write a move-to command into the swf
105 static int moveto(TAG
*tag
, plotxy p0
)
107 int rx
= (int)(p0
.x
*20);
108 int ry
= (int)(p0
.y
*20);
109 if(rx
!=swflastx
|| ry
!=swflasty
|| fillstylechanged
) {
110 swf_ShapeSetMove (tag
, shape
, rx
,ry
);
111 fillstylechanged
= 0;
119 // write a line-to command into the swf
120 static void lineto(TAG
*tag
, plotxy p0
)
122 int rx
= ((int)(p0
.x
*20)-swflastx
);
123 int ry
= ((int)(p0
.y
*20)-swflasty
);
124 /* we can't skip this for rx=0,ry=0, those
126 swf_ShapeSetLine (tag
, shape
, rx
,ry
);
132 // write a spline-to command into the swf
133 static void splineto(TAG
*tag
, plotxy control
,plotxy end
)
135 int cx
= ((int)(control
.x
*20)-swflastx
);
136 int cy
= ((int)(control
.y
*20)-swflasty
);
139 int ex
= ((int)(end
.x
*20)-swflastx
);
140 int ey
= ((int)(end
.y
*20)-swflasty
);
143 if(cx
|| cy
|| ex
|| ey
)
144 swf_ShapeSetCurve(tag
, shape
, cx
,cy
,ex
,ey
);
148 /* write a line, given two points and the transformation
150 static void line(TAG
*tag
, plotxy p0
, plotxy p1
, struct swfmatrix
*m
)
158 /* write a cubic (!) spline. This involves calling the approximate()
159 function out of spline.cc to convert it to a quadratic spline. */
160 static void spline(TAG
*tag
,plotxy p0
,plotxy p1
,plotxy p2
,plotxy p3
,struct swfmatrix
*m
)
163 struct qspline q
[128];
177 /* fonts use a different approximation than shapes */
178 num
= cspline_approximate(&c
, q
, fontsplinemaxerror
/20.0, APPROXIMATE_RECURSIVE_BINARY
);
179 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
181 num
= cspline_approximate(&c
, q
, splinemaxerror
/20.0, APPROXIMATE_RECURSIVE_BINARY
);
185 moveto(tag
,q
[t
].start
);
186 splineto(tag
,q
[t
].control
, q
[t
].end
);
196 static void stopFill()
200 swf_ShapeSetStyle(tag
,shape
,linestyleid
,0x8000,0);
201 fillstylechanged
= 1;
205 static void startFill()
209 swf_ShapeSetStyle(tag
,shape
,0x8000,fillstyleid
,0);
210 fillstylechanged
= 1;
215 /* draw an outline. These are generated by pdf2swf and by t1lib
216 (representing characters). */
217 void drawpath(struct swfoutput
*output
, SWF_OUTLINE
*outline
, struct swfmatrix
*m
, int log
)
219 if( tag
->id
!= ST_DEFINESHAPE
&&
220 tag
->id
!= ST_DEFINESHAPE2
&&
221 tag
->id
!= ST_DEFINESHAPE3
)
223 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag
->id
);
227 double lastx
=0,lasty
=0;
228 double firstx
=0,firsty
=0;
233 x
+= (outline
->dest
.x
/(float)0xffff);
234 y
+= (outline
->dest
.y
/(float)0xffff);
235 if(outline
->type
== SWF_PATHTYPE_MOVE
)
237 if(!init
&& fill
&& output
->drawmode
!= DRAWMODE_EOFILL
&& !ignoredraworder
) {
238 /* drawmode=FILL (not EOFILL) means that
239 seperate shapes do not cancel each other out.
240 On SWF side, we need to start a new shape for each
241 closed polygon, because SWF only knows EOFILL.
248 if(((int)(lastx
*20) != (int)(firstx
*20) ||
249 (int)(lasty
*20) != (int)(firsty
*20)) &&
258 if(log
) printf("fix: %f,%f -> %f,%f\n",p0
.x
,p0
.y
,p1
.x
,p1
.y
);
259 line(tag
, p0
, p1
, m
);
265 else if(outline
->type
== SWF_PATHTYPE_LINE
)
273 if(log
) printf("line: %f,%f -> %f,%f\n",p0
.x
,p0
.y
,p1
.x
,p1
.y
);
276 else if(outline
->type
== SWF_PATHTYPE_BEZIER
)
282 SWF_BEZIERSEGMENT
*o2
= (SWF_BEZIERSEGMENT
*)outline
;
285 p1
.x
=o2
->C
.x
/(float)0xffff+lastx
;
286 p1
.y
=o2
->C
.y
/(float)0xffff+lasty
;
287 p2
.x
=o2
->B
.x
/(float)0xffff+lastx
;
288 p2
.y
=o2
->B
.y
/(float)0xffff+lasty
;
291 if(log
) printf("spline: %f,%f -> %f,%f\n",p3
.x
,p3
.y
,p0
.x
,p0
.y
);
292 spline(tag
,p0
,p1
,p2
,p3
,m
);
295 msg("<error> drawpath: unknown outline type:%d\n", outline
->type
);
299 outline
= outline
->link
;
301 if(((int)(lastx
*20) != (int)(firstx
*20) ||
302 (int)(lasty
*20) != (int)(firsty
*20)) &&
311 if(log
) printf("fix: %f,%f -> %f,%f\n",p0
.x
,p0
.y
,p1
.x
,p1
.y
);
312 line(tag
, p0
, p1
, m
);
316 plotxy
getPivot(SWF_OUTLINE
*outline
, int dir
, double line_width
, int end
, int trytwo
)
318 SWF_PATHPOINT next
, next2
;
319 double xv
=0,yv
=0, xv2
=0, yv2
=0;
324 if(outline
->type
== SWF_PATHTYPE_LINE
) {
325 next
= outline
->dest
;
327 next
= ((SWF_BEZIERSEGMENT
*)outline
)->B
;
328 if(next
.x
==0 && next
.y
==0) {
329 next
= ((SWF_BEZIERSEGMENT
*)outline
)->C
;
331 if(next
.x
==0 && next
.y
==0) {
332 next
= ((SWF_BEZIERSEGMENT
*)outline
)->dest
;
336 if(trytwo
&& outline
->last
&& outline
->last
->type
!= SWF_PATHTYPE_MOVE
) {
337 if(outline
->type
== SWF_PATHTYPE_LINE
) {
338 next2
= outline
->last
->dest
;
340 SWF_PATHPOINT c
= ((SWF_BEZIERSEGMENT
*)(outline
->last
))->C
;
341 SWF_PATHPOINT b
= ((SWF_BEZIERSEGMENT
*)(outline
->last
))->B
;
342 next2
.x
= outline
->last
->dest
.x
- c
.x
;
343 next2
.y
= outline
->last
->dest
.y
- c
.y
;
344 if(next2
.x
==0 && next2
.y
==0) {
345 next2
.x
= outline
->last
->dest
.x
- b
.x
;
346 next2
.y
= outline
->last
->dest
.y
- b
.y
;
348 if(next2
.x
==0 && next2
.y
==0) {
349 next2
.x
= outline
->last
->dest
.x
;
350 next2
.y
= outline
->last
->dest
.y
;
356 if(outline
->type
== SWF_PATHTYPE_LINE
) {
357 next
= outline
->dest
;
359 SWF_PATHPOINT c
= ((SWF_BEZIERSEGMENT
*)outline
)->C
;
360 SWF_PATHPOINT b
= ((SWF_BEZIERSEGMENT
*)outline
)->B
;
361 next
.x
= outline
->dest
.x
- c
.x
;
362 next
.y
= outline
->dest
.y
- c
.y
;
363 if(next
.x
==0 && next
.y
==0) {
364 next
.x
= outline
->dest
.x
- b
.x
;
365 next
.y
= outline
->dest
.y
- b
.y
;
367 if(next
.x
==0 && next
.y
==0) {
368 next
.x
= outline
->dest
.x
;
369 next
.y
= outline
->dest
.y
;
373 if(trytwo
&& outline
->link
&& outline
->link
->type
!= SWF_PATHTYPE_MOVE
) {
374 if(outline
->type
== SWF_PATHTYPE_LINE
) {
375 next2
= outline
->link
->dest
;
377 next2
= ((SWF_BEZIERSEGMENT
*)(outline
->link
))->B
;
378 if(next2
.x
==0 && next2
.y
==0) {
379 next2
= ((SWF_BEZIERSEGMENT
*)outline
->link
)->C
;
381 if(next2
.x
==0 && next2
.y
==0) {
382 next2
= ((SWF_BEZIERSEGMENT
*)outline
->link
)->dest
;
390 xv
= next
.y
/(float)0xffff;
391 yv
= -next
.x
/(float)0xffff;
393 xv
= -next
.y
/(float)0xffff;
394 yv
= next
.x
/(float)0xffff;
397 double r
= (line_width
/2)/sqrt(xv
*xv
+yv
*yv
);
403 xv2
= next2
.y
/(float)0xffff;
404 yv2
= -next2
.x
/(float)0xffff;
406 xv2
= -next2
.y
/(float)0xffff;
407 yv2
= next2
.x
/(float)0xffff;
410 double r2
= (line_width
/2)/sqrt(xv2
*xv2
+yv2
*yv2
);
415 double r3
= (line_width
/2)/sqrt(xv
*xv
+yv
*yv
);
425 void drawShortPath(struct swfoutput
*output
, double x
, double y
, struct swfmatrix
* m
, SWF_OUTLINE
*outline
)
427 double lastx
=x
, lasty
=y
;
428 while (outline
&& outline
->type
!= SWF_PATHTYPE_MOVE
)
430 x
+= (outline
->dest
.x
/(float)0xffff);
431 y
+= (outline
->dest
.y
/(float)0xffff);
433 if(outline
->type
== SWF_PATHTYPE_LINE
)
440 line(tag
, p0
, p1
, m
);
442 else if(outline
->type
== SWF_PATHTYPE_BEZIER
)
445 SWF_BEZIERSEGMENT
*o2
= (SWF_BEZIERSEGMENT
*)outline
;
448 p1
.x
=o2
->C
.x
/(float)0xffff+lastx
;
449 p1
.y
=o2
->C
.y
/(float)0xffff+lasty
;
450 p2
.x
=o2
->B
.x
/(float)0xffff+lastx
;
451 p2
.y
=o2
->B
.y
/(float)0xffff+lasty
;
454 spline(tag
,p0
,p1
,p2
,p3
,m
);
458 outline
= outline
->link
;
462 void drawShortPathWithEnds(struct swfoutput
*output
, double x
, double y
, struct swfmatrix
* m
, SWF_OUTLINE
*outline
, int num
, int line_cap
, int line_join
, double line_width
)
467 if(line_cap
== LINE_CAP_BUTT
|| line_cap
== LINE_CAP_SQUARE
) {
470 SWF_OUTLINE
*last
, *tmp
=outline
;
471 plotxy s
,e
,p0
,p1
,p2
,p3
,m0
,m1
,m2
,m3
;
477 while(tmp
&& tmp
->type
!= SWF_PATHTYPE_MOVE
) {
479 lx
+= (tmp
->dest
.x
/(float)0xffff);
480 ly
+= (tmp
->dest
.y
/(float)0xffff);
483 s
= getPivot(outline
, 0, line_width
, 0, 0);
484 e
= getPivot(last
, 0, line_width
, 1, 0);
486 if(line_cap
== LINE_CAP_BUTT
) {
487 /* make the clipping rectangle slighly bigger
488 than the line ending, so that it get's clipped
498 p2
.x
= x2
- s
.y
- s
.x
*ee
;
499 p2
.y
= y2
+ s
.x
- s
.y
*ee
;
500 p3
.x
= x2
- s
.y
+ s
.x
*ee
;
501 p3
.y
= y2
+ s
.x
+ s
.y
*ee
;
506 m2
.x
= lx
+ e
.y
- e
.x
*ee
;
507 m2
.y
= ly
- e
.x
- e
.y
*ee
;
508 m3
.x
= lx
+ e
.y
+ e
.x
*ee
;
509 m3
.y
= ly
- e
.x
+ e
.y
*ee
;
511 for(nr
=0;nr
<2;nr
++) {
513 struct plotxy q0
,q1
,q2
,q3
,q4
,q5
;
515 if(line_cap
== LINE_CAP_BUTT
) {
518 q1
.x
= sizex
; q1
.y
= 0;
519 q2
.x
= sizex
; q2
.y
= sizey
;
520 q3
.x
= 0; q3
.y
= sizey
;
522 q0
.x
= sizex
; q0
.y
= sizey
;
523 q1
.x
= 0; q1
.y
= sizey
;
525 q3
.x
= sizex
; q3
.y
= 0;
539 line(tag
, p0
, p1
, m
);
540 line(tag
, p1
, p2
, m
);
541 line(tag
, p2
, p3
, m
);
542 line(tag
, p3
, p0
, m
);
544 if(line_cap
== LINE_CAP_BUTT
) {
546 swf_ShapeSetEnd(tag
);
547 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
548 swf_ObjectPlaceClip(tag
,shapeid
,depth
,NULL
,NULL
,NULL
,depth
+2-nr
);
562 drawShortPath(output
,x
,y
,m
,outline
);
564 if(line_cap
== LINE_CAP_BUTT
) {
570 void drawT1toRect(struct swfoutput
*output
, double x
, double y
, struct swfmatrix
* m
, SWF_OUTLINE
*outline
, int num
, int line_cap
, int line_join
, double line_width
)
572 plotxy d1
,d2
,p1
,p2
,p3
,p4
;
574 d1
.x
= (outline
->dest
.x
/(float)0xffff);
575 d1
.y
= (outline
->dest
.y
/(float)0xffff);
576 d2
= getPivot(outline
, 0, line_width
, 0, 0);
578 assert(line_cap
!= LINE_CAP_ROUND
);
579 if(line_cap
== LINE_CAP_SQUARE
) {
588 p2
.x
= x
+ d2
.x
+ d1
.x
;
589 p2
.y
= y
+ d2
.y
+ d1
.y
;
590 p3
.x
= x
- d2
.x
+ d1
.x
;
591 p3
.y
= y
- d2
.y
+ d1
.y
;
601 void drawShortPathWithStraightEnds(struct swfoutput
*output
, double x
, double y
, struct swfmatrix
* m
, SWF_OUTLINE
*outline
, int num
, int line_cap
, int line_join
, double line_width
)
603 SWF_OUTLINE
*tmp
=outline
;
609 drawT1toRect(output
, x
, y
, m
,outline
, num
, line_cap
, line_join
, line_width
);
611 while(tmp
->link
&& tmp
->link
->type
!=SWF_PATHTYPE_MOVE
) {
612 xx
+= (tmp
->dest
.x
/(float)0xffff);
613 yy
+= (tmp
->dest
.y
/(float)0xffff);
617 assert(tmp
->type
== SWF_PATHTYPE_LINE
);
618 assert(outline
->type
== SWF_PATHTYPE_LINE
);
622 if(outline
->link
== tmp
) {
623 /* the two straight line segments (which are everything we
624 need to draw) are very likely to overlap. To avoid that
625 they cancel each other out at the end points, start a new
626 shape for the second one */
627 endshape();startshape(output
);
631 drawT1toRect(output
, xx
, yy
, m
, tmp
, num
, line_cap
, line_join
, line_width
);
633 if(outline
->link
!= tmp
)
637 tmp
->type
= SWF_PATHTYPE_MOVE
;
638 x
+= (outline
->dest
.x
/(float)0xffff);
639 y
+= (outline
->dest
.y
/(float)0xffff);
640 outline
= outline
->link
;
641 drawShortPath(output
, x
, y
, m
, outline
);
649 static int t1len(SWF_OUTLINE
*line
)
652 while(line
&& line
->type
!= SWF_PATHTYPE_MOVE
) {
659 static float t1linelen(SWF_OUTLINE
*line
)
662 x
= (line
->dest
.x
/(float)0xffff);
663 y
= (line
->dest
.y
/(float)0xffff);
664 return sqrt(x
*x
+y
*y
);
667 void drawpath2poly(struct swfoutput
*output
, SWF_OUTLINE
*outline
, struct swfmatrix
*m
, int log
, int line_join
, int line_cap
, double line_width
, double miter_limit
)
669 if( tag
->id
!= ST_DEFINESHAPE
&&
670 tag
->id
!= ST_DEFINESHAPE2
&&
671 tag
->id
!= ST_DEFINESHAPE3
) {
672 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag
->id
);
677 double lastx
=0,lasty
=0;
680 SWF_OUTLINE
*tmp
= outline
, *last
= 0;
685 x
+= (tmp
->dest
.x
/(float)0xffff);
686 y
+= (tmp
->dest
.y
/(float)0xffff);
688 if(!tmp
|| tmp
->type
== SWF_PATHTYPE_MOVE
) {
690 if(last
->type
== SWF_PATHTYPE_LINE
&& t1linelen(last
)>line_width
*2 &&
691 lastwasline
&& line_cap
!= LINE_CAP_ROUND
)
692 drawShortPathWithStraightEnds(output
, lastx
, lasty
, m
, last
, valid
, line_cap
, line_join
, line_width
);
694 drawShortPathWithEnds(output
, lastx
, lasty
, m
, last
, valid
, line_cap
, line_join
, line_width
);
708 if(tmp
&& tmp
->type
== SWF_PATHTYPE_LINE
&& t1linelen(tmp
)>line_width
*2)
714 tmp
->link
->last
= tmp
; // make sure list is properly linked in both directions
719 static inline int colorcompare(RGBA
*a
,RGBA
*b
)
731 static const int CHARDATAMAX
= 8192;
739 } chardata
[CHARDATAMAX
];
742 static void putcharacters(TAG
*tag
)
747 color
.r
= chardata
[0].color
.r
^255;
756 int charadvance
[128];
759 int glyphbits
=1; //TODO: can this be zero?
762 if(tag
->id
!= ST_DEFINETEXT
&&
763 tag
->id
!= ST_DEFINETEXT2
) {
764 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag
->id
);
768 msg("<warning> putcharacters called with zero characters");
771 for(pass
= 0; pass
< 2; pass
++)
781 advancebits
++; // add sign bit
782 swf_SetU8(tag
, glyphbits
);
783 swf_SetU8(tag
, advancebits
);
786 for(t
=0;t
<=chardatapos
;t
++)
788 if(lastfontid
!= chardata
[t
].fontid
||
789 lastx
!=chardata
[t
].x
||
790 lasty
!=chardata
[t
].y
||
791 !colorcompare(&color
, &chardata
[t
].color
) ||
793 lastsize
!= chardata
[t
].size
||
796 if(charstorepos
&& pass
==0)
799 for(s
=0;s
<charstorepos
;s
++)
801 while(charids
[s
]>=(1<<glyphbits
))
803 while(charadvance
[s
]>=(1<<advancebits
))
807 if(charstorepos
&& pass
==1)
809 tag
->writeBit
= 0; // Q&D
810 swf_SetBits(tag
, 0, 1); // GLYPH Record
811 swf_SetBits(tag
, charstorepos
, 7); // number of glyphs
813 for(s
=0;s
<charstorepos
;s
++)
815 swf_SetBits(tag
, charids
[s
], glyphbits
);
816 swf_SetBits(tag
, charadvance
[s
], advancebits
);
821 if(pass
== 1 && t
<chardatapos
)
827 if(lastx
!= chardata
[t
].x
||
828 lasty
!= chardata
[t
].y
)
830 newx
= chardata
[t
].x
;
831 newy
= chardata
[t
].y
;
837 if(!colorcompare(&color
, &chardata
[t
].color
))
839 color
= chardata
[t
].color
;
842 font
.id
= chardata
[t
].fontid
;
843 if(lastfontid
!= chardata
[t
].fontid
|| lastsize
!= chardata
[t
].size
)
846 tag
->writeBit
= 0; // Q&D
847 swf_TextSetInfoRecord(tag
, newfont
, chardata
[t
].size
, newcolor
, newx
,newy
);
850 lastfontid
= chardata
[t
].fontid
;
851 lastx
= chardata
[t
].x
;
852 lasty
= chardata
[t
].y
;
853 lastsize
= chardata
[t
].size
;
860 int nextt
= t
==chardatapos
-1?t
:t
+1;
861 int rel
= chardata
[nextt
].x
-chardata
[t
].x
;
862 if(rel
>=0 && (rel
<(1<<(advancebits
-1)) || pass
==0)) {
864 lastx
=chardata
[nextt
].x
;
870 charids
[charstorepos
] = chardata
[t
].charid
;
871 charadvance
[charstorepos
] = advance
;
878 static void putcharacter(struct swfoutput
*obj
, int fontid
, int charid
,
879 int x
,int y
, int size
)
881 if(chardatapos
== CHARDATAMAX
)
883 msg("<warning> Character buffer too small. SWF will be slightly bigger");
887 chardata
[chardatapos
].fontid
= fontid
;
888 chardata
[chardatapos
].charid
= charid
;
889 chardata
[chardatapos
].x
= x
;
890 chardata
[chardatapos
].y
= y
;
891 chardata
[chardatapos
].color
= obj
->fillrgb
;
892 chardata
[chardatapos
].size
= size
;
902 /* process a character. */
903 static int drawchar(struct swfoutput
*obj
, SWFFONT
*swffont
, char*character
, int charnr
, int u
, swfmatrix
*m
)
906 if(m
->m12
!=0 || m
->m21
!=0)
912 msg("<warning> Font is NULL");
917 msg("<verbose> Non diagonal font matrix: %f %f", m
->m11
, m
->m21
);
918 msg("<verbose> | %f %f", m
->m12
, m
->m22
);
921 //if(usefonts && ! drawonlyshapes)
924 int charid
= getCharID(swffont
, charnr
, character
, u
);
927 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
928 FIXNULL(character
),charnr
, u
, FIXNULL((char*)swffont
->name
), swffont
->numchars
);
929 /*fontlist_t*it = fontlist;
931 msg("<warning> Font history: %s [%d]", it->swffont->name, getCharID(it->swffont, charnr, character, u));
942 putcharacter(obj
, swffont
->id
, charid
,(int)(m
->m13
*20),(int)(m
->m23
*20),
948 SWF_OUTLINE*outline = font->getOutline(character, charnr);
949 char* charname = character;
952 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
953 FIXNULL(character),charnr,FIXNULL(font->getName()));
972 drawpath(tag, outline, &m2, 0);
977 /* draw a curved polygon. */
978 void swfoutput_drawpath(swfoutput
*output
, SWF_OUTLINE
*outline
,
984 /* Multiple polygons in one shape don't overlap correctly,
985 so we better start a new shape here if the polygon is filled
987 if(shapeid
>=0 && fill
&& !ignoredraworder
) {
999 drawpath(output
, outline
,m
, 0);
1002 void swfoutput_drawpath2poly(struct swfoutput
*output
, SWF_OUTLINE
*outline
, struct swfmatrix
*m
, int line_join
, int line_cap
, double line_width
, double miter_limit
)
1012 drawpath2poly(output
, outline
, m
, 0, line_join
, line_cap
, line_width
, miter_limit
);
1015 int getCharID(SWFFONT
*font
, int charnr
, char *charname
, int u
)
1019 for(t
=0;t
<font
->numchars
;t
++) {
1020 if(font
->glyphnames
[t
] && !strcmp(font
->glyphnames
[t
],charname
)) {
1024 /* if we didn't find the character, maybe
1025 we can find the capitalized version */
1026 for(t
=0;t
<font
->numchars
;t
++) {
1027 if(font
->glyphnames
[t
] && !strcasecmp(font
->glyphnames
[t
],charname
)) {
1034 if(u
>=font
->maxascii
)
1035 msg("<debug> u=%d, font->maxascii=%d",u
,font
->maxascii
);
1037 msg("<debug> u=%d, font->maxascii=%d ascci2glyph[%d]=%d",u
,font
->maxascii
,u
,font
->ascii2glyph
[u
]);
1039 /* try to use the unicode id */
1040 if(u
>=0 && u
<font
->maxascii
&& font
->ascii2glyph
[u
]>=0) {
1041 return font
->ascii2glyph
[u
];
1045 if(charnr
>=0 && charnr
<font
->numchars
) {
1053 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1054 void swfoutput_setfont(struct swfoutput
*obj
, char*fontid
, char*filename
)
1056 fontlist_t
*last
=0,*iterator
;
1058 msg("<error> No fontid");
1062 if(obj
->swffont
&& obj
->swffont
->name
&& !strcmp((char*)obj
->swffont
->name
,fontid
))
1065 iterator
= fontlist
;
1067 if(!strcmp((char*)iterator
->swffont
->name
,fontid
)) {
1068 obj
->swffont
= iterator
->swffont
;
1072 iterator
= iterator
->next
;
1076 msg("<error> No filename given for font- internal error?");
1080 SWFFONT
*swffont
= swf_LoadFont(filename
);
1083 msg("<warning> Couldn't load font %s (%s)", fontid
, filename
);
1084 swffont
= swf_LoadFont(0);
1087 swf_FontSetID(swffont
, ++currentswfid
);
1089 if(screenloglevel
>= LOGLEVEL_DEBUG
) {
1090 // print font information
1091 msg("<debug> Font %s (%s)",swffont
->name
, filename
);
1092 msg("<debug> | ID: %d", swffont
->id
);
1093 msg("<debug> | Version: %d", swffont
->version
);
1094 msg("<debug> | Name: %s", fontid
);
1095 msg("<debug> | Numchars: %d", swffont
->numchars
);
1096 msg("<debug> | Maxascii: %d", swffont
->maxascii
);
1097 msg("<debug> | Style: %d", swffont
->style
);
1098 msg("<debug> | Encoding: %d", swffont
->encoding
);
1099 for(int iii
=0; iii
<swffont
->numchars
;iii
++) {
1100 msg("<debug> | Glyph %d) name=%s, unicode=%d\n", iii
, swffont
->glyphnames
[iii
], swffont
->glyph2ascii
[iii
]);
1104 /* set the font name to the ID we use here */
1105 if(swffont
->name
) free(swffont
->name
);
1106 swffont
->name
= (U8
*)strdup(fontid
);
1108 iterator
= new fontlist_t
;
1109 iterator
->swffont
= swffont
;
1113 last
->next
= iterator
;
1115 fontlist
= iterator
;
1117 obj
->swffont
= swffont
;
1120 int swfoutput_queryfont(struct swfoutput
*obj
, char*fontid
)
1122 fontlist_t
*iterator
= fontlist
;
1124 if(!strcmp((char*)iterator
->swffont
->name
,fontid
))
1126 iterator
= iterator
->next
;
1131 /* set's the matrix which is to be applied to characters drawn by
1132 swfoutput_drawchar() */
1133 void swfoutput_setfontmatrix(struct swfoutput
*obj
,double m11
,double m12
,
1134 double m21
,double m22
)
1136 if(obj
->fontm11
== m11
&&
1137 obj
->fontm12
== m12
&&
1138 obj
->fontm21
== m21
&&
1139 obj
->fontm22
== m22
)
1149 /* draws a character at x,y. */
1150 int swfoutput_drawchar(struct swfoutput
* obj
,double x
,double y
,char*character
, int charnr
, int u
)
1153 m
.m11
= obj
->fontm11
;
1154 m
.m12
= obj
->fontm12
;
1155 m
.m21
= obj
->fontm21
;
1156 m
.m22
= obj
->fontm22
;
1159 return drawchar(obj
, obj
->swffont
, character
, charnr
, u
, &m
);
1162 /* initialize the swf writer */
1163 void swfoutput_init(struct swfoutput
* obj
, char*_filename
, int x1
, int y1
, int x2
, int y2
)
1167 memset(obj
, 0, sizeof(struct swfoutput
));
1168 filename
= _filename
;
1172 msg("<verbose> initializing swf output for size %d*%d\n", sizex
,sizey
);
1177 memset(&swf
,0x00,sizeof(SWF
));
1179 swf
.fileVersion
= flashversion
;
1180 swf
.frameRate
= 0x0040; // 1 frame per 4 seconds
1181 swf
.movieSize
.xmin
= 20*x1
;
1182 swf
.movieSize
.ymin
= 20*y1
;
1183 swf
.movieSize
.xmax
= 20*x2
;
1184 swf
.movieSize
.ymax
= 20*y2
;
1188 swf
.firstTag
= swf_InsertTag(NULL
,ST_SETBACKGROUNDCOLOR
);
1190 rgb
.a
= rgb
.r
= rgb
.g
= rgb
.b
= 0xff;
1191 swf_SetRGB(tag
,&rgb
);
1193 if(1)/* add white rectangle */
1198 int shapeid
= ++currentswfid
;
1203 tag
= swf_InsertTag(tag
, ST_DEFINESHAPE
);
1205 fs1
= swf_ShapeAddSolidFillStyle(s
, &rgb
);
1206 swf_SetU16(tag
,shapeid
);
1207 swf_SetRect(tag
,&r
);
1208 swf_SetShapeHeader(tag
,s
);
1209 swf_ShapeSetAll(tag
,s
,x1
*20,y1
*20,ls1
,fs1
,0);
1210 swf_ShapeSetLine(tag
,s
,20*(x2
-x1
),0);
1211 swf_ShapeSetLine(tag
,s
,0,20*(y2
-y1
));
1212 swf_ShapeSetLine(tag
,s
,20*(x1
-x2
),0);
1213 swf_ShapeSetLine(tag
,s
,0,20*(y1
-y2
));
1214 swf_ShapeSetEnd(tag
);
1216 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
1217 swf_ObjectPlace(tag
,shapeid
,depth
++,0,0,0);
1218 tag
= swf_InsertTag(tag
, ST_PLACEOBJECT2
);
1219 swf_ObjectPlaceClip(tag
,shapeid
,depth
++,0,0,0,65535);
1223 tag
= swf_InsertTag(tag
, ST_PROTECT
);
1228 void swfoutput_setprotected() //write PROTECT tag
1233 static void startshape(struct swfoutput
*obj
)
1241 tag
= swf_InsertTag(tag
,ST_DEFINESHAPE
);
1243 swf_ShapeNew(&shape
);
1244 linestyleid
= swf_ShapeAddLineStyle(shape
,obj
->linewidth
,&obj
->strokergb
);
1245 rgb
.r
= obj
->fillrgb
.r
;
1246 rgb
.g
= obj
->fillrgb
.g
;
1247 rgb
.b
= obj
->fillrgb
.b
;
1248 fillstyleid
= swf_ShapeAddSolidFillStyle(shape
,&obj
->fillrgb
);
1250 shapeid
= ++currentswfid
;
1251 swf_SetU16(tag
,shapeid
); // ID
1258 swf_SetRect(tag
,&r
);
1260 swf_SetShapeStyles(tag
,shape
);
1261 swf_ShapeCountBits(shape
,NULL
,NULL
);
1262 swf_SetShapeBits(tag
,shape
);
1264 swf_ShapeSetAll(tag
,shape
,/*x*/0,/*y*/0,linestyleid
,0,0);
1265 swflastx
=swflasty
=0;
1270 static void starttext(struct swfoutput
*obj
)
1276 tag
= swf_InsertTag(tag
,ST_DEFINETEXT
);
1277 textid
= ++currentswfid
;
1278 swf_SetU16(tag
, textid
);
1285 swf_SetRect(tag
,&r
);
1294 swf_SetMatrix(tag
,&m
);
1295 swflastx
=swflasty
=0;
1298 static void endshape()
1302 swf_ShapeSetEnd(tag
);
1305 // delete the tag again, we didn't do anything
1308 swf_DeleteTag(todel
);
1310 tag
= swf_InsertTag(tag
,ST_PLACEOBJECT2
);
1311 swf_ObjectPlace(tag
,shapeid
,/*depth*/depth
++,NULL
,NULL
,NULL
);
1316 static void endtext()
1322 tag
= swf_InsertTag(tag
,ST_PLACEOBJECT2
);
1323 swf_ObjectPlace(tag
,textid
,/*depth*/depth
++,NULL
,NULL
,NULL
);
1327 static void endpage(struct swfoutput
*obj
)
1334 swfoutput_endclip(obj
);
1338 atag
= action_Stop(atag
);
1339 atag
= action_End(atag
);
1340 tag
= swf_InsertTag(tag
,ST_DOACTION
);
1341 swf_ActionSet(tag
,atag
);
1343 tag
= swf_InsertTag(tag
,ST_SHOWFRAME
);
1346 void swfoutput_newpage(struct swfoutput
*obj
)
1350 for(depth
--;depth
>=startdepth
;depth
--) {
1351 tag
= swf_InsertTag(tag
,ST_REMOVEOBJECT2
);
1352 swf_SetU16(tag
,depth
);
1358 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1359 up, complete the swf, and write it out. */
1360 void swfoutput_destroy(struct swfoutput
* obj
)
1363 fontlist_t
*tmp
,*iterator
= fontlist
;
1365 TAG
*mtag
= swf
.firstTag
;
1366 if(iterator
->swffont
) {
1367 mtag
= swf_InsertTag(mtag
, ST_DEFINEFONT2
);
1368 swf_FontSetDefine2(mtag
, iterator
->swffont
);
1369 swf_FontFree(iterator
->swffont
);
1373 iterator
= iterator
->next
;
1380 fi
= open(filename
, O_BINARY
|O_CREAT
|O_TRUNC
|O_WRONLY
, 0777);
1385 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename
));
1389 tag
= swf_InsertTag(tag
,ST_END
);
1392 if FAILED(swf_WriteSWC(fi
,&swf
))
1393 msg("<error> WriteSWC() failed.\n");
1395 if FAILED(swf_WriteSWF(fi
,&swf
))
1396 msg("<error> WriteSWF() failed.\n");
1401 msg("<notice> SWF written\n");
1404 void swfoutput_setdrawmode(swfoutput
* obj
, int mode
)
1406 obj
->drawmode
= mode
;
1407 if(mode
== DRAWMODE_FILL
)
1409 else if(mode
== DRAWMODE_EOFILL
)
1411 else if(mode
== DRAWMODE_STROKE
)
1413 else if(mode
== DRAWMODE_CLIP
)
1415 else if(mode
== DRAWMODE_EOCLIP
)
1419 void swfoutput_setfillcolor(swfoutput
* obj
, u8 r
, u8 g
, u8 b
, u8 a
)
1421 if(obj
->fillrgb
.r
== r
&&
1422 obj
->fillrgb
.g
== g
&&
1423 obj
->fillrgb
.b
== b
&&
1424 obj
->fillrgb
.a
== a
) return;
1434 void swfoutput_setstrokecolor(swfoutput
* obj
, u8 r
, u8 g
, u8 b
, u8 a
)
1436 if(obj
->strokergb
.r
== r
&&
1437 obj
->strokergb
.g
== g
&&
1438 obj
->strokergb
.b
== b
&&
1439 obj
->strokergb
.a
== a
) return;
1443 obj
->strokergb
.r
= r
;
1444 obj
->strokergb
.g
= g
;
1445 obj
->strokergb
.b
= b
;
1446 obj
->strokergb
.a
= a
;
1449 void swfoutput_setlinewidth(struct swfoutput
*obj
, double linewidth
)
1451 if(obj
->linewidth
== (u16
)(linewidth
*20))
1456 obj
->linewidth
= (u16
)(linewidth
*20);
1460 void swfoutput_startclip(swfoutput
*obj
, SWF_OUTLINE
*outline
, struct swfmatrix
*m
)
1469 msg("<warning> Too many clip levels.");
1474 int olddrawmode
= obj
->drawmode
;
1475 swfoutput_setdrawmode(obj
, DRAWMODE_CLIP
);
1476 swfoutput_drawpath(obj
, outline
, m
);
1477 swf_ShapeSetEnd(tag
);
1478 swfoutput_setdrawmode(obj
, olddrawmode
);
1480 tag
= swf_InsertTag(tag
,ST_PLACEOBJECT2
);
1481 cliptags
[clippos
] = tag
;
1482 clipshapes
[clippos
] = shapeid
;
1483 clipdepths
[clippos
] = depth
++;
1488 void swfoutput_endclip(swfoutput
*obj
)
1496 msg("<error> Invalid end of clipping region");
1500 swf_ObjectPlaceClip(cliptags
[clippos
],clipshapes
[clippos
],clipdepths
[clippos
],NULL
,NULL
,NULL
,depth
++);
1503 static void drawlink(struct swfoutput
*obj
, ActionTAG
*,ActionTAG
*, swfcoord
*points
, char mouseover
);
1505 void swfoutput_linktourl(struct swfoutput
*obj
, char*url
, swfcoord
*points
)
1508 if(!strncmp("http://pdf2swf:", url
, 15)) {
1509 char*tmp
= strdup(url
);
1510 int l
= strlen(tmp
);
1513 swfoutput_namedlink(obj
, tmp
+15, points
);
1524 actions
= action_GetUrl(0, url
, "_parent");
1526 actions
= action_GetUrl(0, url
, "_this");
1527 actions
= action_End(actions
);
1529 drawlink(obj
, actions
, 0, points
,0);
1531 void swfoutput_linktopage(struct swfoutput
*obj
, int page
, swfcoord
*points
)
1540 actions
= action_GotoFrame(0, page
);
1541 actions
= action_End(actions
);
1543 drawlink(obj
, actions
, 0, points
,0);
1546 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1547 of the viewer objects, like subtitles, index elements etc.
1549 void swfoutput_namedlink(struct swfoutput
*obj
, char*name
, swfcoord
*points
)
1551 ActionTAG
*actions1
,*actions2
;
1552 char*tmp
= strdup(name
);
1560 if(!strncmp(tmp
, "call:", 5))
1562 char*x
= strchr(&tmp
[5], ':');
1564 actions1
= action_PushInt(0, 0); //number of parameters (0)
1565 actions1
= action_PushString(actions1
, &tmp
[5]); //function name
1566 actions1
= action_CallFunction(actions1
);
1569 actions1
= action_PushString(0, x
+1); //parameter
1570 actions1
= action_PushInt(actions1
, 1); //number of parameters (1)
1571 actions1
= action_PushString(actions1
, &tmp
[5]); //function name
1572 actions1
= action_CallFunction(actions1
);
1574 actions2
= action_End(0);
1579 actions1
= action_PushString(0, "/:subtitle");
1580 actions1
= action_PushString(actions1
, name
);
1581 actions1
= action_SetVariable(actions1
);
1582 actions1
= action_End(actions1
);
1584 actions2
= action_PushString(0, "/:subtitle");
1585 actions2
= action_PushString(actions2
, "");
1586 actions2
= action_SetVariable(actions2
);
1587 actions2
= action_End(actions2
);
1590 drawlink(obj
, actions1
, actions2
, points
,mouseover
);
1592 swf_ActionFree(actions1
);
1593 swf_ActionFree(actions2
);
1597 static void drawlink(struct swfoutput
*obj
, ActionTAG
*actions1
, ActionTAG
*actions2
, swfcoord
*points
, char mouseover
)
1603 struct plotxy p1
,p2
,p3
,p4
;
1607 double xmax
=xmin
=points
[0].x
,ymax
=ymin
=points
[0].y
;
1611 int buttonid
= ++currentswfid
;
1614 if(points
[t
].x
>xmax
) xmax
=points
[t
].x
;
1615 if(points
[t
].y
>ymax
) ymax
=points
[t
].y
;
1616 if(points
[t
].x
<xmin
) xmin
=points
[t
].x
;
1617 if(points
[t
].y
<ymin
) ymin
=points
[t
].y
;
1620 p1
.x
=points
[0].x
; p1
.y
=points
[0].y
; p2
.x
=points
[1].x
; p2
.y
=points
[1].y
;
1621 p3
.x
=points
[2].x
; p3
.y
=points
[2].y
; p4
.x
=points
[3].x
; p4
.y
=points
[3].y
;
1623 /* the following code subtracts the upper left edge from all coordinates,
1624 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1625 Necessary for preprocessing with swfcombine. */
1626 posx
= xmin
; posy
= ymin
;
1627 p1
.x
-=posx
;p2
.x
-=posx
;p3
.x
-=posx
;p4
.x
-=posx
;
1628 p1
.y
-=posy
;p2
.y
-=posy
;p3
.y
-=posy
;p4
.y
-=posy
;
1629 xmin
-= posx
; ymin
-= posy
;
1630 xmax
-= posx
; ymax
-= posy
;
1633 myshapeid
= ++currentswfid
;
1634 tag
= swf_InsertTag(tag
,ST_DEFINESHAPE3
);
1635 swf_ShapeNew(&shape
);
1636 rgb
.r
= rgb
.b
= rgb
.a
= rgb
.g
= 0;
1637 fsid
= swf_ShapeAddSolidFillStyle(shape
,&rgb
);
1638 swf_SetU16(tag
, myshapeid
);
1639 r
.xmin
= (int)(xmin
*20);
1640 r
.ymin
= (int)(ymin
*20);
1641 r
.xmax
= (int)(xmax
*20);
1642 r
.ymax
= (int)(ymax
*20);
1643 swf_SetRect(tag
,&r
);
1644 swf_SetShapeStyles(tag
,shape
);
1645 swf_ShapeCountBits(shape
,NULL
,NULL
);
1646 swf_SetShapeBits(tag
,shape
);
1647 swf_ShapeSetAll(tag
,shape
,/*x*/0,/*y*/0,0,fsid
,0);
1648 swflastx
= swflasty
= 0;
1654 swf_ShapeSetEnd(tag
);
1657 myshapeid2
= ++currentswfid
;
1658 tag
= swf_InsertTag(tag
,ST_DEFINESHAPE3
);
1659 swf_ShapeNew(&shape
);
1660 rgb
.r
= rgb
.b
= rgb
.a
= rgb
.g
= 255;
1662 fsid
= swf_ShapeAddSolidFillStyle(shape
,&rgb
);
1663 swf_SetU16(tag
, myshapeid2
);
1664 r
.xmin
= (int)(xmin
*20);
1665 r
.ymin
= (int)(ymin
*20);
1666 r
.xmax
= (int)(xmax
*20);
1667 r
.ymax
= (int)(ymax
*20);
1668 swf_SetRect(tag
,&r
);
1669 swf_SetShapeStyles(tag
,shape
);
1670 swf_ShapeCountBits(shape
,NULL
,NULL
);
1671 swf_SetShapeBits(tag
,shape
);
1672 swf_ShapeSetAll(tag
,shape
,/*x*/0,/*y*/0,0,fsid
,0);
1673 swflastx
= swflasty
= 0;
1679 swf_ShapeSetEnd(tag
);
1683 tag
= swf_InsertTag(tag
,ST_DEFINEBUTTON
);
1684 swf_SetU16(tag
,buttonid
); //id
1685 swf_ButtonSetFlags(tag
, 0); //menu=no
1686 swf_ButtonSetRecord(tag
,0x01,myshapeid
,depth
,0,0);
1687 swf_ButtonSetRecord(tag
,0x02,myshapeid2
,depth
,0,0);
1688 swf_ButtonSetRecord(tag
,0x04,myshapeid2
,depth
,0,0);
1689 swf_ButtonSetRecord(tag
,0x08,myshapeid
,depth
,0,0);
1691 swf_ActionSet(tag
,actions1
);
1696 tag
= swf_InsertTag(tag
,ST_DEFINEBUTTON2
);
1697 swf_SetU16(tag
,buttonid
); //id
1698 swf_ButtonSetFlags(tag
, 0); //menu=no
1699 swf_ButtonSetRecord(tag
,0x01,myshapeid
,depth
,0,0);
1700 swf_ButtonSetRecord(tag
,0x02,myshapeid2
,depth
,0,0);
1701 swf_ButtonSetRecord(tag
,0x04,myshapeid2
,depth
,0,0);
1702 swf_ButtonSetRecord(tag
,0x08,myshapeid
,depth
,0,0);
1703 swf_SetU8(tag
,0); // end of button records
1704 swf_ButtonSetCondition(tag
, BC_IDLE_OVERUP
);
1705 swf_ActionSet(tag
,actions1
);
1707 swf_ButtonSetCondition(tag
, BC_OVERUP_IDLE
);
1708 swf_ActionSet(tag
,actions2
);
1710 swf_ButtonPostProcess(tag
, 2);
1713 swf_ButtonPostProcess(tag
, 1);
1717 tag
= swf_InsertTag(tag
,ST_PLACEOBJECT2
);
1719 if(posx
!=0 || posy
!=0) {
1721 swf_GetMatrix(0,&m
);
1722 m
.tx
= (int)(posx
*20);
1723 m
.ty
= (int)(posy
*20);
1724 swf_ObjectPlace(tag
, buttonid
, depth
++,&m
,0,0);
1727 swf_ObjectPlace(tag
, buttonid
, depth
++,0,0,0);
1731 static void drawimage(struct swfoutput
*obj
, int bitid
, int sizex
,int sizey
,
1732 double x1
,double y1
,
1733 double x2
,double y2
,
1734 double x3
,double y3
,
1735 double x4
,double y4
)
1741 struct plotxy p1
,p2
,p3
,p4
;
1743 double xmax
=x1
,ymax
=y1
,xmin
=x1
,ymin
=y1
;
1744 if(x2
>xmax
) xmax
=x2
;
1745 if(y2
>ymax
) ymax
=y2
;
1746 if(x2
<xmin
) xmin
=x2
;
1747 if(y2
<ymin
) ymin
=y2
;
1748 if(x3
>xmax
) xmax
=x3
;
1749 if(y3
>ymax
) ymax
=y3
;
1750 if(x3
<xmin
) xmin
=x3
;
1751 if(y3
<ymin
) ymin
=y3
;
1752 if(x4
>xmax
) xmax
=x4
;
1753 if(y4
>ymax
) ymax
=y4
;
1754 if(x4
<xmin
) xmin
=x4
;
1755 if(y4
<ymin
) ymin
=y4
;
1761 {p1
.x
= (int)(p1
.x
*20)/20.0;
1762 p1
.y
= (int)(p1
.y
*20)/20.0;
1763 p2
.x
= (int)(p2
.x
*20)/20.0;
1764 p2
.y
= (int)(p2
.y
*20)/20.0;
1765 p3
.x
= (int)(p3
.x
*20)/20.0;
1766 p3
.y
= (int)(p3
.y
*20)/20.0;
1767 p4
.x
= (int)(p4
.x
*20)/20.0;
1768 p4
.y
= (int)(p4
.y
*20)/20.0;}
1771 m
.sx
= (int)(65536*20*(p4
.x
-p1
.x
)/sizex
);
1772 m
.r1
= -(int)(65536*20*(p4
.y
-p1
.y
)/sizex
);
1773 m
.r0
= (int)(65536*20*(p1
.x
-p2
.x
)/sizey
);
1774 m
.sy
= -(int)(65536*20*(p1
.y
-p2
.y
)/sizey
);
1776 m
.tx
= (int)(p1
.x
*20);
1777 m
.ty
= (int)(p1
.y
*20);
1780 myshapeid
= ++currentswfid
;
1781 tag
= swf_InsertTag(tag
,ST_DEFINESHAPE
);
1782 swf_ShapeNew(&shape
);
1783 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1784 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1785 fsid
= swf_ShapeAddBitmapFillStyle(shape
,&m
,bitid
,1);
1786 swf_SetU16(tag
, myshapeid
);
1787 r
.xmin
= (int)(xmin
*20);
1788 r
.ymin
= (int)(ymin
*20);
1789 r
.xmax
= (int)(xmax
*20);
1790 r
.ymax
= (int)(ymax
*20);
1791 swf_SetRect(tag
,&r
);
1792 swf_SetShapeStyles(tag
,shape
);
1793 swf_ShapeCountBits(shape
,NULL
,NULL
);
1794 swf_SetShapeBits(tag
,shape
);
1795 swf_ShapeSetAll(tag
,shape
,/*x*/0,/*y*/0,lsid
,fsid
,0);
1796 swflastx
= swflasty
= 0;
1803 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1804 ShapeSetLine (tag, shape, (int)(x1*20);
1805 ShapeSetLine (tag, shape, x*20,0);
1806 ShapeSetLine (tag, shape, 0,-y*20);
1807 ShapeSetLine (tag, shape, -x*20,0);*/
1808 swf_ShapeSetEnd(tag
);
1811 tag
= swf_InsertTag(tag
,ST_PLACEOBJECT2
);
1812 swf_ObjectPlace(tag
,myshapeid
,/*depth*/depth
++,NULL
,NULL
,NULL
);
1815 int swfoutput_drawimagejpeg_old(struct swfoutput
*obj
, char*filename
, int sizex
,int sizey
,
1816 double x1
,double y1
,
1817 double x2
,double y2
,
1818 double x3
,double y3
,
1819 double x4
,double y4
)
1827 int bitid
= ++currentswfid
;
1829 tag
= swf_InsertTag(tag
,ST_DEFINEBITSJPEG2
);
1830 swf_SetU16(tag
, bitid
);
1831 if(swf_SetJPEGBits(tag
, filename
, jpegquality
)<0) {
1837 drawimage(obj
, bitid
, sizex
, sizey
, x1
,y1
,x2
,y2
,x3
,y3
,x4
,y4
);
1841 int swfoutput_drawimagejpeg(struct swfoutput
*obj
, RGBA
*mem
, int sizex
,int sizey
,
1842 double x1
,double y1
,
1843 double x2
,double y2
,
1844 double x3
,double y3
,
1845 double x4
,double y4
)
1855 int bitid
= ++currentswfid
;
1857 tag
= swf_InsertTag(tag
,ST_DEFINEBITSJPEG2
);
1858 swf_SetU16(tag
, bitid
);
1859 swf_SetJPEGBits2(tag
,sizex
,sizey
,mem
,jpegquality
);
1860 drawimage(obj
, bitid
, sizex
, sizey
, x1
,y1
,x2
,y2
,x3
,y3
,x4
,y4
);
1864 int swfoutput_drawimagelossless(struct swfoutput
*obj
, RGBA
*mem
, int sizex
,int sizey
,
1865 double x1
,double y1
,
1866 double x2
,double y2
,
1867 double x3
,double y3
,
1868 double x4
,double y4
)
1876 int bitid
= ++currentswfid
;
1878 tag
= swf_InsertTag(tag
,ST_DEFINEBITSLOSSLESS
);
1879 swf_SetU16(tag
, bitid
);
1880 if(swf_SetLosslessBits(tag
,sizex
,sizey
,mem
, BMF_32BIT
)<0) {
1886 drawimage(obj
, bitid
, sizex
, sizey
, x1
,y1
,x2
,y2
,x3
,y3
,x4
,y4
);
1890 int swfoutput_drawimagelosslessN(struct swfoutput
*obj
, U8
*mem
, RGBA
*pal
, int sizex
,int sizey
,
1891 double x1
,double y1
,
1892 double x2
,double y2
,
1893 double x3
,double y3
,
1894 double x4
,double y4
, int n
)
1905 /* SWF expects scanlines to be 4 byte aligned */
1908 mem2
= (U8
*)malloc(BYTES_PER_SCANLINE(sizex
)*sizey
);
1910 for(y
=0;y
<sizey
;y
++)
1912 for(x
=0;x
<sizex
;x
++)
1913 *ptr
++ = mem
[y
*sizex
+x
];
1914 ptr
+= BYTES_PER_SCANLINE(sizex
)-sizex
;
1919 int bitid
= ++currentswfid
;
1921 tag
= swf_InsertTag(tag
,ST_DEFINEBITSLOSSLESS2
);
1922 swf_SetU16(tag
, bitid
);
1923 if(swf_SetLosslessBitsIndexed(tag
,sizex
,sizey
,mem
, pal
, n
)<0) {
1931 drawimage(obj
, bitid
, sizex
, sizey
, x1
,y1
,x2
,y2
,x3
,y3
,x4
,y4
);
1935 void swfoutput_drawimageagain(struct swfoutput
*obj
, int id
, int sizex
,int sizey
,
1936 double x1
,double y1
,
1937 double x2
,double y2
,
1938 double x3
,double y3
,
1939 double x4
,double y4
)
1947 drawimage(obj
, id
, sizex
, sizey
, x1
,y1
,x2
,y2
,x3
,y3
,x4
,y4
);