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"
32 #define logf logarithmf // logf is also used by ../lib/log.h
35 #include "swfoutput.h"
38 #include "../lib/log.h"
39 #include "../lib/rfxswf.h"
41 #define standardEncodingSize 335
42 extern char *standardEncodingNames[standardEncodingSize];
45 int ignoredraworder=0;
48 int storeallcharacters=0;
53 int fontsplinemaxerror=1;
54 static int flag_protected = 0;
56 typedef unsigned char u8;
57 typedef unsigned short int u16;
58 typedef unsigned long int u32;
61 static char* filename = 0;
64 static int currentswfid = 0;
66 static int startdepth = 1;
69 static int shapeid = -1;
70 static int textid = -1;
72 static int drawmode = -1;
73 static char storefont = 0;
74 static int fillstyleid;
75 static int linestyleid;
76 static int swflastx=0;
77 static int swflasty=0;
78 static int lastwasfill = 0;
90 char fillstylechanged = 0;
92 static void startshape(struct swfoutput* obj);
93 static void starttext(struct swfoutput* obj);
94 static void endshape();
95 static void endtext();
97 // matrix multiplication. changes p0
98 static void transform (plotxy*p0,struct swfmatrix*m)
101 x = m->m11*p0->x+m->m12*p0->y;
102 y = m->m21*p0->x+m->m22*p0->y;
107 // write a move-to command into the swf
108 static int moveto(TAG*tag, plotxy p0)
110 int rx = (int)(p0.x*20);
111 int ry = (int)(p0.y*20);
112 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
113 swf_ShapeSetMove (tag, shape, rx,ry);
114 fillstylechanged = 0;
122 // write a line-to command into the swf
123 static void lineto(TAG*tag, plotxy p0)
125 int rx = ((int)(p0.x*20)-swflastx);
126 int ry = ((int)(p0.y*20)-swflasty);
127 /* we can't skip this for rx=0,ry=0, those
129 swf_ShapeSetLine (tag, shape, rx,ry);
134 // write a spline-to command into the swf
135 static void splineto(TAG*tag, plotxy control,plotxy end)
137 int cx = ((int)(control.x*20)-swflastx);
138 int cy = ((int)(control.y*20)-swflasty);
141 int ex = ((int)(end.x*20)-swflastx);
142 int ey = ((int)(end.y*20)-swflasty);
145 if(cx || cy || ex || ey)
146 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
149 /* write a line, given two points and the transformation
151 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
159 /* write a cubic (!) spline. This involves calling the approximate()
160 function out of spline.cc to convert it to a quadratic spline. */
161 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
164 struct qspline q[128];
178 /* fonts use a different approximation than shapes */
179 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
180 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
182 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
186 moveto(tag,q[t].start);
187 splineto(tag,q[t].control, q[t].end);
197 static void stopFill()
201 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
202 fillstylechanged = 1;
206 static void startFill()
210 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
211 fillstylechanged = 1;
216 /* draw a T1 outline. These are generated by pdf2swf and by t1lib
217 (representing characters). */
218 void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log)
220 if(tag->id != ST_DEFINEFONT &&
221 tag->id != ST_DEFINESHAPE &&
222 tag->id != ST_DEFINESHAPE2 &&
223 tag->id != ST_DEFINESHAPE3)
225 logf("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
229 double lastx=0,lasty=0;
230 double firstx=0,firsty=0;
235 x += (outline->dest.x/(float)0xffff);
236 y += (outline->dest.y/(float)0xffff);
237 if(outline->type == T1_PATHTYPE_MOVE)
239 if(((int)(lastx*20) != (int)(firstx*20) ||
240 (int)(lasty*20) != (int)(firsty*20)) &&
249 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
250 line(tag, p0, p1, m);
256 else if(outline->type == T1_PATHTYPE_LINE)
264 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
267 else if(outline->type == T1_PATHTYPE_BEZIER)
273 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
276 p1.x=o2->C.x/(float)0xffff+lastx;
277 p1.y=o2->C.y/(float)0xffff+lasty;
278 p2.x=o2->B.x/(float)0xffff+lastx;
279 p2.y=o2->B.y/(float)0xffff+lasty;
282 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
283 spline(tag,p0,p1,p2,p3,m);
286 logf("<error> drawpath: unknown outline type:%d\n", outline->type);
290 outline = outline->link;
292 if(((int)(lastx*20) != (int)(firstx*20) ||
293 (int)(lasty*20) != (int)(firsty*20)) &&
302 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
303 line(tag, p0, p1, m);
307 plotxy getPivot(T1_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
309 T1_PATHPOINT next, next2;
310 double xv=0,yv=0, xv2=0, yv2=0;
315 if(outline->type == T1_PATHTYPE_LINE) {
316 next = outline->dest;
318 next = ((T1_BEZIERSEGMENT*)outline)->B;
319 if(next.x==0 && next.y==0) {
320 next = ((T1_BEZIERSEGMENT*)outline)->C;
322 if(next.x==0 && next.y==0) {
323 next = ((T1_BEZIERSEGMENT*)outline)->dest;
327 if(trytwo && outline->last && outline->last->type != T1_PATHTYPE_MOVE) {
328 if(outline->type == T1_PATHTYPE_LINE) {
329 next2 = outline->last->dest;
331 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)(outline->last))->C;
332 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)(outline->last))->B;
333 next2.x = outline->last->dest.x - c.x;
334 next2.y = outline->last->dest.y - c.y;
335 if(next2.x==0 && next2.y==0) {
336 next2.x = outline->last->dest.x - b.x;
337 next2.y = outline->last->dest.y - b.y;
339 if(next2.x==0 && next2.y==0) {
340 next2.x = outline->last->dest.x;
341 next2.y = outline->last->dest.y;
347 if(outline->type == T1_PATHTYPE_LINE) {
348 next = outline->dest;
350 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)outline)->C;
351 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)outline)->B;
352 next.x = outline->dest.x - c.x;
353 next.y = outline->dest.y - c.y;
354 if(next.x==0 && next.y==0) {
355 next.x = outline->dest.x - b.x;
356 next.y = outline->dest.y - b.y;
358 if(next.x==0 && next.y==0) {
359 next.x = outline->dest.x;
360 next.y = outline->dest.y;
364 if(trytwo && outline->link && outline->link->type != T1_PATHTYPE_MOVE) {
365 if(outline->type == T1_PATHTYPE_LINE) {
366 next2 = outline->link->dest;
368 next2 = ((T1_BEZIERSEGMENT*)(outline->link))->B;
369 if(next2.x==0 && next2.y==0) {
370 next2 = ((T1_BEZIERSEGMENT*)outline->link)->C;
372 if(next2.x==0 && next2.y==0) {
373 next2 = ((T1_BEZIERSEGMENT*)outline->link)->dest;
381 xv = next.y/(float)0xffff;
382 yv = -next.x/(float)0xffff;
384 xv = -next.y/(float)0xffff;
385 yv = next.x/(float)0xffff;
388 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
394 xv2 = next2.y/(float)0xffff;
395 yv2 = -next2.x/(float)0xffff;
397 xv2 = -next2.y/(float)0xffff;
398 yv2 = next2.x/(float)0xffff;
401 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
406 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
416 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline)
418 double lastx=x, lasty=y;
419 while (outline && outline->type != T1_PATHTYPE_MOVE)
421 x += (outline->dest.x/(float)0xffff);
422 y += (outline->dest.y/(float)0xffff);
424 if(outline->type == T1_PATHTYPE_LINE)
431 line(tag, p0, p1, m);
433 else if(outline->type == T1_PATHTYPE_BEZIER)
436 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
439 p1.x=o2->C.x/(float)0xffff+lastx;
440 p1.y=o2->C.y/(float)0xffff+lasty;
441 p2.x=o2->B.x/(float)0xffff+lastx;
442 p2.y=o2->B.y/(float)0xffff+lasty;
445 spline(tag,p0,p1,p2,p3,m);
449 outline = outline->link;
453 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)
458 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
461 T1_OUTLINE *last, *tmp=outline;
462 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
468 while(tmp && tmp->type != T1_PATHTYPE_MOVE) {
470 lx += (tmp->dest.x/(float)0xffff);
471 ly += (tmp->dest.y/(float)0xffff);
474 s = getPivot(outline, 0, line_width, 0, 0);
475 e = getPivot(last, 0, line_width, 1, 0);
477 if(line_cap == LINE_CAP_BUTT) {
478 /* make the clipping rectangle slighly bigger
479 than the line ending, so that it get's clipped
489 p2.x = x2 - s.y - s.x*ee;
490 p2.y = y2 + s.x - s.y*ee;
491 p3.x = x2 - s.y + s.x*ee;
492 p3.y = y2 + s.x + s.y*ee;
497 m2.x = lx + e.y - e.x*ee;
498 m2.y = ly - e.x - e.y*ee;
499 m3.x = lx + e.y + e.x*ee;
500 m3.y = ly - e.x + e.y*ee;
502 for(nr=0;nr<2;nr++) {
504 struct plotxy q0,q1,q2,q3,q4,q5;
506 if(line_cap == LINE_CAP_BUTT) {
509 q1.x = sizex; q1.y = 0;
510 q2.x = sizex; q2.y = sizey;
511 q3.x = 0; q3.y = sizey;
513 q0.x = sizex; q0.y = sizey;
514 q1.x = 0; q1.y = sizey;
516 q3.x = sizex; q3.y = 0;
530 line(tag, p0, p1, m);
531 line(tag, p1, p2, m);
532 line(tag, p2, p3, m);
533 line(tag, p3, p0, m);
535 if(line_cap == LINE_CAP_BUTT) {
537 swf_ShapeSetEnd(tag);
538 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
539 swf_ObjectPlaceClip(tag,shapeid,depth,NULL,NULL,NULL,depth+2-nr);
553 drawShortPath(output,x,y,m,outline);
555 if(line_cap == LINE_CAP_BUTT) {
561 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)
563 plotxy d1,d2,p1,p2,p3,p4;
565 d1.x = (outline->dest.x/(float)0xffff);
566 d1.y = (outline->dest.y/(float)0xffff);
567 d2 = getPivot(outline, 0, line_width, 0, 0);
569 assert(line_cap != LINE_CAP_ROUND);
570 if(line_cap == LINE_CAP_SQUARE) {
579 p2.x = x + d2.x + d1.x;
580 p2.y = y + d2.y + d1.y;
581 p3.x = x - d2.x + d1.x;
582 p3.y = y - d2.y + d1.y;
592 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)
594 T1_OUTLINE*tmp=outline;
600 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
602 while(tmp->link && tmp->link->type!=T1_PATHTYPE_MOVE) {
603 xx += (tmp->dest.x/(float)0xffff);
604 yy += (tmp->dest.y/(float)0xffff);
608 assert(tmp->type == T1_PATHTYPE_LINE);
609 assert(outline->type == T1_PATHTYPE_LINE);
613 if(outline->link == tmp) {
614 /* the two straight line segments (which are everything we
615 need to draw) are very likely to overlap. To avoid that
616 they cancel each other out at the end points, start a new
617 shape for the second one */
618 endshape();startshape(output);
622 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
624 if(outline->link != tmp)
628 tmp->type = T1_PATHTYPE_MOVE;
629 x += (outline->dest.x/(float)0xffff);
630 y += (outline->dest.y/(float)0xffff);
631 outline = outline->link;
632 drawShortPath(output, x, y, m, outline);
640 static int t1len(T1_OUTLINE*line)
643 while(line && line->type != T1_PATHTYPE_MOVE) {
650 static float t1linelen(T1_OUTLINE*line)
653 x = (line->dest.x/(float)0xffff);
654 y = (line->dest.y/(float)0xffff);
655 return sqrt(x*x+y*y);
658 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)
660 if(tag->id != ST_DEFINEFONT &&
661 tag->id != ST_DEFINESHAPE &&
662 tag->id != ST_DEFINESHAPE2 &&
663 tag->id != ST_DEFINESHAPE3) {
664 logf("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
669 double lastx=0,lasty=0;
672 T1_OUTLINE*tmp = outline, *last = 0;
677 x += (tmp->dest.x/(float)0xffff);
678 y += (tmp->dest.y/(float)0xffff);
680 if(!tmp || tmp->type == T1_PATHTYPE_MOVE) {
682 if(last->type == T1_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
683 lastwasline && line_cap != LINE_CAP_ROUND)
684 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
686 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
700 if(tmp && tmp->type == T1_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
706 tmp->link->last = tmp; // make sure list is properly linked in both directions
711 static inline int colorcompare(RGBA*a,RGBA*b)
723 static const int CHARDATAMAX = 1024;
731 } chardata[CHARDATAMAX];
734 static void putcharacters(TAG*tag)
739 color.r = chardata[0].color.r^255;
748 int charadvance[128];
751 int glyphbits=1; //TODO: can this be zero?
754 if(tag->id != ST_DEFINETEXT &&
755 tag->id != ST_DEFINETEXT2) {
756 logf("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
760 logf("<warning> putcharacters called with zero characters");
763 for(pass = 0; pass < 2; pass++)
773 advancebits++; // add sign bit
774 swf_SetU8(tag, glyphbits);
775 swf_SetU8(tag, advancebits);
778 for(t=0;t<=chardatapos;t++)
780 if(lastfontid != chardata[t].fontid ||
781 lastx!=chardata[t].x ||
782 lasty!=chardata[t].y ||
783 !colorcompare(&color, &chardata[t].color) ||
785 lastsize != chardata[t].size ||
788 if(charstorepos && pass==0)
791 for(s=0;s<charstorepos;s++)
793 while(charids[s]>=(1<<glyphbits))
795 while(charadvance[s]>=(1<<advancebits))
799 if(charstorepos && pass==1)
801 tag->writeBit = 0; // Q&D
802 swf_SetBits(tag, 0, 1); // GLYPH Record
803 swf_SetBits(tag, charstorepos, 7); // number of glyphs
805 for(s=0;s<charstorepos;s++)
807 swf_SetBits(tag, charids[s], glyphbits);
808 swf_SetBits(tag, charadvance[s], advancebits);
813 if(pass == 1 && t<chardatapos)
819 if(lastx != chardata[t].x ||
820 lasty != chardata[t].y)
825 if(!colorcompare(&color, &chardata[t].color))
827 color = chardata[t].color;
830 font.id = chardata[t].fontid;
831 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
834 tag->writeBit = 0; // Q&D
835 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
838 lastfontid = chardata[t].fontid;
839 lastx = chardata[t].x;
840 lasty = chardata[t].y;
841 lastsize = chardata[t].size;
848 int nextt = t==chardatapos-1?t:t+1;
849 int rel = chardata[nextt].x-chardata[t].x;
850 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
852 lastx=chardata[nextt].x;
858 charids[charstorepos] = chardata[t].charid;
859 charadvance[charstorepos] = advance;
866 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
867 int x,int y, int size)
869 if(chardatapos == CHARDATAMAX)
874 chardata[chardatapos].fontid = fontid;
875 chardata[chardatapos].charid = charid;
876 chardata[chardatapos].x = x;
877 chardata[chardatapos].y = y;
878 chardata[chardatapos].color = obj->fillrgb;
879 chardata[chardatapos].size = size;
884 /* process a character. */
885 static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m)
888 if(m->m12!=0 || m->m21!=0)
893 if(usefonts && ! drawonlyshapes)
895 int charid = font->getSWFCharID(character, charnr);
900 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
901 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
905 T1_OUTLINE*outline = font->getOutline(character, charnr);
906 char* charname = character;
909 logf("<warning> Didn't find %s in current charset (%s)",
910 FIXNULL(character),FIXNULL(font->getName()));
929 drawpath(tag, outline, &m2, 0);
934 /* draw a curved polygon. */
935 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
941 /* Multiple polygons in one shape don't overlap correctly,
942 so we better start a new shape here if the polygon is filled
944 if(shapeid>=0 && fill && !ignoredraworder) {
956 drawpath(tag, outline,m, 0);
959 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
969 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
972 /* SWFFont: copy all t1 font outlines to a local
974 SWFFont::SWFFont(char*name, int id, char*filename)
976 if(!T1_GetFontName(id))
979 this->name = strdup(T1_GetFontFileName(id));
980 this->fontid = strdup(name);
983 char**a= T1_GetAllCharNames(id);
994 logf("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
996 this->standardtablesize = 256;
997 if(this->charnum < this->standardtablesize)
998 this->standardtablesize = this->charnum;
999 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1001 for(t = 0; t < this->standardtablesize; t++) {
1002 char*name = T1_GetCharName(id,t);
1005 standardtable[t] = strdup(name);
1008 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1009 charname = (char**)malloc(charnum*sizeof(char*));
1010 width = (int*)malloc(charnum*sizeof(int));
1011 memset(width, 0, charnum*sizeof(int));
1012 memset(charname, 0, charnum*sizeof(char*));
1013 used = (char*)malloc(charnum*sizeof(char));
1014 char2swfcharid = (U16*)malloc(charnum*2);
1015 swfcharid2char = (U16*)malloc(charnum*2);
1018 memset(used,0,charnum*sizeof(char));
1020 this->swfid = ++currentswfid;
1033 int ret = T1_ReencodeFont(id, map);
1037 int ret = T1_ReencodeFont(id, map);
1039 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1045 char* name = T1_GetCharName(id, s);
1046 if(!name) name = "";
1047 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1048 this->width[outlinepos] = T1_GetCharWidth(id, s);
1049 this->charname[outlinepos] = strdup(name);
1057 /* free all tables, write out definefont tags */
1063 if(storeallcharacters)
1066 for(t=0;t<this->charnum;t++)
1068 if(this->charname[t])
1069 getSWFCharID(this->charname[t], -1);
1073 ptr = (int*)malloc(swfcharpos*sizeof(int));
1075 for(t=0;t<charnum;t++)
1076 if(used[t]) usednum++;
1078 if(usednum && !drawonlyshapes)
1080 logf("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1081 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1082 swf_SetU16(ftag, this->swfid);
1083 int initpos = swf_GetTagLen(ftag);
1090 for(t=0;t<swfcharpos;t++)
1092 ptr[t] = swf_GetTagLen(ftag);
1093 swf_SetU16(ftag, 0x1234);
1095 for(t=0;t<swfcharpos;t++)
1097 *(U16*)&ftag->data[ptr[t]] =
1098 SWAP16(swf_GetTagLen(ftag)-initpos);
1102 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1106 swf_ShapeSetStyle(ftag,&s,0,1,0);
1107 fillstylechanged = 1;
1108 int lastfill = fill;
1111 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1114 swf_ShapeSetEnd(ftag);
1116 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1117 swf_SetU16(ftag, this->swfid);
1119 swf_SetU8(ftag, strlen(this->fontid));
1120 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1124 swf_SetU8(ftag, 0); //flags
1125 for(t=0;t<swfcharpos;t++)
1128 char * name = this->charname[this->swfcharid2char[t]];
1129 for(s=0;s<256;s++) {
1130 if(standardEncodingNames[s] &&
1131 !strcmp(name,standardEncodingNames[s]))
1134 swf_SetU8(ftag, (U8)s);
1140 for(t=0;t<charnum;t++)
1142 for(t=0;t<standardtablesize;t++)
1143 if(standardtable[t]) {
1144 free(standardtable[t]);
1146 free(standardtable);
1150 free(swfcharid2char);
1151 free(char2swfcharid);
1154 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1157 for(t=0;t<this->charnum;t++) {
1158 if(!strcmp(this->charname[t],name)) {
1163 /* if we didn't find the character, maybe
1164 we can find the capitalized version */
1165 for(t=0;t<this->charnum;t++) {
1166 if(!strcasecmp(this->charname[t],name))
1170 /* if we didn't find it by name, use the names of the first 256 characters
1171 of the font to try a new name based on charnr */
1172 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1173 return getOutline(this->standardtable[charnr], -1);
1176 logf("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1180 int SWFFont::getSWFCharID(char*name, int charnr)
1183 for(t=0;t<this->charnum;t++) {
1184 if(!strcmp(this->charname[t],name)) {
1187 swfcharid2char[swfcharpos] = t;
1188 char2swfcharid[t] = swfcharpos++;
1191 return char2swfcharid[t];
1195 /* if we didn't find the character, maybe
1196 we can find the capitalized version */
1197 for(t=0;t<this->charnum;t++) {
1198 if(!strcasecmp(this->charname[t],name)) {
1201 swfcharid2char[swfcharpos] = t;
1202 char2swfcharid[t] = swfcharpos++;
1205 return char2swfcharid[t];
1209 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1210 of the font to try a new name based on charnr */
1211 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1212 return getSWFCharID(this->standardtable[charnr], -1);
1214 logf("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1218 int SWFFont::getWidth(char*name)
1221 for(t=0;t<this->charnum;t++) {
1222 if(!strcmp(this->charname[t],name)) {
1223 return this->width[t];
1229 char*SWFFont::getName()
1240 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1241 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1243 fontlist_t*last=0,*iterator;
1244 if(obj->font && !strcmp(obj->font->fontid,fontid))
1247 iterator = fontlist;
1249 if(!strcmp(iterator->font->fontid,fontid))
1252 iterator = iterator->next;
1256 obj->font = iterator->font;
1261 logf("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1264 SWFFont*font = new SWFFont(fontid, t1id, filename);
1265 iterator = new fontlist_t;
1266 iterator->font = font;
1270 last->next = iterator;
1272 fontlist = iterator;
1276 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1278 fontlist_t *iterator = fontlist;
1280 if(!strcmp(iterator->font->fontid,fontid))
1282 iterator = iterator->next;
1287 /* set's the matrix which is to be applied to characters drawn by
1288 swfoutput_drawchar() */
1289 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1290 double m21,double m22)
1292 if(obj->fontm11 == m11 &&
1293 obj->fontm12 == m12 &&
1294 obj->fontm21 == m21 &&
1295 obj->fontm22 == m22)
1305 /* draws a character at x,y. */
1306 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1309 m.m11 = obj->fontm11;
1310 m.m12 = obj->fontm12;
1311 m.m21 = obj->fontm21;
1312 m.m22 = obj->fontm22;
1315 drawchar(obj, obj->font, character, charnr, &m);
1318 /* initialize the swf writer */
1319 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1324 memset(obj, 0, sizeof(struct swfoutput));
1325 filename = _filename;
1329 logf("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1333 memset(&swf,0x00,sizeof(SWF));
1335 swf.fileVersion = flashversion;
1336 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1337 swf.movieSize.xmax = 20*sizex;
1338 swf.movieSize.ymax = 20*sizey;
1340 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1345 swf_SetRGB(tag,&rgb);
1346 if(flag_protected) // good practice! /r
1347 tag = swf_InsertTag(tag, ST_PROTECT);
1352 void swfoutput_setprotected() //write PROTECT tag
1357 static void startshape(struct swfoutput*obj)
1365 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1367 swf_ShapeNew(&shape);
1368 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1369 rgb.r = obj->fillrgb.r;
1370 rgb.g = obj->fillrgb.g;
1371 rgb.b = obj->fillrgb.b;
1372 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1374 shapeid = ++currentswfid;
1375 swf_SetU16(tag,shapeid); // ID
1382 swf_SetRect(tag,&r);
1384 swf_SetShapeStyles(tag,shape);
1385 swf_ShapeCountBits(shape,NULL,NULL);
1386 swf_SetShapeBits(tag,shape);
1388 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1389 swflastx=swflasty=0;
1393 static void starttext(struct swfoutput*obj)
1399 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1400 textid = ++currentswfid;
1401 swf_SetU16(tag, textid);
1408 swf_SetRect(tag,&r);
1417 swf_SetMatrix(tag,&m);
1418 swflastx=swflasty=0;
1421 static void endshape()
1425 swf_ShapeSetEnd(tag);
1426 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1427 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1431 static void endtext()
1437 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1438 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1442 static void endpage(struct swfoutput*obj)
1449 swfoutput_endclip(obj);
1453 atag = action_Stop(atag);
1454 atag = action_End(atag);
1455 tag = swf_InsertTag(tag,ST_DOACTION);
1456 swf_ActionSet(tag,atag);
1458 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1461 void swfoutput_newpage(struct swfoutput*obj)
1465 for(depth--;depth>=startdepth;depth--) {
1466 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1467 swf_SetU16(tag,depth);
1474 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1475 up, complete the swf, and write it out. */
1476 void swfoutput_destroy(struct swfoutput* obj)
1479 fontlist_t *tmp,*iterator = fontlist;
1481 delete iterator->font;
1484 iterator = iterator->next;
1492 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1497 logf("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1501 tag = swf_InsertTag(tag,ST_END);
1504 if FAILED(swf_WriteSWC(fi,&swf))
1505 logf("<error> WriteSWC() failed.\n");
1507 if FAILED(swf_WriteSWF(fi,&swf))
1508 logf("<error> WriteSWF() failed.\n");
1513 logf("<notice> SWF written\n");
1516 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1519 if(mode == DRAWMODE_FILL)
1521 else if(mode == DRAWMODE_EOFILL)
1523 else if(mode == DRAWMODE_STROKE)
1525 else if(mode == DRAWMODE_CLIP)
1527 else if(mode == DRAWMODE_EOCLIP)
1531 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1533 if(obj->fillrgb.r == r &&
1534 obj->fillrgb.g == g &&
1535 obj->fillrgb.b == b &&
1536 obj->fillrgb.a == a) return;
1546 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1548 if(obj->strokergb.r == r &&
1549 obj->strokergb.g == g &&
1550 obj->strokergb.b == b &&
1551 obj->strokergb.a == a) return;
1555 obj->strokergb.r = r;
1556 obj->strokergb.g = g;
1557 obj->strokergb.b = b;
1558 obj->strokergb.a = a;
1561 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1563 if(obj->linewidth == (u16)(linewidth*20))
1568 obj->linewidth = (u16)(linewidth*20);
1572 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1581 logf("<warning> Too many clip levels.");
1586 int olddrawmode = drawmode;
1587 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1588 swfoutput_drawpath(obj, outline, m);
1589 swf_ShapeSetEnd(tag);
1590 swfoutput_setdrawmode(obj, olddrawmode);
1592 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1593 cliptags[clippos] = tag;
1594 clipshapes[clippos] = shapeid;
1595 clipdepths[clippos] = depth++;
1600 void swfoutput_endclip(swfoutput*obj)
1608 logf("<error> Invalid end of clipping region");
1612 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1615 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1617 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1620 if(!strncmp("http://pdf2swf:", url, 15)) {
1621 char*tmp = strdup(url);
1622 int l = strlen(tmp);
1625 swfoutput_namedlink(obj, tmp+15, points);
1636 actions = action_GetUrl(0, url, "_parent");
1638 actions = action_GetUrl(0, url, "_this");
1639 actions = action_End(actions);
1641 drawlink(obj, actions, 0, points,0);
1643 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1652 actions = action_GotoFrame(0, page);
1653 actions = action_End(actions);
1655 drawlink(obj, actions, 0, points,0);
1658 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1659 of the viewer objects, like subtitles, index elements etc.
1661 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1663 ActionTAG *actions1,*actions2;
1664 char*tmp = strdup(name);
1672 if(!strncmp(tmp, "call:", 5))
1674 char*x = strchr(&tmp[5], ':');
1676 actions1 = action_PushInt(0, 0); //number of parameters (0)
1677 actions1 = action_PushString(actions1, &tmp[5]); //function name
1678 actions1 = action_CallFunction(actions1);
1681 actions1 = action_PushString(0, x+1); //parameter
1682 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1683 actions1 = action_PushString(actions1, &tmp[5]); //function name
1684 actions1 = action_CallFunction(actions1);
1686 actions2 = action_End(0);
1691 actions1 = action_PushString(0, "/:subtitle");
1692 actions1 = action_PushString(actions1, name);
1693 actions1 = action_SetVariable(actions1);
1694 actions1 = action_End(actions1);
1696 actions2 = action_PushString(0, "/:subtitle");
1697 actions2 = action_PushString(actions2, "");
1698 actions2 = action_SetVariable(actions2);
1699 actions2 = action_End(actions2);
1702 drawlink(obj, actions1, actions2, points,mouseover);
1704 swf_ActionFree(actions1);
1705 swf_ActionFree(actions2);
1709 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1715 struct plotxy p1,p2,p3,p4;
1719 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1723 int buttonid = ++currentswfid;
1726 if(points[t].x>xmax) xmax=points[t].x;
1727 if(points[t].y>ymax) ymax=points[t].y;
1728 if(points[t].x<xmin) xmin=points[t].x;
1729 if(points[t].y<ymin) ymin=points[t].y;
1732 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1733 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1735 /* the following code subtracts the upper left edge from all coordinates,
1736 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1737 Necessary for preprocessing with swfcombine. */
1738 posx = xmin; posy = ymin;
1739 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1740 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1741 xmin -= posx; ymin -= posy;
1742 xmax -= posx; ymax -= posy;
1745 myshapeid = ++currentswfid;
1746 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1747 swf_ShapeNew(&shape);
1748 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1749 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1750 swf_SetU16(tag, myshapeid);
1751 r.xmin = (int)(xmin*20);
1752 r.ymin = (int)(ymin*20);
1753 r.xmax = (int)(xmax*20);
1754 r.ymax = (int)(ymax*20);
1755 swf_SetRect(tag,&r);
1756 swf_SetShapeStyles(tag,shape);
1757 swf_ShapeCountBits(shape,NULL,NULL);
1758 swf_SetShapeBits(tag,shape);
1759 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1760 swflastx = swflasty = 0;
1766 swf_ShapeSetEnd(tag);
1769 myshapeid2 = ++currentswfid;
1770 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1771 swf_ShapeNew(&shape);
1772 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1774 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1775 swf_SetU16(tag, myshapeid2);
1776 r.xmin = (int)(xmin*20);
1777 r.ymin = (int)(ymin*20);
1778 r.xmax = (int)(xmax*20);
1779 r.ymax = (int)(ymax*20);
1780 swf_SetRect(tag,&r);
1781 swf_SetShapeStyles(tag,shape);
1782 swf_ShapeCountBits(shape,NULL,NULL);
1783 swf_SetShapeBits(tag,shape);
1784 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1785 swflastx = swflasty = 0;
1791 swf_ShapeSetEnd(tag);
1795 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1796 swf_SetU16(tag,buttonid); //id
1797 swf_ButtonSetFlags(tag, 0); //menu=no
1798 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1799 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1800 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1801 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1803 swf_ActionSet(tag,actions1);
1808 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1809 swf_SetU16(tag,buttonid); //id
1810 swf_ButtonSetFlags(tag, 0); //menu=no
1811 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1812 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1813 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1814 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1815 swf_SetU8(tag,0); // end of button records
1816 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1817 swf_ActionSet(tag,actions1);
1819 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1820 swf_ActionSet(tag,actions2);
1822 swf_ButtonPostProcess(tag, 2);
1825 swf_ButtonPostProcess(tag, 1);
1829 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1831 if(posx!=0 || posy!=0) {
1833 swf_GetMatrix(0,&m);
1834 m.tx = (int)(posx*20);
1835 m.ty = (int)(posy*20);
1836 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1839 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1843 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1844 double x1,double y1,
1845 double x2,double y2,
1846 double x3,double y3,
1847 double x4,double y4)
1853 struct plotxy p1,p2,p3,p4;
1855 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1856 if(x2>xmax) xmax=x2;
1857 if(y2>ymax) ymax=y2;
1858 if(x2<xmin) xmin=x2;
1859 if(y2<ymin) ymin=y2;
1860 if(x3>xmax) xmax=x3;
1861 if(y3>ymax) ymax=y3;
1862 if(x3<xmin) xmin=x3;
1863 if(y3<ymin) ymin=y3;
1864 if(x4>xmax) xmax=x4;
1865 if(y4>ymax) ymax=y4;
1866 if(x4<xmin) xmin=x4;
1867 if(y4<ymin) ymin=y4;
1873 {p1.x = (int)(p1.x*20)/20.0;
1874 p1.y = (int)(p1.y*20)/20.0;
1875 p2.x = (int)(p2.x*20)/20.0;
1876 p2.y = (int)(p2.y*20)/20.0;
1877 p3.x = (int)(p3.x*20)/20.0;
1878 p3.y = (int)(p3.y*20)/20.0;
1879 p4.x = (int)(p4.x*20)/20.0;
1880 p4.y = (int)(p4.y*20)/20.0;}
1883 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1884 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1885 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1886 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1888 m.tx = (int)(p1.x*20);
1889 m.ty = (int)(p1.y*20);
1892 myshapeid = ++currentswfid;
1893 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1894 swf_ShapeNew(&shape);
1895 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1896 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1897 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1898 swf_SetU16(tag, myshapeid);
1899 r.xmin = (int)(xmin*20);
1900 r.ymin = (int)(ymin*20);
1901 r.xmax = (int)(xmax*20);
1902 r.ymax = (int)(ymax*20);
1903 swf_SetRect(tag,&r);
1904 swf_SetShapeStyles(tag,shape);
1905 swf_ShapeCountBits(shape,NULL,NULL);
1906 swf_SetShapeBits(tag,shape);
1907 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1908 swflastx = swflasty = 0;
1915 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1916 ShapeSetLine (tag, shape, (int)(x1*20);
1917 ShapeSetLine (tag, shape, x*20,0);
1918 ShapeSetLine (tag, shape, 0,-y*20);
1919 ShapeSetLine (tag, shape, -x*20,0);*/
1920 swf_ShapeSetEnd(tag);
1923 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1924 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1927 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1928 double x1,double y1,
1929 double x2,double y2,
1930 double x3,double y3,
1931 double x4,double y4)
1939 int bitid = ++currentswfid;
1941 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1942 swf_SetU16(tag, bitid);
1943 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1949 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1953 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1954 double x1,double y1,
1955 double x2,double y2,
1956 double x3,double y3,
1957 double x4,double y4)
1967 int bitid = ++currentswfid;
1969 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1970 swf_SetU16(tag, bitid);
1971 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1972 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1976 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1977 double x1,double y1,
1978 double x2,double y2,
1979 double x3,double y3,
1980 double x4,double y4)
1988 int bitid = ++currentswfid;
1990 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1991 swf_SetU16(tag, bitid);
1992 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
1998 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2002 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2003 double x1,double y1,
2004 double x2,double y2,
2005 double x3,double y3,
2006 double x4,double y4, int n)
2017 /* SWF expects scanlines to be 4 byte aligned */
2020 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2022 for(y=0;y<sizey;y++)
2024 for(x=0;x<sizex;x++)
2025 *ptr++ = mem[y*sizex+x];
2026 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2031 int bitid = ++currentswfid;
2033 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2034 swf_SetU16(tag, bitid);
2035 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2043 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2047 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2048 double x1,double y1,
2049 double x2,double y2,
2050 double x3,double y3,
2051 double x4,double y4)
2059 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);