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"
39 #define standardEncodingSize 335
40 extern char *standardEncodingNames[standardEncodingSize];
43 int ignoredraworder=0;
46 int storeallcharacters=0;
51 int fontsplinemaxerror=1;
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 drawmode = -1;
71 static char storefont = 0;
72 static int fillstyleid;
73 static int linestyleid;
74 static int swflastx=0;
75 static int swflasty=0;
76 static int lastwasfill = 0;
88 char fillstylechanged = 0;
90 static void startshape(struct swfoutput* obj);
91 static void starttext(struct swfoutput* obj);
92 static void endshape();
93 static void endtext();
95 // matrix multiplication. changes p0
96 static void transform (plotxy*p0,struct swfmatrix*m)
99 x = m->m11*p0->x+m->m12*p0->y;
100 y = m->m21*p0->x+m->m22*p0->y;
105 // write a move-to command into the swf
106 static int moveto(TAG*tag, plotxy p0)
108 int rx = (int)(p0.x*20);
109 int ry = (int)(p0.y*20);
110 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
111 swf_ShapeSetMove (tag, shape, rx,ry);
112 fillstylechanged = 0;
120 // write a line-to command into the swf
121 static void lineto(TAG*tag, plotxy p0)
123 int rx = ((int)(p0.x*20)-swflastx);
124 int ry = ((int)(p0.y*20)-swflasty);
125 /* we can't skip this for rx=0,ry=0, those
127 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);
147 /* write a line, given two points and the transformation
149 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
157 /* write a cubic (!) spline. This involves calling the approximate()
158 function out of spline.cc to convert it to a quadratic spline. */
159 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
162 struct qspline q[128];
176 /* fonts use a different approximation than shapes */
177 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
178 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
180 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
184 moveto(tag,q[t].start);
185 splineto(tag,q[t].control, q[t].end);
195 static void stopFill()
199 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
200 fillstylechanged = 1;
204 static void startFill()
208 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
209 fillstylechanged = 1;
214 /* draw a T1 outline. These are generated by pdf2swf and by t1lib
215 (representing characters). */
216 void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log)
218 if(tag->id != ST_DEFINEFONT &&
219 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 == T1_PATHTYPE_MOVE)
237 if(((int)(lastx*20) != (int)(firstx*20) ||
238 (int)(lasty*20) != (int)(firsty*20)) &&
247 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
248 line(tag, p0, p1, m);
254 else if(outline->type == T1_PATHTYPE_LINE)
262 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
265 else if(outline->type == T1_PATHTYPE_BEZIER)
271 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
274 p1.x=o2->C.x/(float)0xffff+lastx;
275 p1.y=o2->C.y/(float)0xffff+lasty;
276 p2.x=o2->B.x/(float)0xffff+lastx;
277 p2.y=o2->B.y/(float)0xffff+lasty;
280 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
281 spline(tag,p0,p1,p2,p3,m);
284 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
288 outline = outline->link;
290 if(((int)(lastx*20) != (int)(firstx*20) ||
291 (int)(lasty*20) != (int)(firsty*20)) &&
300 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
301 line(tag, p0, p1, m);
305 plotxy getPivot(T1_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
307 T1_PATHPOINT next, next2;
308 double xv=0,yv=0, xv2=0, yv2=0;
313 if(outline->type == T1_PATHTYPE_LINE) {
314 next = outline->dest;
316 next = ((T1_BEZIERSEGMENT*)outline)->B;
317 if(next.x==0 && next.y==0) {
318 next = ((T1_BEZIERSEGMENT*)outline)->C;
320 if(next.x==0 && next.y==0) {
321 next = ((T1_BEZIERSEGMENT*)outline)->dest;
325 if(trytwo && outline->last && outline->last->type != T1_PATHTYPE_MOVE) {
326 if(outline->type == T1_PATHTYPE_LINE) {
327 next2 = outline->last->dest;
329 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)(outline->last))->C;
330 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)(outline->last))->B;
331 next2.x = outline->last->dest.x - c.x;
332 next2.y = outline->last->dest.y - c.y;
333 if(next2.x==0 && next2.y==0) {
334 next2.x = outline->last->dest.x - b.x;
335 next2.y = outline->last->dest.y - b.y;
337 if(next2.x==0 && next2.y==0) {
338 next2.x = outline->last->dest.x;
339 next2.y = outline->last->dest.y;
345 if(outline->type == T1_PATHTYPE_LINE) {
346 next = outline->dest;
348 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)outline)->C;
349 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)outline)->B;
350 next.x = outline->dest.x - c.x;
351 next.y = outline->dest.y - c.y;
352 if(next.x==0 && next.y==0) {
353 next.x = outline->dest.x - b.x;
354 next.y = outline->dest.y - b.y;
356 if(next.x==0 && next.y==0) {
357 next.x = outline->dest.x;
358 next.y = outline->dest.y;
362 if(trytwo && outline->link && outline->link->type != T1_PATHTYPE_MOVE) {
363 if(outline->type == T1_PATHTYPE_LINE) {
364 next2 = outline->link->dest;
366 next2 = ((T1_BEZIERSEGMENT*)(outline->link))->B;
367 if(next2.x==0 && next2.y==0) {
368 next2 = ((T1_BEZIERSEGMENT*)outline->link)->C;
370 if(next2.x==0 && next2.y==0) {
371 next2 = ((T1_BEZIERSEGMENT*)outline->link)->dest;
379 xv = next.y/(float)0xffff;
380 yv = -next.x/(float)0xffff;
382 xv = -next.y/(float)0xffff;
383 yv = next.x/(float)0xffff;
386 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
392 xv2 = next2.y/(float)0xffff;
393 yv2 = -next2.x/(float)0xffff;
395 xv2 = -next2.y/(float)0xffff;
396 yv2 = next2.x/(float)0xffff;
399 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
404 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
414 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline)
416 double lastx=x, lasty=y;
417 while (outline && outline->type != T1_PATHTYPE_MOVE)
419 x += (outline->dest.x/(float)0xffff);
420 y += (outline->dest.y/(float)0xffff);
422 if(outline->type == T1_PATHTYPE_LINE)
429 line(tag, p0, p1, m);
431 else if(outline->type == T1_PATHTYPE_BEZIER)
434 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
437 p1.x=o2->C.x/(float)0xffff+lastx;
438 p1.y=o2->C.y/(float)0xffff+lasty;
439 p2.x=o2->B.x/(float)0xffff+lastx;
440 p2.y=o2->B.y/(float)0xffff+lasty;
443 spline(tag,p0,p1,p2,p3,m);
447 outline = outline->link;
451 void drawShortPathWithEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
456 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
459 T1_OUTLINE *last, *tmp=outline;
460 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
466 while(tmp && tmp->type != T1_PATHTYPE_MOVE) {
468 lx += (tmp->dest.x/(float)0xffff);
469 ly += (tmp->dest.y/(float)0xffff);
472 s = getPivot(outline, 0, line_width, 0, 0);
473 e = getPivot(last, 0, line_width, 1, 0);
475 if(line_cap == LINE_CAP_BUTT) {
476 /* make the clipping rectangle slighly bigger
477 than the line ending, so that it get's clipped
487 p2.x = x2 - s.y - s.x*ee;
488 p2.y = y2 + s.x - s.y*ee;
489 p3.x = x2 - s.y + s.x*ee;
490 p3.y = y2 + s.x + s.y*ee;
495 m2.x = lx + e.y - e.x*ee;
496 m2.y = ly - e.x - e.y*ee;
497 m3.x = lx + e.y + e.x*ee;
498 m3.y = ly - e.x + e.y*ee;
500 for(nr=0;nr<2;nr++) {
502 struct plotxy q0,q1,q2,q3,q4,q5;
504 if(line_cap == LINE_CAP_BUTT) {
507 q1.x = sizex; q1.y = 0;
508 q2.x = sizex; q2.y = sizey;
509 q3.x = 0; q3.y = sizey;
511 q0.x = sizex; q0.y = sizey;
512 q1.x = 0; q1.y = sizey;
514 q3.x = sizex; q3.y = 0;
528 line(tag, p0, p1, m);
529 line(tag, p1, p2, m);
530 line(tag, p2, p3, m);
531 line(tag, p3, p0, m);
533 if(line_cap == LINE_CAP_BUTT) {
535 swf_ShapeSetEnd(tag);
536 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
537 swf_ObjectPlaceClip(tag,shapeid,depth,NULL,NULL,NULL,depth+2-nr);
551 drawShortPath(output,x,y,m,outline);
553 if(line_cap == LINE_CAP_BUTT) {
559 void drawT1toRect(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
561 plotxy d1,d2,p1,p2,p3,p4;
563 d1.x = (outline->dest.x/(float)0xffff);
564 d1.y = (outline->dest.y/(float)0xffff);
565 d2 = getPivot(outline, 0, line_width, 0, 0);
567 assert(line_cap != LINE_CAP_ROUND);
568 if(line_cap == LINE_CAP_SQUARE) {
577 p2.x = x + d2.x + d1.x;
578 p2.y = y + d2.y + d1.y;
579 p3.x = x - d2.x + d1.x;
580 p3.y = y - d2.y + d1.y;
590 void drawShortPathWithStraightEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
592 T1_OUTLINE*tmp=outline;
598 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
600 while(tmp->link && tmp->link->type!=T1_PATHTYPE_MOVE) {
601 xx += (tmp->dest.x/(float)0xffff);
602 yy += (tmp->dest.y/(float)0xffff);
606 assert(tmp->type == T1_PATHTYPE_LINE);
607 assert(outline->type == T1_PATHTYPE_LINE);
611 if(outline->link == tmp) {
612 /* the two straight line segments (which are everything we
613 need to draw) are very likely to overlap. To avoid that
614 they cancel each other out at the end points, start a new
615 shape for the second one */
616 endshape();startshape(output);
620 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
622 if(outline->link != tmp)
626 tmp->type = T1_PATHTYPE_MOVE;
627 x += (outline->dest.x/(float)0xffff);
628 y += (outline->dest.y/(float)0xffff);
629 outline = outline->link;
630 drawShortPath(output, x, y, m, outline);
638 static int t1len(T1_OUTLINE*line)
641 while(line && line->type != T1_PATHTYPE_MOVE) {
648 static float t1linelen(T1_OUTLINE*line)
651 x = (line->dest.x/(float)0xffff);
652 y = (line->dest.y/(float)0xffff);
653 return sqrt(x*x+y*y);
656 void drawpath2poly(struct swfoutput *output, T1_OUTLINE*outline, struct swfmatrix*m, int log, int line_join, int line_cap, double line_width, double miter_limit)
658 if(tag->id != ST_DEFINEFONT &&
659 tag->id != ST_DEFINESHAPE &&
660 tag->id != ST_DEFINESHAPE2 &&
661 tag->id != ST_DEFINESHAPE3) {
662 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
667 double lastx=0,lasty=0;
670 T1_OUTLINE*tmp = outline, *last = 0;
675 x += (tmp->dest.x/(float)0xffff);
676 y += (tmp->dest.y/(float)0xffff);
678 if(!tmp || tmp->type == T1_PATHTYPE_MOVE) {
680 if(last->type == T1_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
681 lastwasline && line_cap != LINE_CAP_ROUND)
682 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
684 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
698 if(tmp && tmp->type == T1_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
704 tmp->link->last = tmp; // make sure list is properly linked in both directions
709 static inline int colorcompare(RGBA*a,RGBA*b)
721 static const int CHARDATAMAX = 1024;
729 } chardata[CHARDATAMAX];
732 static void putcharacters(TAG*tag)
737 color.r = chardata[0].color.r^255;
746 int charadvance[128];
749 int glyphbits=1; //TODO: can this be zero?
752 if(tag->id != ST_DEFINETEXT &&
753 tag->id != ST_DEFINETEXT2) {
754 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
758 msg("<warning> putcharacters called with zero characters");
761 for(pass = 0; pass < 2; pass++)
771 advancebits++; // add sign bit
772 swf_SetU8(tag, glyphbits);
773 swf_SetU8(tag, advancebits);
776 for(t=0;t<=chardatapos;t++)
778 if(lastfontid != chardata[t].fontid ||
779 lastx!=chardata[t].x ||
780 lasty!=chardata[t].y ||
781 !colorcompare(&color, &chardata[t].color) ||
783 lastsize != chardata[t].size ||
786 if(charstorepos && pass==0)
789 for(s=0;s<charstorepos;s++)
791 while(charids[s]>=(1<<glyphbits))
793 while(charadvance[s]>=(1<<advancebits))
797 if(charstorepos && pass==1)
799 tag->writeBit = 0; // Q&D
800 swf_SetBits(tag, 0, 1); // GLYPH Record
801 swf_SetBits(tag, charstorepos, 7); // number of glyphs
803 for(s=0;s<charstorepos;s++)
805 swf_SetBits(tag, charids[s], glyphbits);
806 swf_SetBits(tag, charadvance[s], advancebits);
811 if(pass == 1 && t<chardatapos)
817 if(lastx != chardata[t].x ||
818 lasty != chardata[t].y)
823 if(!colorcompare(&color, &chardata[t].color))
825 color = chardata[t].color;
828 font.id = chardata[t].fontid;
829 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
832 tag->writeBit = 0; // Q&D
833 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
836 lastfontid = chardata[t].fontid;
837 lastx = chardata[t].x;
838 lasty = chardata[t].y;
839 lastsize = chardata[t].size;
846 int nextt = t==chardatapos-1?t:t+1;
847 int rel = chardata[nextt].x-chardata[t].x;
848 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
850 lastx=chardata[nextt].x;
856 charids[charstorepos] = chardata[t].charid;
857 charadvance[charstorepos] = advance;
864 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
865 int x,int y, int size)
867 if(chardatapos == CHARDATAMAX)
872 chardata[chardatapos].fontid = fontid;
873 chardata[chardatapos].charid = charid;
874 chardata[chardatapos].x = x;
875 chardata[chardatapos].y = y;
876 chardata[chardatapos].color = obj->fillrgb;
877 chardata[chardatapos].size = size;
882 /* process a character. */
883 static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m)
886 if(m->m12!=0 || m->m21!=0)
891 if(usefonts && ! drawonlyshapes)
893 int charid = font->getSWFCharID(character, charnr);
898 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
899 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
903 T1_OUTLINE*outline = font->getOutline(character, charnr);
904 char* charname = character;
907 msg("<warning> Didn't find %s in current charset (%s)",
908 FIXNULL(character),FIXNULL(font->getName()));
927 drawpath(tag, outline, &m2, 0);
932 /* draw a curved polygon. */
933 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
939 /* Multiple polygons in one shape don't overlap correctly,
940 so we better start a new shape here if the polygon is filled
942 if(shapeid>=0 && fill && !ignoredraworder) {
954 drawpath(tag, outline,m, 0);
957 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
967 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
970 /* SWFFont: copy all t1 font outlines to a local
972 SWFFont::SWFFont(char*name, int id, char*filename)
974 if(!T1_GetFontName(id))
977 this->name = strdup(T1_GetFontFileName(id));
978 this->fontid = strdup(name);
981 char**a= T1_GetAllCharNames(id);
992 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
994 this->standardtablesize = 256;
995 if(this->charnum < this->standardtablesize)
996 this->standardtablesize = this->charnum;
997 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
999 for(t = 0; t < this->standardtablesize; t++) {
1000 char*name = T1_GetCharName(id,t);
1003 standardtable[t] = strdup(name);
1006 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1007 charname = (char**)malloc(charnum*sizeof(char*));
1008 width = (int*)malloc(charnum*sizeof(int));
1009 memset(width, 0, charnum*sizeof(int));
1010 memset(charname, 0, charnum*sizeof(char*));
1011 used = (char*)malloc(charnum*sizeof(char));
1012 char2swfcharid = (U16*)malloc(charnum*2);
1013 swfcharid2char = (U16*)malloc(charnum*2);
1016 memset(used,0,charnum*sizeof(char));
1018 this->swfid = ++currentswfid;
1031 int ret = T1_ReencodeFont(id, map);
1035 int ret = T1_ReencodeFont(id, map);
1037 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1043 char* name = T1_GetCharName(id, s);
1044 if(!name) name = "";
1045 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1046 this->width[outlinepos] = T1_GetCharWidth(id, s);
1047 this->charname[outlinepos] = strdup(name);
1055 /* free all tables, write out definefont tags */
1061 if(storeallcharacters)
1064 for(t=0;t<this->charnum;t++)
1066 if(this->charname[t])
1067 getSWFCharID(this->charname[t], -1);
1071 ptr = (int*)malloc(swfcharpos*sizeof(int));
1073 for(t=0;t<charnum;t++)
1074 if(used[t]) usednum++;
1076 if(usednum && !drawonlyshapes)
1078 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1079 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1080 swf_SetU16(ftag, this->swfid);
1081 int initpos = swf_GetTagLen(ftag);
1088 for(t=0;t<swfcharpos;t++)
1090 ptr[t] = swf_GetTagLen(ftag);
1091 swf_SetU16(ftag, 0x1234);
1093 for(t=0;t<swfcharpos;t++)
1095 *(U16*)&ftag->data[ptr[t]] =
1096 SWAP16(swf_GetTagLen(ftag)-initpos);
1100 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1104 swf_ShapeSetStyle(ftag,&s,0,1,0);
1105 fillstylechanged = 1;
1106 int lastfill = fill;
1109 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1112 swf_ShapeSetEnd(ftag);
1114 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1115 swf_SetU16(ftag, this->swfid);
1117 swf_SetU8(ftag, strlen(this->fontid));
1118 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1122 swf_SetU8(ftag, 0); //flags
1123 for(t=0;t<swfcharpos;t++)
1126 char * name = this->charname[this->swfcharid2char[t]];
1127 for(s=0;s<256;s++) {
1128 if(standardEncodingNames[s] &&
1129 !strcmp(name,standardEncodingNames[s]))
1132 swf_SetU8(ftag, (U8)s);
1138 for(t=0;t<charnum;t++)
1140 for(t=0;t<standardtablesize;t++)
1141 if(standardtable[t]) {
1142 free(standardtable[t]);
1144 free(standardtable);
1148 free(swfcharid2char);
1149 free(char2swfcharid);
1152 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1155 for(t=0;t<this->charnum;t++) {
1156 if(!strcmp(this->charname[t],name)) {
1161 /* if we didn't find the character, maybe
1162 we can find the capitalized version */
1163 for(t=0;t<this->charnum;t++) {
1164 if(!strcasecmp(this->charname[t],name))
1168 /* if we didn't find it by name, use the names of the first 256 characters
1169 of the font to try a new name based on charnr */
1170 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1171 return getOutline(this->standardtable[charnr], -1);
1174 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1178 int SWFFont::getSWFCharID(char*name, int charnr)
1181 for(t=0;t<this->charnum;t++) {
1182 if(!strcmp(this->charname[t],name)) {
1185 swfcharid2char[swfcharpos] = t;
1186 char2swfcharid[t] = swfcharpos++;
1189 return char2swfcharid[t];
1193 /* if we didn't find the character, maybe
1194 we can find the capitalized version */
1195 for(t=0;t<this->charnum;t++) {
1196 if(!strcasecmp(this->charname[t],name)) {
1199 swfcharid2char[swfcharpos] = t;
1200 char2swfcharid[t] = swfcharpos++;
1203 return char2swfcharid[t];
1207 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1208 of the font to try a new name based on charnr */
1209 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1210 return getSWFCharID(this->standardtable[charnr], -1);
1212 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1216 int SWFFont::getWidth(char*name)
1219 for(t=0;t<this->charnum;t++) {
1220 if(!strcmp(this->charname[t],name)) {
1221 return this->width[t];
1227 char*SWFFont::getName()
1238 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1239 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1241 fontlist_t*last=0,*iterator;
1242 if(obj->font && !strcmp(obj->font->fontid,fontid))
1245 iterator = fontlist;
1247 if(!strcmp(iterator->font->fontid,fontid))
1250 iterator = iterator->next;
1254 obj->font = iterator->font;
1259 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1262 SWFFont*font = new SWFFont(fontid, t1id, filename);
1263 iterator = new fontlist_t;
1264 iterator->font = font;
1268 last->next = iterator;
1270 fontlist = iterator;
1274 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1276 fontlist_t *iterator = fontlist;
1278 if(!strcmp(iterator->font->fontid,fontid))
1280 iterator = iterator->next;
1285 /* set's the matrix which is to be applied to characters drawn by
1286 swfoutput_drawchar() */
1287 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1288 double m21,double m22)
1290 if(obj->fontm11 == m11 &&
1291 obj->fontm12 == m12 &&
1292 obj->fontm21 == m21 &&
1293 obj->fontm22 == m22)
1303 /* draws a character at x,y. */
1304 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1307 m.m11 = obj->fontm11;
1308 m.m12 = obj->fontm12;
1309 m.m21 = obj->fontm21;
1310 m.m22 = obj->fontm22;
1313 drawchar(obj, obj->font, character, charnr, &m);
1316 /* initialize the swf writer */
1317 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1322 memset(obj, 0, sizeof(struct swfoutput));
1323 filename = _filename;
1327 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1331 memset(&swf,0x00,sizeof(SWF));
1333 swf.fileVersion = flashversion;
1334 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1335 swf.movieSize.xmax = 20*sizex;
1336 swf.movieSize.ymax = 20*sizey;
1338 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1343 swf_SetRGB(tag,&rgb);
1344 if(flag_protected) // good practice! /r
1345 tag = swf_InsertTag(tag, ST_PROTECT);
1350 void swfoutput_setprotected() //write PROTECT tag
1355 static void startshape(struct swfoutput*obj)
1363 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1365 swf_ShapeNew(&shape);
1366 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1367 rgb.r = obj->fillrgb.r;
1368 rgb.g = obj->fillrgb.g;
1369 rgb.b = obj->fillrgb.b;
1370 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1372 shapeid = ++currentswfid;
1373 swf_SetU16(tag,shapeid); // ID
1380 swf_SetRect(tag,&r);
1382 swf_SetShapeStyles(tag,shape);
1383 swf_ShapeCountBits(shape,NULL,NULL);
1384 swf_SetShapeBits(tag,shape);
1386 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1387 swflastx=swflasty=0;
1391 static void starttext(struct swfoutput*obj)
1397 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1398 textid = ++currentswfid;
1399 swf_SetU16(tag, textid);
1406 swf_SetRect(tag,&r);
1415 swf_SetMatrix(tag,&m);
1416 swflastx=swflasty=0;
1419 static void endshape()
1423 swf_ShapeSetEnd(tag);
1424 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1425 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1429 static void endtext()
1435 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1436 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1440 static void endpage(struct swfoutput*obj)
1447 swfoutput_endclip(obj);
1451 atag = action_Stop(atag);
1452 atag = action_End(atag);
1453 tag = swf_InsertTag(tag,ST_DOACTION);
1454 swf_ActionSet(tag,atag);
1456 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1459 void swfoutput_newpage(struct swfoutput*obj)
1463 for(depth--;depth>=startdepth;depth--) {
1464 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1465 swf_SetU16(tag,depth);
1472 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1473 up, complete the swf, and write it out. */
1474 void swfoutput_destroy(struct swfoutput* obj)
1477 fontlist_t *tmp,*iterator = fontlist;
1479 delete iterator->font;
1482 iterator = iterator->next;
1490 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1495 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1499 tag = swf_InsertTag(tag,ST_END);
1502 if FAILED(swf_WriteSWC(fi,&swf))
1503 msg("<error> WriteSWC() failed.\n");
1505 if FAILED(swf_WriteSWF(fi,&swf))
1506 msg("<error> WriteSWF() failed.\n");
1511 msg("<notice> SWF written\n");
1514 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1517 if(mode == DRAWMODE_FILL)
1519 else if(mode == DRAWMODE_EOFILL)
1521 else if(mode == DRAWMODE_STROKE)
1523 else if(mode == DRAWMODE_CLIP)
1525 else if(mode == DRAWMODE_EOCLIP)
1529 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1531 if(obj->fillrgb.r == r &&
1532 obj->fillrgb.g == g &&
1533 obj->fillrgb.b == b &&
1534 obj->fillrgb.a == a) return;
1544 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1546 if(obj->strokergb.r == r &&
1547 obj->strokergb.g == g &&
1548 obj->strokergb.b == b &&
1549 obj->strokergb.a == a) return;
1553 obj->strokergb.r = r;
1554 obj->strokergb.g = g;
1555 obj->strokergb.b = b;
1556 obj->strokergb.a = a;
1559 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1561 if(obj->linewidth == (u16)(linewidth*20))
1566 obj->linewidth = (u16)(linewidth*20);
1570 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1579 msg("<warning> Too many clip levels.");
1584 int olddrawmode = drawmode;
1585 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1586 swfoutput_drawpath(obj, outline, m);
1587 swf_ShapeSetEnd(tag);
1588 swfoutput_setdrawmode(obj, olddrawmode);
1590 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1591 cliptags[clippos] = tag;
1592 clipshapes[clippos] = shapeid;
1593 clipdepths[clippos] = depth++;
1598 void swfoutput_endclip(swfoutput*obj)
1606 msg("<error> Invalid end of clipping region");
1610 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1613 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1615 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1618 if(!strncmp("http://pdf2swf:", url, 15)) {
1619 char*tmp = strdup(url);
1620 int l = strlen(tmp);
1623 swfoutput_namedlink(obj, tmp+15, points);
1634 actions = action_GetUrl(0, url, "_parent");
1636 actions = action_GetUrl(0, url, "_this");
1637 actions = action_End(actions);
1639 drawlink(obj, actions, 0, points,0);
1641 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1650 actions = action_GotoFrame(0, page);
1651 actions = action_End(actions);
1653 drawlink(obj, actions, 0, points,0);
1656 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1657 of the viewer objects, like subtitles, index elements etc.
1659 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1661 ActionTAG *actions1,*actions2;
1662 char*tmp = strdup(name);
1670 if(!strncmp(tmp, "call:", 5))
1672 char*x = strchr(&tmp[5], ':');
1674 actions1 = action_PushInt(0, 0); //number of parameters (0)
1675 actions1 = action_PushString(actions1, &tmp[5]); //function name
1676 actions1 = action_CallFunction(actions1);
1679 actions1 = action_PushString(0, x+1); //parameter
1680 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1681 actions1 = action_PushString(actions1, &tmp[5]); //function name
1682 actions1 = action_CallFunction(actions1);
1684 actions2 = action_End(0);
1689 actions1 = action_PushString(0, "/:subtitle");
1690 actions1 = action_PushString(actions1, name);
1691 actions1 = action_SetVariable(actions1);
1692 actions1 = action_End(actions1);
1694 actions2 = action_PushString(0, "/:subtitle");
1695 actions2 = action_PushString(actions2, "");
1696 actions2 = action_SetVariable(actions2);
1697 actions2 = action_End(actions2);
1700 drawlink(obj, actions1, actions2, points,mouseover);
1702 swf_ActionFree(actions1);
1703 swf_ActionFree(actions2);
1707 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1713 struct plotxy p1,p2,p3,p4;
1717 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1721 int buttonid = ++currentswfid;
1724 if(points[t].x>xmax) xmax=points[t].x;
1725 if(points[t].y>ymax) ymax=points[t].y;
1726 if(points[t].x<xmin) xmin=points[t].x;
1727 if(points[t].y<ymin) ymin=points[t].y;
1730 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1731 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1733 /* the following code subtracts the upper left edge from all coordinates,
1734 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1735 Necessary for preprocessing with swfcombine. */
1736 posx = xmin; posy = ymin;
1737 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1738 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1739 xmin -= posx; ymin -= posy;
1740 xmax -= posx; ymax -= posy;
1743 myshapeid = ++currentswfid;
1744 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1745 swf_ShapeNew(&shape);
1746 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1747 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1748 swf_SetU16(tag, myshapeid);
1749 r.xmin = (int)(xmin*20);
1750 r.ymin = (int)(ymin*20);
1751 r.xmax = (int)(xmax*20);
1752 r.ymax = (int)(ymax*20);
1753 swf_SetRect(tag,&r);
1754 swf_SetShapeStyles(tag,shape);
1755 swf_ShapeCountBits(shape,NULL,NULL);
1756 swf_SetShapeBits(tag,shape);
1757 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1758 swflastx = swflasty = 0;
1764 swf_ShapeSetEnd(tag);
1767 myshapeid2 = ++currentswfid;
1768 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1769 swf_ShapeNew(&shape);
1770 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1772 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1773 swf_SetU16(tag, myshapeid2);
1774 r.xmin = (int)(xmin*20);
1775 r.ymin = (int)(ymin*20);
1776 r.xmax = (int)(xmax*20);
1777 r.ymax = (int)(ymax*20);
1778 swf_SetRect(tag,&r);
1779 swf_SetShapeStyles(tag,shape);
1780 swf_ShapeCountBits(shape,NULL,NULL);
1781 swf_SetShapeBits(tag,shape);
1782 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1783 swflastx = swflasty = 0;
1789 swf_ShapeSetEnd(tag);
1793 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1794 swf_SetU16(tag,buttonid); //id
1795 swf_ButtonSetFlags(tag, 0); //menu=no
1796 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1797 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1798 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1799 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1801 swf_ActionSet(tag,actions1);
1806 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1807 swf_SetU16(tag,buttonid); //id
1808 swf_ButtonSetFlags(tag, 0); //menu=no
1809 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1810 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1811 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1812 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1813 swf_SetU8(tag,0); // end of button records
1814 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1815 swf_ActionSet(tag,actions1);
1817 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1818 swf_ActionSet(tag,actions2);
1820 swf_ButtonPostProcess(tag, 2);
1823 swf_ButtonPostProcess(tag, 1);
1827 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1829 if(posx!=0 || posy!=0) {
1831 swf_GetMatrix(0,&m);
1832 m.tx = (int)(posx*20);
1833 m.ty = (int)(posy*20);
1834 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1837 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1841 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1842 double x1,double y1,
1843 double x2,double y2,
1844 double x3,double y3,
1845 double x4,double y4)
1851 struct plotxy p1,p2,p3,p4;
1853 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1854 if(x2>xmax) xmax=x2;
1855 if(y2>ymax) ymax=y2;
1856 if(x2<xmin) xmin=x2;
1857 if(y2<ymin) ymin=y2;
1858 if(x3>xmax) xmax=x3;
1859 if(y3>ymax) ymax=y3;
1860 if(x3<xmin) xmin=x3;
1861 if(y3<ymin) ymin=y3;
1862 if(x4>xmax) xmax=x4;
1863 if(y4>ymax) ymax=y4;
1864 if(x4<xmin) xmin=x4;
1865 if(y4<ymin) ymin=y4;
1871 {p1.x = (int)(p1.x*20)/20.0;
1872 p1.y = (int)(p1.y*20)/20.0;
1873 p2.x = (int)(p2.x*20)/20.0;
1874 p2.y = (int)(p2.y*20)/20.0;
1875 p3.x = (int)(p3.x*20)/20.0;
1876 p3.y = (int)(p3.y*20)/20.0;
1877 p4.x = (int)(p4.x*20)/20.0;
1878 p4.y = (int)(p4.y*20)/20.0;}
1881 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1882 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1883 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1884 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1886 m.tx = (int)(p1.x*20);
1887 m.ty = (int)(p1.y*20);
1890 myshapeid = ++currentswfid;
1891 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1892 swf_ShapeNew(&shape);
1893 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1894 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1895 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1896 swf_SetU16(tag, myshapeid);
1897 r.xmin = (int)(xmin*20);
1898 r.ymin = (int)(ymin*20);
1899 r.xmax = (int)(xmax*20);
1900 r.ymax = (int)(ymax*20);
1901 swf_SetRect(tag,&r);
1902 swf_SetShapeStyles(tag,shape);
1903 swf_ShapeCountBits(shape,NULL,NULL);
1904 swf_SetShapeBits(tag,shape);
1905 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1906 swflastx = swflasty = 0;
1913 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1914 ShapeSetLine (tag, shape, (int)(x1*20);
1915 ShapeSetLine (tag, shape, x*20,0);
1916 ShapeSetLine (tag, shape, 0,-y*20);
1917 ShapeSetLine (tag, shape, -x*20,0);*/
1918 swf_ShapeSetEnd(tag);
1921 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1922 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1925 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1926 double x1,double y1,
1927 double x2,double y2,
1928 double x3,double y3,
1929 double x4,double y4)
1937 int bitid = ++currentswfid;
1939 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1940 swf_SetU16(tag, bitid);
1941 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1947 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1951 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1952 double x1,double y1,
1953 double x2,double y2,
1954 double x3,double y3,
1955 double x4,double y4)
1965 int bitid = ++currentswfid;
1967 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1968 swf_SetU16(tag, bitid);
1969 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1970 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1974 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1975 double x1,double y1,
1976 double x2,double y2,
1977 double x3,double y3,
1978 double x4,double y4)
1986 int bitid = ++currentswfid;
1988 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1989 swf_SetU16(tag, bitid);
1990 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
1996 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2000 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2001 double x1,double y1,
2002 double x2,double y2,
2003 double x3,double y3,
2004 double x4,double y4, int n)
2015 /* SWF expects scanlines to be 4 byte aligned */
2018 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2020 for(y=0;y<sizey;y++)
2022 for(x=0;x<sizex;x++)
2023 *ptr++ = mem[y*sizex+x];
2024 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2029 int bitid = ++currentswfid;
2031 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2032 swf_SetU16(tag, bitid);
2033 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2041 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2045 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2046 double x1,double y1,
2047 double x2,double y2,
2048 double x3,double y3,
2049 double x4,double y4)
2057 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);