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)
892 msg("<warning> Font is NULL");
895 if(usefonts && ! drawonlyshapes)
897 int charid = font->getSWFCharID(character, charnr);
902 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
903 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
907 T1_OUTLINE*outline = font->getOutline(character, charnr);
908 char* charname = character;
911 msg("<warning> Didn't find %s in current charset (%s)",
912 FIXNULL(character),FIXNULL(font->getName()));
931 drawpath(tag, outline, &m2, 0);
936 /* draw a curved polygon. */
937 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
943 /* Multiple polygons in one shape don't overlap correctly,
944 so we better start a new shape here if the polygon is filled
946 if(shapeid>=0 && fill && !ignoredraworder) {
958 drawpath(tag, outline,m, 0);
961 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
971 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
974 /* SWFFont: copy all t1 font outlines to a local
976 SWFFont::SWFFont(char*name, int id, char*filename)
978 if(!T1_GetFontName(id))
981 this->name = strdup(T1_GetFontFileName(id));
982 this->fontid = strdup(name);
985 char**a= T1_GetAllCharNames(id);
996 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
998 this->standardtablesize = 256;
999 if(this->charnum < this->standardtablesize)
1000 this->standardtablesize = this->charnum;
1001 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1003 for(t = 0; t < this->standardtablesize; t++) {
1004 char*name = T1_GetCharName(id,t);
1007 standardtable[t] = strdup(name);
1010 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1011 charname = (char**)malloc(charnum*sizeof(char*));
1012 width = (int*)malloc(charnum*sizeof(int));
1013 memset(width, 0, charnum*sizeof(int));
1014 memset(charname, 0, charnum*sizeof(char*));
1015 used = (char*)malloc(charnum*sizeof(char));
1016 char2swfcharid = (U16*)malloc(charnum*2);
1017 swfcharid2char = (U16*)malloc(charnum*2);
1020 memset(used,0,charnum*sizeof(char));
1022 this->swfid = ++currentswfid;
1035 int ret = T1_ReencodeFont(id, map);
1039 int ret = T1_ReencodeFont(id, map);
1041 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1047 char* name = T1_GetCharName(id, s);
1048 if(!name) name = "";
1049 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1050 this->width[outlinepos] = T1_GetCharWidth(id, s);
1051 this->charname[outlinepos] = strdup(name);
1059 /* free all tables, write out definefont tags */
1065 if(storeallcharacters)
1068 for(t=0;t<this->charnum;t++)
1070 if(this->charname[t])
1071 getSWFCharID(this->charname[t], -1);
1075 ptr = (int*)malloc(swfcharpos*sizeof(int));
1077 for(t=0;t<charnum;t++)
1078 if(used[t]) usednum++;
1080 if(usednum && !drawonlyshapes)
1082 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1083 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1084 swf_SetU16(ftag, this->swfid);
1085 int initpos = swf_GetTagLen(ftag);
1092 for(t=0;t<swfcharpos;t++)
1094 ptr[t] = swf_GetTagLen(ftag);
1095 swf_SetU16(ftag, 0x1234);
1097 for(t=0;t<swfcharpos;t++)
1099 *(U16*)&ftag->data[ptr[t]] =
1100 SWAP16(swf_GetTagLen(ftag)-initpos);
1104 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1108 swf_ShapeSetStyle(ftag,&s,0,1,0);
1109 fillstylechanged = 1;
1110 int lastfill = fill;
1113 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1116 swf_ShapeSetEnd(ftag);
1118 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1119 swf_SetU16(ftag, this->swfid);
1121 swf_SetU8(ftag, strlen(this->fontid));
1122 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1126 swf_SetU8(ftag, 0); //flags
1127 for(t=0;t<swfcharpos;t++)
1130 char * name = this->charname[this->swfcharid2char[t]];
1131 for(s=0;s<256;s++) {
1132 if(standardEncodingNames[s] &&
1133 !strcmp(name,standardEncodingNames[s]))
1136 swf_SetU8(ftag, (U8)s);
1142 for(t=0;t<charnum;t++)
1144 for(t=0;t<standardtablesize;t++)
1145 if(standardtable[t]) {
1146 free(standardtable[t]);
1148 free(standardtable);
1152 free(swfcharid2char);
1153 free(char2swfcharid);
1156 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1159 for(t=0;t<this->charnum;t++) {
1160 if(!strcmp(this->charname[t],name)) {
1165 /* if we didn't find the character, maybe
1166 we can find the capitalized version */
1167 for(t=0;t<this->charnum;t++) {
1168 if(!strcasecmp(this->charname[t],name))
1172 /* if we didn't find it by name, use the names of the first 256 characters
1173 of the font to try a new name based on charnr */
1174 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1175 return getOutline(this->standardtable[charnr], -1);
1178 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1182 int SWFFont::getSWFCharID(char*name, int charnr)
1185 for(t=0;t<this->charnum;t++) {
1186 if(!strcmp(this->charname[t],name)) {
1189 swfcharid2char[swfcharpos] = t;
1190 char2swfcharid[t] = swfcharpos++;
1193 return char2swfcharid[t];
1197 /* if we didn't find the character, maybe
1198 we can find the capitalized version */
1199 for(t=0;t<this->charnum;t++) {
1200 if(!strcasecmp(this->charname[t],name)) {
1203 swfcharid2char[swfcharpos] = t;
1204 char2swfcharid[t] = swfcharpos++;
1207 return char2swfcharid[t];
1211 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1212 of the font to try a new name based on charnr */
1213 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1214 return getSWFCharID(this->standardtable[charnr], -1);
1216 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1220 int SWFFont::getWidth(char*name)
1223 for(t=0;t<this->charnum;t++) {
1224 if(!strcmp(this->charname[t],name)) {
1225 return this->width[t];
1231 char*SWFFont::getName()
1242 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1243 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1245 fontlist_t*last=0,*iterator;
1246 if(obj->font && !strcmp(obj->font->fontid,fontid))
1249 iterator = fontlist;
1251 if(!strcmp(iterator->font->fontid,fontid))
1254 iterator = iterator->next;
1258 obj->font = iterator->font;
1263 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1266 SWFFont*font = new SWFFont(fontid, t1id, filename);
1267 iterator = new fontlist_t;
1268 iterator->font = font;
1272 last->next = iterator;
1274 fontlist = iterator;
1278 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1280 fontlist_t *iterator = fontlist;
1282 if(!strcmp(iterator->font->fontid,fontid))
1284 iterator = iterator->next;
1289 /* set's the matrix which is to be applied to characters drawn by
1290 swfoutput_drawchar() */
1291 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1292 double m21,double m22)
1294 if(obj->fontm11 == m11 &&
1295 obj->fontm12 == m12 &&
1296 obj->fontm21 == m21 &&
1297 obj->fontm22 == m22)
1307 /* draws a character at x,y. */
1308 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1311 m.m11 = obj->fontm11;
1312 m.m12 = obj->fontm12;
1313 m.m21 = obj->fontm21;
1314 m.m22 = obj->fontm22;
1317 drawchar(obj, obj->font, character, charnr, &m);
1320 /* initialize the swf writer */
1321 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1326 memset(obj, 0, sizeof(struct swfoutput));
1327 filename = _filename;
1331 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1335 memset(&swf,0x00,sizeof(SWF));
1337 swf.fileVersion = flashversion;
1338 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1339 swf.movieSize.xmax = 20*sizex;
1340 swf.movieSize.ymax = 20*sizey;
1342 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1347 swf_SetRGB(tag,&rgb);
1348 if(flag_protected) // good practice! /r
1349 tag = swf_InsertTag(tag, ST_PROTECT);
1354 void swfoutput_setprotected() //write PROTECT tag
1359 static void startshape(struct swfoutput*obj)
1367 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1369 swf_ShapeNew(&shape);
1370 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1371 rgb.r = obj->fillrgb.r;
1372 rgb.g = obj->fillrgb.g;
1373 rgb.b = obj->fillrgb.b;
1374 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1376 shapeid = ++currentswfid;
1377 swf_SetU16(tag,shapeid); // ID
1384 swf_SetRect(tag,&r);
1386 swf_SetShapeStyles(tag,shape);
1387 swf_ShapeCountBits(shape,NULL,NULL);
1388 swf_SetShapeBits(tag,shape);
1390 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1391 swflastx=swflasty=0;
1395 static void starttext(struct swfoutput*obj)
1401 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1402 textid = ++currentswfid;
1403 swf_SetU16(tag, textid);
1410 swf_SetRect(tag,&r);
1419 swf_SetMatrix(tag,&m);
1420 swflastx=swflasty=0;
1423 static void endshape()
1427 swf_ShapeSetEnd(tag);
1428 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1429 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1433 static void endtext()
1439 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1440 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1444 static void endpage(struct swfoutput*obj)
1451 swfoutput_endclip(obj);
1455 atag = action_Stop(atag);
1456 atag = action_End(atag);
1457 tag = swf_InsertTag(tag,ST_DOACTION);
1458 swf_ActionSet(tag,atag);
1460 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1463 void swfoutput_newpage(struct swfoutput*obj)
1467 for(depth--;depth>=startdepth;depth--) {
1468 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1469 swf_SetU16(tag,depth);
1476 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1477 up, complete the swf, and write it out. */
1478 void swfoutput_destroy(struct swfoutput* obj)
1481 fontlist_t *tmp,*iterator = fontlist;
1483 delete iterator->font;
1486 iterator = iterator->next;
1494 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1499 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1503 tag = swf_InsertTag(tag,ST_END);
1506 if FAILED(swf_WriteSWC(fi,&swf))
1507 msg("<error> WriteSWC() failed.\n");
1509 if FAILED(swf_WriteSWF(fi,&swf))
1510 msg("<error> WriteSWF() failed.\n");
1515 msg("<notice> SWF written\n");
1518 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1521 if(mode == DRAWMODE_FILL)
1523 else if(mode == DRAWMODE_EOFILL)
1525 else if(mode == DRAWMODE_STROKE)
1527 else if(mode == DRAWMODE_CLIP)
1529 else if(mode == DRAWMODE_EOCLIP)
1533 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1535 if(obj->fillrgb.r == r &&
1536 obj->fillrgb.g == g &&
1537 obj->fillrgb.b == b &&
1538 obj->fillrgb.a == a) return;
1548 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1550 if(obj->strokergb.r == r &&
1551 obj->strokergb.g == g &&
1552 obj->strokergb.b == b &&
1553 obj->strokergb.a == a) return;
1557 obj->strokergb.r = r;
1558 obj->strokergb.g = g;
1559 obj->strokergb.b = b;
1560 obj->strokergb.a = a;
1563 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1565 if(obj->linewidth == (u16)(linewidth*20))
1570 obj->linewidth = (u16)(linewidth*20);
1574 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1583 msg("<warning> Too many clip levels.");
1588 int olddrawmode = drawmode;
1589 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1590 swfoutput_drawpath(obj, outline, m);
1591 swf_ShapeSetEnd(tag);
1592 swfoutput_setdrawmode(obj, olddrawmode);
1594 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1595 cliptags[clippos] = tag;
1596 clipshapes[clippos] = shapeid;
1597 clipdepths[clippos] = depth++;
1602 void swfoutput_endclip(swfoutput*obj)
1610 msg("<error> Invalid end of clipping region");
1614 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1617 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1619 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1622 if(!strncmp("http://pdf2swf:", url, 15)) {
1623 char*tmp = strdup(url);
1624 int l = strlen(tmp);
1627 swfoutput_namedlink(obj, tmp+15, points);
1638 actions = action_GetUrl(0, url, "_parent");
1640 actions = action_GetUrl(0, url, "_this");
1641 actions = action_End(actions);
1643 drawlink(obj, actions, 0, points,0);
1645 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1654 actions = action_GotoFrame(0, page);
1655 actions = action_End(actions);
1657 drawlink(obj, actions, 0, points,0);
1660 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1661 of the viewer objects, like subtitles, index elements etc.
1663 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1665 ActionTAG *actions1,*actions2;
1666 char*tmp = strdup(name);
1674 if(!strncmp(tmp, "call:", 5))
1676 char*x = strchr(&tmp[5], ':');
1678 actions1 = action_PushInt(0, 0); //number of parameters (0)
1679 actions1 = action_PushString(actions1, &tmp[5]); //function name
1680 actions1 = action_CallFunction(actions1);
1683 actions1 = action_PushString(0, x+1); //parameter
1684 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1685 actions1 = action_PushString(actions1, &tmp[5]); //function name
1686 actions1 = action_CallFunction(actions1);
1688 actions2 = action_End(0);
1693 actions1 = action_PushString(0, "/:subtitle");
1694 actions1 = action_PushString(actions1, name);
1695 actions1 = action_SetVariable(actions1);
1696 actions1 = action_End(actions1);
1698 actions2 = action_PushString(0, "/:subtitle");
1699 actions2 = action_PushString(actions2, "");
1700 actions2 = action_SetVariable(actions2);
1701 actions2 = action_End(actions2);
1704 drawlink(obj, actions1, actions2, points,mouseover);
1706 swf_ActionFree(actions1);
1707 swf_ActionFree(actions2);
1711 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1717 struct plotxy p1,p2,p3,p4;
1721 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1725 int buttonid = ++currentswfid;
1728 if(points[t].x>xmax) xmax=points[t].x;
1729 if(points[t].y>ymax) ymax=points[t].y;
1730 if(points[t].x<xmin) xmin=points[t].x;
1731 if(points[t].y<ymin) ymin=points[t].y;
1734 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1735 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1737 /* the following code subtracts the upper left edge from all coordinates,
1738 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1739 Necessary for preprocessing with swfcombine. */
1740 posx = xmin; posy = ymin;
1741 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1742 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1743 xmin -= posx; ymin -= posy;
1744 xmax -= posx; ymax -= posy;
1747 myshapeid = ++currentswfid;
1748 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1749 swf_ShapeNew(&shape);
1750 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1751 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1752 swf_SetU16(tag, myshapeid);
1753 r.xmin = (int)(xmin*20);
1754 r.ymin = (int)(ymin*20);
1755 r.xmax = (int)(xmax*20);
1756 r.ymax = (int)(ymax*20);
1757 swf_SetRect(tag,&r);
1758 swf_SetShapeStyles(tag,shape);
1759 swf_ShapeCountBits(shape,NULL,NULL);
1760 swf_SetShapeBits(tag,shape);
1761 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1762 swflastx = swflasty = 0;
1768 swf_ShapeSetEnd(tag);
1771 myshapeid2 = ++currentswfid;
1772 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1773 swf_ShapeNew(&shape);
1774 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1776 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1777 swf_SetU16(tag, myshapeid2);
1778 r.xmin = (int)(xmin*20);
1779 r.ymin = (int)(ymin*20);
1780 r.xmax = (int)(xmax*20);
1781 r.ymax = (int)(ymax*20);
1782 swf_SetRect(tag,&r);
1783 swf_SetShapeStyles(tag,shape);
1784 swf_ShapeCountBits(shape,NULL,NULL);
1785 swf_SetShapeBits(tag,shape);
1786 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1787 swflastx = swflasty = 0;
1793 swf_ShapeSetEnd(tag);
1797 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1798 swf_SetU16(tag,buttonid); //id
1799 swf_ButtonSetFlags(tag, 0); //menu=no
1800 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1801 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1802 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1803 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1805 swf_ActionSet(tag,actions1);
1810 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1811 swf_SetU16(tag,buttonid); //id
1812 swf_ButtonSetFlags(tag, 0); //menu=no
1813 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1814 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1815 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1816 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1817 swf_SetU8(tag,0); // end of button records
1818 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1819 swf_ActionSet(tag,actions1);
1821 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1822 swf_ActionSet(tag,actions2);
1824 swf_ButtonPostProcess(tag, 2);
1827 swf_ButtonPostProcess(tag, 1);
1831 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1833 if(posx!=0 || posy!=0) {
1835 swf_GetMatrix(0,&m);
1836 m.tx = (int)(posx*20);
1837 m.ty = (int)(posy*20);
1838 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1841 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1845 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1846 double x1,double y1,
1847 double x2,double y2,
1848 double x3,double y3,
1849 double x4,double y4)
1855 struct plotxy p1,p2,p3,p4;
1857 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1858 if(x2>xmax) xmax=x2;
1859 if(y2>ymax) ymax=y2;
1860 if(x2<xmin) xmin=x2;
1861 if(y2<ymin) ymin=y2;
1862 if(x3>xmax) xmax=x3;
1863 if(y3>ymax) ymax=y3;
1864 if(x3<xmin) xmin=x3;
1865 if(y3<ymin) ymin=y3;
1866 if(x4>xmax) xmax=x4;
1867 if(y4>ymax) ymax=y4;
1868 if(x4<xmin) xmin=x4;
1869 if(y4<ymin) ymin=y4;
1875 {p1.x = (int)(p1.x*20)/20.0;
1876 p1.y = (int)(p1.y*20)/20.0;
1877 p2.x = (int)(p2.x*20)/20.0;
1878 p2.y = (int)(p2.y*20)/20.0;
1879 p3.x = (int)(p3.x*20)/20.0;
1880 p3.y = (int)(p3.y*20)/20.0;
1881 p4.x = (int)(p4.x*20)/20.0;
1882 p4.y = (int)(p4.y*20)/20.0;}
1885 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1886 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1887 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1888 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1890 m.tx = (int)(p1.x*20);
1891 m.ty = (int)(p1.y*20);
1894 myshapeid = ++currentswfid;
1895 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1896 swf_ShapeNew(&shape);
1897 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1898 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1899 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1900 swf_SetU16(tag, myshapeid);
1901 r.xmin = (int)(xmin*20);
1902 r.ymin = (int)(ymin*20);
1903 r.xmax = (int)(xmax*20);
1904 r.ymax = (int)(ymax*20);
1905 swf_SetRect(tag,&r);
1906 swf_SetShapeStyles(tag,shape);
1907 swf_ShapeCountBits(shape,NULL,NULL);
1908 swf_SetShapeBits(tag,shape);
1909 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1910 swflastx = swflasty = 0;
1917 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1918 ShapeSetLine (tag, shape, (int)(x1*20);
1919 ShapeSetLine (tag, shape, x*20,0);
1920 ShapeSetLine (tag, shape, 0,-y*20);
1921 ShapeSetLine (tag, shape, -x*20,0);*/
1922 swf_ShapeSetEnd(tag);
1925 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1926 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1929 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1930 double x1,double y1,
1931 double x2,double y2,
1932 double x3,double y3,
1933 double x4,double y4)
1941 int bitid = ++currentswfid;
1943 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1944 swf_SetU16(tag, bitid);
1945 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1951 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1955 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1956 double x1,double y1,
1957 double x2,double y2,
1958 double x3,double y3,
1959 double x4,double y4)
1969 int bitid = ++currentswfid;
1971 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1972 swf_SetU16(tag, bitid);
1973 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1974 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1978 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1979 double x1,double y1,
1980 double x2,double y2,
1981 double x3,double y3,
1982 double x4,double y4)
1990 int bitid = ++currentswfid;
1992 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1993 swf_SetU16(tag, bitid);
1994 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2000 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2004 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2005 double x1,double y1,
2006 double x2,double y2,
2007 double x3,double y3,
2008 double x4,double y4, int n)
2019 /* SWF expects scanlines to be 4 byte aligned */
2022 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2024 for(y=0;y<sizey;y++)
2026 for(x=0;x<sizex;x++)
2027 *ptr++ = mem[y*sizex+x];
2028 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2033 int bitid = ++currentswfid;
2035 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2036 swf_SetU16(tag, bitid);
2037 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2045 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2049 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2050 double x1,double y1,
2051 double x2,double y2,
2052 double x3,double y3,
2053 double x4,double y4)
2061 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);