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**charnamebase= T1_GetAllCharNames(id);
990 char**a= charnamebase;
1001 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
1003 this->standardtablesize = 256;
1004 if(this->charnum < this->standardtablesize)
1005 this->standardtablesize = this->charnum;
1006 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1008 for(t = 0; t < this->standardtablesize; t++) {
1009 char*name = T1_GetCharName(id,t);
1012 standardtable[t] = strdup(name);
1015 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1016 charname = (char**)malloc(charnum*sizeof(char*));
1017 width = (int*)malloc(charnum*sizeof(int));
1018 memset(width, 0, charnum*sizeof(int));
1019 memset(charname, 0, charnum*sizeof(char*));
1020 used = (char*)malloc(charnum*sizeof(char));
1021 char2swfcharid = (U16*)malloc(charnum*2);
1022 swfcharid2char = (U16*)malloc(charnum*2);
1025 memset(used,0,charnum*sizeof(char));
1027 this->swfid = ++currentswfid;
1032 map[t] = strdup(*a);
1040 int ret = T1_ReencodeFont(id, map);
1044 int ret = T1_ReencodeFont(id, map);
1046 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1047 /* Deleting the font invalidates the charname array,
1048 so we have to ask for it again now.
1049 We continue at the position we were, hoping the font
1050 didn't shrink in the meantime or something.
1052 a = T1_GetAllCharNames(id) + (a - charnamebase);
1058 char* name = T1_GetCharName(id, s);
1059 if(!name) name = "";
1060 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1061 this->width[outlinepos] = T1_GetCharWidth(id, s);
1062 this->charname[outlinepos] = strdup(name);
1074 /* free all tables, write out definefont tags */
1080 if(storeallcharacters)
1083 for(t=0;t<this->charnum;t++)
1085 if(this->charname[t])
1086 getSWFCharID(this->charname[t], -1);
1090 ptr = (int*)malloc(swfcharpos*sizeof(int));
1092 for(t=0;t<charnum;t++)
1093 if(used[t]) usednum++;
1095 if(usednum && !drawonlyshapes)
1097 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1098 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1099 swf_SetU16(ftag, this->swfid);
1100 int initpos = swf_GetTagLen(ftag);
1107 for(t=0;t<swfcharpos;t++)
1109 ptr[t] = swf_GetTagLen(ftag);
1110 swf_SetU16(ftag, 0x1234);
1112 for(t=0;t<swfcharpos;t++)
1114 *(U16*)&ftag->data[ptr[t]] =
1115 SWAP16(swf_GetTagLen(ftag)-initpos);
1119 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1123 swf_ShapeSetStyle(ftag,&s,0,1,0);
1124 fillstylechanged = 1;
1125 int lastfill = fill;
1128 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1131 swf_ShapeSetEnd(ftag);
1133 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1134 swf_SetU16(ftag, this->swfid);
1136 swf_SetU8(ftag, strlen(this->fontid));
1137 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1141 swf_SetU8(ftag, 0); //flags
1142 for(t=0;t<swfcharpos;t++)
1145 char * name = this->charname[this->swfcharid2char[t]];
1146 for(s=0;s<256;s++) {
1147 if(standardEncodingNames[s] &&
1148 !strcmp(name,standardEncodingNames[s]))
1151 swf_SetU8(ftag, (U8)s);
1157 for(t=0;t<charnum;t++)
1159 for(t=0;t<standardtablesize;t++)
1160 if(standardtable[t]) {
1161 free(standardtable[t]);
1163 free(standardtable);
1167 free(swfcharid2char);
1168 free(char2swfcharid);
1171 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1174 for(t=0;t<this->charnum;t++) {
1175 if(!strcmp(this->charname[t],name)) {
1180 /* if we didn't find the character, maybe
1181 we can find the capitalized version */
1182 for(t=0;t<this->charnum;t++) {
1183 if(!strcasecmp(this->charname[t],name))
1187 /* if we didn't find it by name, use the names of the first 256 characters
1188 of the font to try a new name based on charnr */
1189 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1190 return getOutline(this->standardtable[charnr], -1);
1193 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1197 int SWFFont::getSWFCharID(char*name, int charnr)
1200 for(t=0;t<this->charnum;t++) {
1201 if(!strcmp(this->charname[t],name)) {
1204 swfcharid2char[swfcharpos] = t;
1205 char2swfcharid[t] = swfcharpos++;
1208 return char2swfcharid[t];
1212 /* if we didn't find the character, maybe
1213 we can find the capitalized version */
1214 for(t=0;t<this->charnum;t++) {
1215 if(!strcasecmp(this->charname[t],name)) {
1218 swfcharid2char[swfcharpos] = t;
1219 char2swfcharid[t] = swfcharpos++;
1222 return char2swfcharid[t];
1226 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1227 of the font to try a new name based on charnr */
1228 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1229 return getSWFCharID(this->standardtable[charnr], -1);
1231 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1235 int SWFFont::getWidth(char*name)
1238 for(t=0;t<this->charnum;t++) {
1239 if(!strcmp(this->charname[t],name)) {
1240 return this->width[t];
1246 char*SWFFont::getName()
1257 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1258 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1260 fontlist_t*last=0,*iterator;
1261 if(obj->font && !strcmp(obj->font->fontid,fontid))
1264 iterator = fontlist;
1266 if(!strcmp(iterator->font->fontid,fontid))
1269 iterator = iterator->next;
1273 obj->font = iterator->font;
1278 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1281 SWFFont*font = new SWFFont(fontid, t1id, filename);
1282 iterator = new fontlist_t;
1283 iterator->font = font;
1287 last->next = iterator;
1289 fontlist = iterator;
1293 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1295 fontlist_t *iterator = fontlist;
1297 if(!strcmp(iterator->font->fontid,fontid))
1299 iterator = iterator->next;
1304 /* set's the matrix which is to be applied to characters drawn by
1305 swfoutput_drawchar() */
1306 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1307 double m21,double m22)
1309 if(obj->fontm11 == m11 &&
1310 obj->fontm12 == m12 &&
1311 obj->fontm21 == m21 &&
1312 obj->fontm22 == m22)
1322 /* draws a character at x,y. */
1323 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1326 m.m11 = obj->fontm11;
1327 m.m12 = obj->fontm12;
1328 m.m21 = obj->fontm21;
1329 m.m22 = obj->fontm22;
1332 drawchar(obj, obj->font, character, charnr, &m);
1335 /* initialize the swf writer */
1336 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1341 memset(obj, 0, sizeof(struct swfoutput));
1342 filename = _filename;
1346 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1350 memset(&swf,0x00,sizeof(SWF));
1352 swf.fileVersion = flashversion;
1353 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1354 swf.movieSize.xmax = 20*sizex;
1355 swf.movieSize.ymax = 20*sizey;
1357 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1362 swf_SetRGB(tag,&rgb);
1363 if(flag_protected) // good practice! /r
1364 tag = swf_InsertTag(tag, ST_PROTECT);
1369 void swfoutput_setprotected() //write PROTECT tag
1374 static void startshape(struct swfoutput*obj)
1382 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1384 swf_ShapeNew(&shape);
1385 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1386 rgb.r = obj->fillrgb.r;
1387 rgb.g = obj->fillrgb.g;
1388 rgb.b = obj->fillrgb.b;
1389 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1391 shapeid = ++currentswfid;
1392 swf_SetU16(tag,shapeid); // ID
1399 swf_SetRect(tag,&r);
1401 swf_SetShapeStyles(tag,shape);
1402 swf_ShapeCountBits(shape,NULL,NULL);
1403 swf_SetShapeBits(tag,shape);
1405 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1406 swflastx=swflasty=0;
1410 static void starttext(struct swfoutput*obj)
1416 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1417 textid = ++currentswfid;
1418 swf_SetU16(tag, textid);
1425 swf_SetRect(tag,&r);
1434 swf_SetMatrix(tag,&m);
1435 swflastx=swflasty=0;
1438 static void endshape()
1442 swf_ShapeSetEnd(tag);
1443 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1444 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1448 static void endtext()
1454 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1455 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1459 static void endpage(struct swfoutput*obj)
1466 swfoutput_endclip(obj);
1470 atag = action_Stop(atag);
1471 atag = action_End(atag);
1472 tag = swf_InsertTag(tag,ST_DOACTION);
1473 swf_ActionSet(tag,atag);
1475 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1478 void swfoutput_newpage(struct swfoutput*obj)
1482 for(depth--;depth>=startdepth;depth--) {
1483 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1484 swf_SetU16(tag,depth);
1491 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1492 up, complete the swf, and write it out. */
1493 void swfoutput_destroy(struct swfoutput* obj)
1496 fontlist_t *tmp,*iterator = fontlist;
1498 delete iterator->font;
1501 iterator = iterator->next;
1509 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1514 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1518 tag = swf_InsertTag(tag,ST_END);
1521 if FAILED(swf_WriteSWC(fi,&swf))
1522 msg("<error> WriteSWC() failed.\n");
1524 if FAILED(swf_WriteSWF(fi,&swf))
1525 msg("<error> WriteSWF() failed.\n");
1530 msg("<notice> SWF written\n");
1533 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1536 if(mode == DRAWMODE_FILL)
1538 else if(mode == DRAWMODE_EOFILL)
1540 else if(mode == DRAWMODE_STROKE)
1542 else if(mode == DRAWMODE_CLIP)
1544 else if(mode == DRAWMODE_EOCLIP)
1548 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1550 if(obj->fillrgb.r == r &&
1551 obj->fillrgb.g == g &&
1552 obj->fillrgb.b == b &&
1553 obj->fillrgb.a == a) return;
1563 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1565 if(obj->strokergb.r == r &&
1566 obj->strokergb.g == g &&
1567 obj->strokergb.b == b &&
1568 obj->strokergb.a == a) return;
1572 obj->strokergb.r = r;
1573 obj->strokergb.g = g;
1574 obj->strokergb.b = b;
1575 obj->strokergb.a = a;
1578 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1580 if(obj->linewidth == (u16)(linewidth*20))
1585 obj->linewidth = (u16)(linewidth*20);
1589 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1598 msg("<warning> Too many clip levels.");
1603 int olddrawmode = drawmode;
1604 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1605 swfoutput_drawpath(obj, outline, m);
1606 swf_ShapeSetEnd(tag);
1607 swfoutput_setdrawmode(obj, olddrawmode);
1609 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1610 cliptags[clippos] = tag;
1611 clipshapes[clippos] = shapeid;
1612 clipdepths[clippos] = depth++;
1617 void swfoutput_endclip(swfoutput*obj)
1625 msg("<error> Invalid end of clipping region");
1629 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1632 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1634 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1637 if(!strncmp("http://pdf2swf:", url, 15)) {
1638 char*tmp = strdup(url);
1639 int l = strlen(tmp);
1642 swfoutput_namedlink(obj, tmp+15, points);
1653 actions = action_GetUrl(0, url, "_parent");
1655 actions = action_GetUrl(0, url, "_this");
1656 actions = action_End(actions);
1658 drawlink(obj, actions, 0, points,0);
1660 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1669 actions = action_GotoFrame(0, page);
1670 actions = action_End(actions);
1672 drawlink(obj, actions, 0, points,0);
1675 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1676 of the viewer objects, like subtitles, index elements etc.
1678 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1680 ActionTAG *actions1,*actions2;
1681 char*tmp = strdup(name);
1689 if(!strncmp(tmp, "call:", 5))
1691 char*x = strchr(&tmp[5], ':');
1693 actions1 = action_PushInt(0, 0); //number of parameters (0)
1694 actions1 = action_PushString(actions1, &tmp[5]); //function name
1695 actions1 = action_CallFunction(actions1);
1698 actions1 = action_PushString(0, x+1); //parameter
1699 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1700 actions1 = action_PushString(actions1, &tmp[5]); //function name
1701 actions1 = action_CallFunction(actions1);
1703 actions2 = action_End(0);
1708 actions1 = action_PushString(0, "/:subtitle");
1709 actions1 = action_PushString(actions1, name);
1710 actions1 = action_SetVariable(actions1);
1711 actions1 = action_End(actions1);
1713 actions2 = action_PushString(0, "/:subtitle");
1714 actions2 = action_PushString(actions2, "");
1715 actions2 = action_SetVariable(actions2);
1716 actions2 = action_End(actions2);
1719 drawlink(obj, actions1, actions2, points,mouseover);
1721 swf_ActionFree(actions1);
1722 swf_ActionFree(actions2);
1726 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1732 struct plotxy p1,p2,p3,p4;
1736 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1740 int buttonid = ++currentswfid;
1743 if(points[t].x>xmax) xmax=points[t].x;
1744 if(points[t].y>ymax) ymax=points[t].y;
1745 if(points[t].x<xmin) xmin=points[t].x;
1746 if(points[t].y<ymin) ymin=points[t].y;
1749 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1750 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1752 /* the following code subtracts the upper left edge from all coordinates,
1753 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1754 Necessary for preprocessing with swfcombine. */
1755 posx = xmin; posy = ymin;
1756 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1757 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1758 xmin -= posx; ymin -= posy;
1759 xmax -= posx; ymax -= posy;
1762 myshapeid = ++currentswfid;
1763 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1764 swf_ShapeNew(&shape);
1765 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1766 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1767 swf_SetU16(tag, myshapeid);
1768 r.xmin = (int)(xmin*20);
1769 r.ymin = (int)(ymin*20);
1770 r.xmax = (int)(xmax*20);
1771 r.ymax = (int)(ymax*20);
1772 swf_SetRect(tag,&r);
1773 swf_SetShapeStyles(tag,shape);
1774 swf_ShapeCountBits(shape,NULL,NULL);
1775 swf_SetShapeBits(tag,shape);
1776 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1777 swflastx = swflasty = 0;
1783 swf_ShapeSetEnd(tag);
1786 myshapeid2 = ++currentswfid;
1787 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1788 swf_ShapeNew(&shape);
1789 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1791 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1792 swf_SetU16(tag, myshapeid2);
1793 r.xmin = (int)(xmin*20);
1794 r.ymin = (int)(ymin*20);
1795 r.xmax = (int)(xmax*20);
1796 r.ymax = (int)(ymax*20);
1797 swf_SetRect(tag,&r);
1798 swf_SetShapeStyles(tag,shape);
1799 swf_ShapeCountBits(shape,NULL,NULL);
1800 swf_SetShapeBits(tag,shape);
1801 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1802 swflastx = swflasty = 0;
1808 swf_ShapeSetEnd(tag);
1812 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1813 swf_SetU16(tag,buttonid); //id
1814 swf_ButtonSetFlags(tag, 0); //menu=no
1815 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1816 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1817 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1818 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1820 swf_ActionSet(tag,actions1);
1825 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1826 swf_SetU16(tag,buttonid); //id
1827 swf_ButtonSetFlags(tag, 0); //menu=no
1828 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1829 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1830 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1831 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1832 swf_SetU8(tag,0); // end of button records
1833 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1834 swf_ActionSet(tag,actions1);
1836 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1837 swf_ActionSet(tag,actions2);
1839 swf_ButtonPostProcess(tag, 2);
1842 swf_ButtonPostProcess(tag, 1);
1846 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1848 if(posx!=0 || posy!=0) {
1850 swf_GetMatrix(0,&m);
1851 m.tx = (int)(posx*20);
1852 m.ty = (int)(posy*20);
1853 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1856 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1860 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1861 double x1,double y1,
1862 double x2,double y2,
1863 double x3,double y3,
1864 double x4,double y4)
1870 struct plotxy p1,p2,p3,p4;
1872 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1873 if(x2>xmax) xmax=x2;
1874 if(y2>ymax) ymax=y2;
1875 if(x2<xmin) xmin=x2;
1876 if(y2<ymin) ymin=y2;
1877 if(x3>xmax) xmax=x3;
1878 if(y3>ymax) ymax=y3;
1879 if(x3<xmin) xmin=x3;
1880 if(y3<ymin) ymin=y3;
1881 if(x4>xmax) xmax=x4;
1882 if(y4>ymax) ymax=y4;
1883 if(x4<xmin) xmin=x4;
1884 if(y4<ymin) ymin=y4;
1890 {p1.x = (int)(p1.x*20)/20.0;
1891 p1.y = (int)(p1.y*20)/20.0;
1892 p2.x = (int)(p2.x*20)/20.0;
1893 p2.y = (int)(p2.y*20)/20.0;
1894 p3.x = (int)(p3.x*20)/20.0;
1895 p3.y = (int)(p3.y*20)/20.0;
1896 p4.x = (int)(p4.x*20)/20.0;
1897 p4.y = (int)(p4.y*20)/20.0;}
1900 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1901 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1902 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1903 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1905 m.tx = (int)(p1.x*20);
1906 m.ty = (int)(p1.y*20);
1909 myshapeid = ++currentswfid;
1910 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1911 swf_ShapeNew(&shape);
1912 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1913 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1914 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1915 swf_SetU16(tag, myshapeid);
1916 r.xmin = (int)(xmin*20);
1917 r.ymin = (int)(ymin*20);
1918 r.xmax = (int)(xmax*20);
1919 r.ymax = (int)(ymax*20);
1920 swf_SetRect(tag,&r);
1921 swf_SetShapeStyles(tag,shape);
1922 swf_ShapeCountBits(shape,NULL,NULL);
1923 swf_SetShapeBits(tag,shape);
1924 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1925 swflastx = swflasty = 0;
1932 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1933 ShapeSetLine (tag, shape, (int)(x1*20);
1934 ShapeSetLine (tag, shape, x*20,0);
1935 ShapeSetLine (tag, shape, 0,-y*20);
1936 ShapeSetLine (tag, shape, -x*20,0);*/
1937 swf_ShapeSetEnd(tag);
1940 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1941 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1944 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1945 double x1,double y1,
1946 double x2,double y2,
1947 double x3,double y3,
1948 double x4,double y4)
1956 int bitid = ++currentswfid;
1958 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1959 swf_SetU16(tag, bitid);
1960 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1966 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1970 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1971 double x1,double y1,
1972 double x2,double y2,
1973 double x3,double y3,
1974 double x4,double y4)
1984 int bitid = ++currentswfid;
1986 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1987 swf_SetU16(tag, bitid);
1988 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1989 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1993 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1994 double x1,double y1,
1995 double x2,double y2,
1996 double x3,double y3,
1997 double x4,double y4)
2005 int bitid = ++currentswfid;
2007 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2008 swf_SetU16(tag, bitid);
2009 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2015 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2019 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2020 double x1,double y1,
2021 double x2,double y2,
2022 double x3,double y3,
2023 double x4,double y4, int n)
2034 /* SWF expects scanlines to be 4 byte aligned */
2037 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2039 for(y=0;y<sizey;y++)
2041 for(x=0;x<sizex;x++)
2042 *ptr++ = mem[y*sizex+x];
2043 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2048 int bitid = ++currentswfid;
2050 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2051 swf_SetU16(tag, bitid);
2052 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2060 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2064 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2065 double x1,double y1,
2066 double x2,double y2,
2067 double x3,double y3,
2068 double x4,double y4)
2076 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);