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)
820 newx = chardata[t].x;
821 newy = chardata[t].y;
827 if(!colorcompare(&color, &chardata[t].color))
829 color = chardata[t].color;
832 font.id = chardata[t].fontid;
833 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
836 tag->writeBit = 0; // Q&D
837 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
840 lastfontid = chardata[t].fontid;
841 lastx = chardata[t].x;
842 lasty = chardata[t].y;
843 lastsize = chardata[t].size;
850 int nextt = t==chardatapos-1?t:t+1;
851 int rel = chardata[nextt].x-chardata[t].x;
852 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
854 lastx=chardata[nextt].x;
860 charids[charstorepos] = chardata[t].charid;
861 charadvance[charstorepos] = advance;
868 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
869 int x,int y, int size)
871 if(chardatapos == CHARDATAMAX)
876 chardata[chardatapos].fontid = fontid;
877 chardata[chardatapos].charid = charid;
878 chardata[chardatapos].x = x;
879 chardata[chardatapos].y = y;
880 chardata[chardatapos].color = obj->fillrgb;
881 chardata[chardatapos].size = size;
886 /* process a character. */
887 static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m)
890 if(m->m12!=0 || m->m21!=0)
896 msg("<warning> Font is NULL");
899 if(usefonts && ! drawonlyshapes)
901 int charid = font->getSWFCharID(character, charnr);
906 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
907 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
911 T1_OUTLINE*outline = font->getOutline(character, charnr);
912 char* charname = character;
915 msg("<warning> Didn't find %s in current charset (%s)",
916 FIXNULL(character),FIXNULL(font->getName()));
935 drawpath(tag, outline, &m2, 0);
940 /* draw a curved polygon. */
941 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
947 /* Multiple polygons in one shape don't overlap correctly,
948 so we better start a new shape here if the polygon is filled
950 if(shapeid>=0 && fill && !ignoredraworder) {
962 drawpath(tag, outline,m, 0);
965 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
975 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
978 /* SWFFont: copy all t1 font outlines to a local
980 SWFFont::SWFFont(char*name, int id, char*filename)
982 if(!T1_GetFontName(id))
985 this->name = strdup(T1_GetFontFileName(id));
986 this->fontid = strdup(name);
989 char**a= T1_GetAllCharNames(id);
1000 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
1002 this->standardtablesize = 256;
1003 if(this->charnum < this->standardtablesize)
1004 this->standardtablesize = this->charnum;
1005 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1007 for(t = 0; t < this->standardtablesize; t++) {
1008 char*name = T1_GetCharName(id,t);
1011 standardtable[t] = strdup(name);
1014 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1015 charname = (char**)malloc(charnum*sizeof(char*));
1016 width = (int*)malloc(charnum*sizeof(int));
1017 memset(width, 0, charnum*sizeof(int));
1018 memset(charname, 0, charnum*sizeof(char*));
1019 used = (char*)malloc(charnum*sizeof(char));
1020 char2swfcharid = (U16*)malloc(charnum*2);
1021 swfcharid2char = (U16*)malloc(charnum*2);
1024 memset(used,0,charnum*sizeof(char));
1026 this->swfid = ++currentswfid;
1039 int ret = T1_ReencodeFont(id, map);
1043 int ret = T1_ReencodeFont(id, map);
1045 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1051 char* name = T1_GetCharName(id, s);
1052 if(!name) name = "";
1053 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1054 this->width[outlinepos] = T1_GetCharWidth(id, s);
1055 this->charname[outlinepos] = strdup(name);
1063 /* free all tables, write out definefont tags */
1069 if(storeallcharacters)
1072 for(t=0;t<this->charnum;t++)
1074 if(this->charname[t])
1075 getSWFCharID(this->charname[t], -1);
1079 ptr = (int*)malloc(swfcharpos*sizeof(int));
1081 for(t=0;t<charnum;t++)
1082 if(used[t]) usednum++;
1084 if(usednum && !drawonlyshapes)
1086 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1087 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1088 swf_SetU16(ftag, this->swfid);
1089 int initpos = swf_GetTagLen(ftag);
1096 for(t=0;t<swfcharpos;t++)
1098 ptr[t] = swf_GetTagLen(ftag);
1099 swf_SetU16(ftag, 0x1234);
1101 for(t=0;t<swfcharpos;t++)
1103 *(U16*)&ftag->data[ptr[t]] =
1104 SWAP16(swf_GetTagLen(ftag)-initpos);
1108 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1112 swf_ShapeSetStyle(ftag,&s,0,1,0);
1113 fillstylechanged = 1;
1114 int lastfill = fill;
1117 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1120 swf_ShapeSetEnd(ftag);
1122 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1123 swf_SetU16(ftag, this->swfid);
1125 swf_SetU8(ftag, strlen(this->fontid));
1126 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1130 swf_SetU8(ftag, 0); //flags
1131 for(t=0;t<swfcharpos;t++)
1134 char * name = this->charname[this->swfcharid2char[t]];
1135 for(s=0;s<256;s++) {
1136 if(standardEncodingNames[s] &&
1137 !strcmp(name,standardEncodingNames[s]))
1140 swf_SetU8(ftag, (U8)s);
1146 for(t=0;t<charnum;t++)
1148 for(t=0;t<standardtablesize;t++)
1149 if(standardtable[t]) {
1150 free(standardtable[t]);
1152 free(standardtable);
1156 free(swfcharid2char);
1157 free(char2swfcharid);
1160 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1163 for(t=0;t<this->charnum;t++) {
1164 if(!strcmp(this->charname[t],name)) {
1169 /* if we didn't find the character, maybe
1170 we can find the capitalized version */
1171 for(t=0;t<this->charnum;t++) {
1172 if(!strcasecmp(this->charname[t],name))
1176 /* if we didn't find it by name, use the names of the first 256 characters
1177 of the font to try a new name based on charnr */
1178 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1179 return getOutline(this->standardtable[charnr], -1);
1182 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1186 int SWFFont::getSWFCharID(char*name, int charnr)
1189 for(t=0;t<this->charnum;t++) {
1190 if(!strcmp(this->charname[t],name)) {
1193 swfcharid2char[swfcharpos] = t;
1194 char2swfcharid[t] = swfcharpos++;
1197 return char2swfcharid[t];
1201 /* if we didn't find the character, maybe
1202 we can find the capitalized version */
1203 for(t=0;t<this->charnum;t++) {
1204 if(!strcasecmp(this->charname[t],name)) {
1207 swfcharid2char[swfcharpos] = t;
1208 char2swfcharid[t] = swfcharpos++;
1211 return char2swfcharid[t];
1215 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1216 of the font to try a new name based on charnr */
1217 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1218 return getSWFCharID(this->standardtable[charnr], -1);
1220 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1224 int SWFFont::getWidth(char*name)
1227 for(t=0;t<this->charnum;t++) {
1228 if(!strcmp(this->charname[t],name)) {
1229 return this->width[t];
1235 char*SWFFont::getName()
1246 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1247 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1249 fontlist_t*last=0,*iterator;
1250 if(obj->font && !strcmp(obj->font->fontid,fontid))
1253 iterator = fontlist;
1255 if(!strcmp(iterator->font->fontid,fontid))
1258 iterator = iterator->next;
1262 obj->font = iterator->font;
1267 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1270 SWFFont*font = new SWFFont(fontid, t1id, filename);
1271 iterator = new fontlist_t;
1272 iterator->font = font;
1276 last->next = iterator;
1278 fontlist = iterator;
1282 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1284 fontlist_t *iterator = fontlist;
1286 if(!strcmp(iterator->font->fontid,fontid))
1288 iterator = iterator->next;
1293 /* set's the matrix which is to be applied to characters drawn by
1294 swfoutput_drawchar() */
1295 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1296 double m21,double m22)
1298 if(obj->fontm11 == m11 &&
1299 obj->fontm12 == m12 &&
1300 obj->fontm21 == m21 &&
1301 obj->fontm22 == m22)
1311 /* draws a character at x,y. */
1312 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1315 m.m11 = obj->fontm11;
1316 m.m12 = obj->fontm12;
1317 m.m21 = obj->fontm21;
1318 m.m22 = obj->fontm22;
1321 drawchar(obj, obj->font, character, charnr, &m);
1324 /* initialize the swf writer */
1325 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1330 memset(obj, 0, sizeof(struct swfoutput));
1331 filename = _filename;
1335 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1339 memset(&swf,0x00,sizeof(SWF));
1341 swf.fileVersion = flashversion;
1342 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1343 swf.movieSize.xmax = 20*sizex;
1344 swf.movieSize.ymax = 20*sizey;
1346 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1351 swf_SetRGB(tag,&rgb);
1352 if(flag_protected) // good practice! /r
1353 tag = swf_InsertTag(tag, ST_PROTECT);
1358 void swfoutput_setprotected() //write PROTECT tag
1363 static void startshape(struct swfoutput*obj)
1371 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1373 swf_ShapeNew(&shape);
1374 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1375 rgb.r = obj->fillrgb.r;
1376 rgb.g = obj->fillrgb.g;
1377 rgb.b = obj->fillrgb.b;
1378 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1380 shapeid = ++currentswfid;
1381 swf_SetU16(tag,shapeid); // ID
1388 swf_SetRect(tag,&r);
1390 swf_SetShapeStyles(tag,shape);
1391 swf_ShapeCountBits(shape,NULL,NULL);
1392 swf_SetShapeBits(tag,shape);
1394 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1395 swflastx=swflasty=0;
1399 static void starttext(struct swfoutput*obj)
1405 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1406 textid = ++currentswfid;
1407 swf_SetU16(tag, textid);
1414 swf_SetRect(tag,&r);
1423 swf_SetMatrix(tag,&m);
1424 swflastx=swflasty=0;
1427 static void endshape()
1431 swf_ShapeSetEnd(tag);
1432 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1433 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1437 static void endtext()
1443 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1444 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1448 static void endpage(struct swfoutput*obj)
1455 swfoutput_endclip(obj);
1459 atag = action_Stop(atag);
1460 atag = action_End(atag);
1461 tag = swf_InsertTag(tag,ST_DOACTION);
1462 swf_ActionSet(tag,atag);
1464 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1467 void swfoutput_newpage(struct swfoutput*obj)
1471 for(depth--;depth>=startdepth;depth--) {
1472 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1473 swf_SetU16(tag,depth);
1480 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1481 up, complete the swf, and write it out. */
1482 void swfoutput_destroy(struct swfoutput* obj)
1485 fontlist_t *tmp,*iterator = fontlist;
1487 delete iterator->font;
1490 iterator = iterator->next;
1498 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1503 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1507 tag = swf_InsertTag(tag,ST_END);
1510 if FAILED(swf_WriteSWC(fi,&swf))
1511 msg("<error> WriteSWC() failed.\n");
1513 if FAILED(swf_WriteSWF(fi,&swf))
1514 msg("<error> WriteSWF() failed.\n");
1519 msg("<notice> SWF written\n");
1522 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1525 if(mode == DRAWMODE_FILL)
1527 else if(mode == DRAWMODE_EOFILL)
1529 else if(mode == DRAWMODE_STROKE)
1531 else if(mode == DRAWMODE_CLIP)
1533 else if(mode == DRAWMODE_EOCLIP)
1537 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1539 if(obj->fillrgb.r == r &&
1540 obj->fillrgb.g == g &&
1541 obj->fillrgb.b == b &&
1542 obj->fillrgb.a == a) return;
1552 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1554 if(obj->strokergb.r == r &&
1555 obj->strokergb.g == g &&
1556 obj->strokergb.b == b &&
1557 obj->strokergb.a == a) return;
1561 obj->strokergb.r = r;
1562 obj->strokergb.g = g;
1563 obj->strokergb.b = b;
1564 obj->strokergb.a = a;
1567 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1569 if(obj->linewidth == (u16)(linewidth*20))
1574 obj->linewidth = (u16)(linewidth*20);
1578 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1587 msg("<warning> Too many clip levels.");
1592 int olddrawmode = drawmode;
1593 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1594 swfoutput_drawpath(obj, outline, m);
1595 swf_ShapeSetEnd(tag);
1596 swfoutput_setdrawmode(obj, olddrawmode);
1598 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1599 cliptags[clippos] = tag;
1600 clipshapes[clippos] = shapeid;
1601 clipdepths[clippos] = depth++;
1606 void swfoutput_endclip(swfoutput*obj)
1614 msg("<error> Invalid end of clipping region");
1618 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1621 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1623 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1626 if(!strncmp("http://pdf2swf:", url, 15)) {
1627 char*tmp = strdup(url);
1628 int l = strlen(tmp);
1631 swfoutput_namedlink(obj, tmp+15, points);
1642 actions = action_GetUrl(0, url, "_parent");
1644 actions = action_GetUrl(0, url, "_this");
1645 actions = action_End(actions);
1647 drawlink(obj, actions, 0, points,0);
1649 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1658 actions = action_GotoFrame(0, page);
1659 actions = action_End(actions);
1661 drawlink(obj, actions, 0, points,0);
1664 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1665 of the viewer objects, like subtitles, index elements etc.
1667 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1669 ActionTAG *actions1,*actions2;
1670 char*tmp = strdup(name);
1678 if(!strncmp(tmp, "call:", 5))
1680 char*x = strchr(&tmp[5], ':');
1682 actions1 = action_PushInt(0, 0); //number of parameters (0)
1683 actions1 = action_PushString(actions1, &tmp[5]); //function name
1684 actions1 = action_CallFunction(actions1);
1687 actions1 = action_PushString(0, x+1); //parameter
1688 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1689 actions1 = action_PushString(actions1, &tmp[5]); //function name
1690 actions1 = action_CallFunction(actions1);
1692 actions2 = action_End(0);
1697 actions1 = action_PushString(0, "/:subtitle");
1698 actions1 = action_PushString(actions1, name);
1699 actions1 = action_SetVariable(actions1);
1700 actions1 = action_End(actions1);
1702 actions2 = action_PushString(0, "/:subtitle");
1703 actions2 = action_PushString(actions2, "");
1704 actions2 = action_SetVariable(actions2);
1705 actions2 = action_End(actions2);
1708 drawlink(obj, actions1, actions2, points,mouseover);
1710 swf_ActionFree(actions1);
1711 swf_ActionFree(actions2);
1715 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1721 struct plotxy p1,p2,p3,p4;
1725 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1729 int buttonid = ++currentswfid;
1732 if(points[t].x>xmax) xmax=points[t].x;
1733 if(points[t].y>ymax) ymax=points[t].y;
1734 if(points[t].x<xmin) xmin=points[t].x;
1735 if(points[t].y<ymin) ymin=points[t].y;
1738 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1739 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1741 /* the following code subtracts the upper left edge from all coordinates,
1742 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1743 Necessary for preprocessing with swfcombine. */
1744 posx = xmin; posy = ymin;
1745 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1746 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1747 xmin -= posx; ymin -= posy;
1748 xmax -= posx; ymax -= posy;
1751 myshapeid = ++currentswfid;
1752 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1753 swf_ShapeNew(&shape);
1754 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1755 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1756 swf_SetU16(tag, myshapeid);
1757 r.xmin = (int)(xmin*20);
1758 r.ymin = (int)(ymin*20);
1759 r.xmax = (int)(xmax*20);
1760 r.ymax = (int)(ymax*20);
1761 swf_SetRect(tag,&r);
1762 swf_SetShapeStyles(tag,shape);
1763 swf_ShapeCountBits(shape,NULL,NULL);
1764 swf_SetShapeBits(tag,shape);
1765 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1766 swflastx = swflasty = 0;
1772 swf_ShapeSetEnd(tag);
1775 myshapeid2 = ++currentswfid;
1776 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1777 swf_ShapeNew(&shape);
1778 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1780 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1781 swf_SetU16(tag, myshapeid2);
1782 r.xmin = (int)(xmin*20);
1783 r.ymin = (int)(ymin*20);
1784 r.xmax = (int)(xmax*20);
1785 r.ymax = (int)(ymax*20);
1786 swf_SetRect(tag,&r);
1787 swf_SetShapeStyles(tag,shape);
1788 swf_ShapeCountBits(shape,NULL,NULL);
1789 swf_SetShapeBits(tag,shape);
1790 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1791 swflastx = swflasty = 0;
1797 swf_ShapeSetEnd(tag);
1801 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1802 swf_SetU16(tag,buttonid); //id
1803 swf_ButtonSetFlags(tag, 0); //menu=no
1804 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1805 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1806 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1807 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1809 swf_ActionSet(tag,actions1);
1814 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1815 swf_SetU16(tag,buttonid); //id
1816 swf_ButtonSetFlags(tag, 0); //menu=no
1817 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1818 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1819 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1820 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1821 swf_SetU8(tag,0); // end of button records
1822 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1823 swf_ActionSet(tag,actions1);
1825 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1826 swf_ActionSet(tag,actions2);
1828 swf_ButtonPostProcess(tag, 2);
1831 swf_ButtonPostProcess(tag, 1);
1835 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1837 if(posx!=0 || posy!=0) {
1839 swf_GetMatrix(0,&m);
1840 m.tx = (int)(posx*20);
1841 m.ty = (int)(posy*20);
1842 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1845 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1849 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1850 double x1,double y1,
1851 double x2,double y2,
1852 double x3,double y3,
1853 double x4,double y4)
1859 struct plotxy p1,p2,p3,p4;
1861 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1862 if(x2>xmax) xmax=x2;
1863 if(y2>ymax) ymax=y2;
1864 if(x2<xmin) xmin=x2;
1865 if(y2<ymin) ymin=y2;
1866 if(x3>xmax) xmax=x3;
1867 if(y3>ymax) ymax=y3;
1868 if(x3<xmin) xmin=x3;
1869 if(y3<ymin) ymin=y3;
1870 if(x4>xmax) xmax=x4;
1871 if(y4>ymax) ymax=y4;
1872 if(x4<xmin) xmin=x4;
1873 if(y4<ymin) ymin=y4;
1879 {p1.x = (int)(p1.x*20)/20.0;
1880 p1.y = (int)(p1.y*20)/20.0;
1881 p2.x = (int)(p2.x*20)/20.0;
1882 p2.y = (int)(p2.y*20)/20.0;
1883 p3.x = (int)(p3.x*20)/20.0;
1884 p3.y = (int)(p3.y*20)/20.0;
1885 p4.x = (int)(p4.x*20)/20.0;
1886 p4.y = (int)(p4.y*20)/20.0;}
1889 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1890 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1891 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1892 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1894 m.tx = (int)(p1.x*20);
1895 m.ty = (int)(p1.y*20);
1898 myshapeid = ++currentswfid;
1899 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1900 swf_ShapeNew(&shape);
1901 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1902 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1903 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1904 swf_SetU16(tag, myshapeid);
1905 r.xmin = (int)(xmin*20);
1906 r.ymin = (int)(ymin*20);
1907 r.xmax = (int)(xmax*20);
1908 r.ymax = (int)(ymax*20);
1909 swf_SetRect(tag,&r);
1910 swf_SetShapeStyles(tag,shape);
1911 swf_ShapeCountBits(shape,NULL,NULL);
1912 swf_SetShapeBits(tag,shape);
1913 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1914 swflastx = swflasty = 0;
1921 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1922 ShapeSetLine (tag, shape, (int)(x1*20);
1923 ShapeSetLine (tag, shape, x*20,0);
1924 ShapeSetLine (tag, shape, 0,-y*20);
1925 ShapeSetLine (tag, shape, -x*20,0);*/
1926 swf_ShapeSetEnd(tag);
1929 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1930 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1933 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1934 double x1,double y1,
1935 double x2,double y2,
1936 double x3,double y3,
1937 double x4,double y4)
1945 int bitid = ++currentswfid;
1947 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1948 swf_SetU16(tag, bitid);
1949 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1955 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1959 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1960 double x1,double y1,
1961 double x2,double y2,
1962 double x3,double y3,
1963 double x4,double y4)
1973 int bitid = ++currentswfid;
1975 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1976 swf_SetU16(tag, bitid);
1977 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1978 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1982 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1983 double x1,double y1,
1984 double x2,double y2,
1985 double x3,double y3,
1986 double x4,double y4)
1994 int bitid = ++currentswfid;
1996 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1997 swf_SetU16(tag, bitid);
1998 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2004 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2008 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2009 double x1,double y1,
2010 double x2,double y2,
2011 double x3,double y3,
2012 double x4,double y4, int n)
2023 /* SWF expects scanlines to be 4 byte aligned */
2026 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2028 for(y=0;y<sizey;y++)
2030 for(x=0;x<sizex;x++)
2031 *ptr++ = mem[y*sizex+x];
2032 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2037 int bitid = ++currentswfid;
2039 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2040 swf_SetU16(tag, bitid);
2041 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2049 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2053 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2054 double x1,double y1,
2055 double x2,double y2,
2056 double x3,double y3,
2057 double x4,double y4)
2065 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);