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);
1073 /* free all tables, write out definefont tags */
1079 if(storeallcharacters)
1082 for(t=0;t<this->charnum;t++)
1084 if(this->charname[t])
1085 getSWFCharID(this->charname[t], -1);
1089 ptr = (int*)malloc(swfcharpos*sizeof(int));
1091 for(t=0;t<charnum;t++)
1092 if(used[t]) usednum++;
1094 if(usednum && !drawonlyshapes)
1096 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1097 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1098 swf_SetU16(ftag, this->swfid);
1099 int initpos = swf_GetTagLen(ftag);
1106 for(t=0;t<swfcharpos;t++)
1108 ptr[t] = swf_GetTagLen(ftag);
1109 swf_SetU16(ftag, 0x1234);
1111 for(t=0;t<swfcharpos;t++)
1113 *(U16*)&ftag->data[ptr[t]] =
1114 SWAP16(swf_GetTagLen(ftag)-initpos);
1118 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1122 swf_ShapeSetStyle(ftag,&s,0,1,0);
1123 fillstylechanged = 1;
1124 int lastfill = fill;
1127 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1130 swf_ShapeSetEnd(ftag);
1132 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1133 swf_SetU16(ftag, this->swfid);
1135 swf_SetU8(ftag, strlen(this->fontid));
1136 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1140 swf_SetU8(ftag, 0); //flags
1141 for(t=0;t<swfcharpos;t++)
1144 char * name = this->charname[this->swfcharid2char[t]];
1145 for(s=0;s<256;s++) {
1146 if(standardEncodingNames[s] &&
1147 !strcmp(name,standardEncodingNames[s]))
1150 swf_SetU8(ftag, (U8)s);
1156 for(t=0;t<charnum;t++)
1158 for(t=0;t<standardtablesize;t++)
1159 if(standardtable[t]) {
1160 free(standardtable[t]);
1162 free(standardtable);
1166 free(swfcharid2char);
1167 free(char2swfcharid);
1170 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1173 for(t=0;t<this->charnum;t++) {
1174 if(!strcmp(this->charname[t],name)) {
1179 /* if we didn't find the character, maybe
1180 we can find the capitalized version */
1181 for(t=0;t<this->charnum;t++) {
1182 if(!strcasecmp(this->charname[t],name))
1186 /* if we didn't find it by name, use the names of the first 256 characters
1187 of the font to try a new name based on charnr */
1188 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1189 return getOutline(this->standardtable[charnr], -1);
1192 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1196 int SWFFont::getSWFCharID(char*name, int charnr)
1199 for(t=0;t<this->charnum;t++) {
1200 if(!strcmp(this->charname[t],name)) {
1203 swfcharid2char[swfcharpos] = t;
1204 char2swfcharid[t] = swfcharpos++;
1207 return char2swfcharid[t];
1211 /* if we didn't find the character, maybe
1212 we can find the capitalized version */
1213 for(t=0;t<this->charnum;t++) {
1214 if(!strcasecmp(this->charname[t],name)) {
1217 swfcharid2char[swfcharpos] = t;
1218 char2swfcharid[t] = swfcharpos++;
1221 return char2swfcharid[t];
1225 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1226 of the font to try a new name based on charnr */
1227 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1228 return getSWFCharID(this->standardtable[charnr], -1);
1230 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1234 int SWFFont::getWidth(char*name)
1237 for(t=0;t<this->charnum;t++) {
1238 if(!strcmp(this->charname[t],name)) {
1239 return this->width[t];
1245 char*SWFFont::getName()
1256 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1257 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1259 fontlist_t*last=0,*iterator;
1260 if(obj->font && !strcmp(obj->font->fontid,fontid))
1263 iterator = fontlist;
1265 if(!strcmp(iterator->font->fontid,fontid))
1268 iterator = iterator->next;
1272 obj->font = iterator->font;
1277 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1280 SWFFont*font = new SWFFont(fontid, t1id, filename);
1281 iterator = new fontlist_t;
1282 iterator->font = font;
1286 last->next = iterator;
1288 fontlist = iterator;
1292 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1294 fontlist_t *iterator = fontlist;
1296 if(!strcmp(iterator->font->fontid,fontid))
1298 iterator = iterator->next;
1303 /* set's the matrix which is to be applied to characters drawn by
1304 swfoutput_drawchar() */
1305 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1306 double m21,double m22)
1308 if(obj->fontm11 == m11 &&
1309 obj->fontm12 == m12 &&
1310 obj->fontm21 == m21 &&
1311 obj->fontm22 == m22)
1321 /* draws a character at x,y. */
1322 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1325 m.m11 = obj->fontm11;
1326 m.m12 = obj->fontm12;
1327 m.m21 = obj->fontm21;
1328 m.m22 = obj->fontm22;
1331 drawchar(obj, obj->font, character, charnr, &m);
1334 /* initialize the swf writer */
1335 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1340 memset(obj, 0, sizeof(struct swfoutput));
1341 filename = _filename;
1345 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1349 memset(&swf,0x00,sizeof(SWF));
1351 swf.fileVersion = flashversion;
1352 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1353 swf.movieSize.xmax = 20*sizex;
1354 swf.movieSize.ymax = 20*sizey;
1356 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1361 swf_SetRGB(tag,&rgb);
1362 if(flag_protected) // good practice! /r
1363 tag = swf_InsertTag(tag, ST_PROTECT);
1368 void swfoutput_setprotected() //write PROTECT tag
1373 static void startshape(struct swfoutput*obj)
1381 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1383 swf_ShapeNew(&shape);
1384 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1385 rgb.r = obj->fillrgb.r;
1386 rgb.g = obj->fillrgb.g;
1387 rgb.b = obj->fillrgb.b;
1388 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1390 shapeid = ++currentswfid;
1391 swf_SetU16(tag,shapeid); // ID
1398 swf_SetRect(tag,&r);
1400 swf_SetShapeStyles(tag,shape);
1401 swf_ShapeCountBits(shape,NULL,NULL);
1402 swf_SetShapeBits(tag,shape);
1404 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1405 swflastx=swflasty=0;
1409 static void starttext(struct swfoutput*obj)
1415 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1416 textid = ++currentswfid;
1417 swf_SetU16(tag, textid);
1424 swf_SetRect(tag,&r);
1433 swf_SetMatrix(tag,&m);
1434 swflastx=swflasty=0;
1437 static void endshape()
1441 swf_ShapeSetEnd(tag);
1442 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1443 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1447 static void endtext()
1453 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1454 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1458 static void endpage(struct swfoutput*obj)
1465 swfoutput_endclip(obj);
1469 atag = action_Stop(atag);
1470 atag = action_End(atag);
1471 tag = swf_InsertTag(tag,ST_DOACTION);
1472 swf_ActionSet(tag,atag);
1474 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1477 void swfoutput_newpage(struct swfoutput*obj)
1481 for(depth--;depth>=startdepth;depth--) {
1482 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1483 swf_SetU16(tag,depth);
1490 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1491 up, complete the swf, and write it out. */
1492 void swfoutput_destroy(struct swfoutput* obj)
1495 fontlist_t *tmp,*iterator = fontlist;
1497 delete iterator->font;
1500 iterator = iterator->next;
1508 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1513 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1517 tag = swf_InsertTag(tag,ST_END);
1520 if FAILED(swf_WriteSWC(fi,&swf))
1521 msg("<error> WriteSWC() failed.\n");
1523 if FAILED(swf_WriteSWF(fi,&swf))
1524 msg("<error> WriteSWF() failed.\n");
1529 msg("<notice> SWF written\n");
1532 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1535 if(mode == DRAWMODE_FILL)
1537 else if(mode == DRAWMODE_EOFILL)
1539 else if(mode == DRAWMODE_STROKE)
1541 else if(mode == DRAWMODE_CLIP)
1543 else if(mode == DRAWMODE_EOCLIP)
1547 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1549 if(obj->fillrgb.r == r &&
1550 obj->fillrgb.g == g &&
1551 obj->fillrgb.b == b &&
1552 obj->fillrgb.a == a) return;
1562 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1564 if(obj->strokergb.r == r &&
1565 obj->strokergb.g == g &&
1566 obj->strokergb.b == b &&
1567 obj->strokergb.a == a) return;
1571 obj->strokergb.r = r;
1572 obj->strokergb.g = g;
1573 obj->strokergb.b = b;
1574 obj->strokergb.a = a;
1577 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1579 if(obj->linewidth == (u16)(linewidth*20))
1584 obj->linewidth = (u16)(linewidth*20);
1588 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1597 msg("<warning> Too many clip levels.");
1602 int olddrawmode = drawmode;
1603 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1604 swfoutput_drawpath(obj, outline, m);
1605 swf_ShapeSetEnd(tag);
1606 swfoutput_setdrawmode(obj, olddrawmode);
1608 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1609 cliptags[clippos] = tag;
1610 clipshapes[clippos] = shapeid;
1611 clipdepths[clippos] = depth++;
1616 void swfoutput_endclip(swfoutput*obj)
1624 msg("<error> Invalid end of clipping region");
1628 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1631 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1633 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1636 if(!strncmp("http://pdf2swf:", url, 15)) {
1637 char*tmp = strdup(url);
1638 int l = strlen(tmp);
1641 swfoutput_namedlink(obj, tmp+15, points);
1652 actions = action_GetUrl(0, url, "_parent");
1654 actions = action_GetUrl(0, url, "_this");
1655 actions = action_End(actions);
1657 drawlink(obj, actions, 0, points,0);
1659 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1668 actions = action_GotoFrame(0, page);
1669 actions = action_End(actions);
1671 drawlink(obj, actions, 0, points,0);
1674 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1675 of the viewer objects, like subtitles, index elements etc.
1677 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1679 ActionTAG *actions1,*actions2;
1680 char*tmp = strdup(name);
1688 if(!strncmp(tmp, "call:", 5))
1690 char*x = strchr(&tmp[5], ':');
1692 actions1 = action_PushInt(0, 0); //number of parameters (0)
1693 actions1 = action_PushString(actions1, &tmp[5]); //function name
1694 actions1 = action_CallFunction(actions1);
1697 actions1 = action_PushString(0, x+1); //parameter
1698 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1699 actions1 = action_PushString(actions1, &tmp[5]); //function name
1700 actions1 = action_CallFunction(actions1);
1702 actions2 = action_End(0);
1707 actions1 = action_PushString(0, "/:subtitle");
1708 actions1 = action_PushString(actions1, name);
1709 actions1 = action_SetVariable(actions1);
1710 actions1 = action_End(actions1);
1712 actions2 = action_PushString(0, "/:subtitle");
1713 actions2 = action_PushString(actions2, "");
1714 actions2 = action_SetVariable(actions2);
1715 actions2 = action_End(actions2);
1718 drawlink(obj, actions1, actions2, points,mouseover);
1720 swf_ActionFree(actions1);
1721 swf_ActionFree(actions2);
1725 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1731 struct plotxy p1,p2,p3,p4;
1735 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1739 int buttonid = ++currentswfid;
1742 if(points[t].x>xmax) xmax=points[t].x;
1743 if(points[t].y>ymax) ymax=points[t].y;
1744 if(points[t].x<xmin) xmin=points[t].x;
1745 if(points[t].y<ymin) ymin=points[t].y;
1748 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1749 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1751 /* the following code subtracts the upper left edge from all coordinates,
1752 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1753 Necessary for preprocessing with swfcombine. */
1754 posx = xmin; posy = ymin;
1755 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1756 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1757 xmin -= posx; ymin -= posy;
1758 xmax -= posx; ymax -= posy;
1761 myshapeid = ++currentswfid;
1762 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1763 swf_ShapeNew(&shape);
1764 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1765 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1766 swf_SetU16(tag, myshapeid);
1767 r.xmin = (int)(xmin*20);
1768 r.ymin = (int)(ymin*20);
1769 r.xmax = (int)(xmax*20);
1770 r.ymax = (int)(ymax*20);
1771 swf_SetRect(tag,&r);
1772 swf_SetShapeStyles(tag,shape);
1773 swf_ShapeCountBits(shape,NULL,NULL);
1774 swf_SetShapeBits(tag,shape);
1775 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1776 swflastx = swflasty = 0;
1782 swf_ShapeSetEnd(tag);
1785 myshapeid2 = ++currentswfid;
1786 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1787 swf_ShapeNew(&shape);
1788 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1790 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1791 swf_SetU16(tag, myshapeid2);
1792 r.xmin = (int)(xmin*20);
1793 r.ymin = (int)(ymin*20);
1794 r.xmax = (int)(xmax*20);
1795 r.ymax = (int)(ymax*20);
1796 swf_SetRect(tag,&r);
1797 swf_SetShapeStyles(tag,shape);
1798 swf_ShapeCountBits(shape,NULL,NULL);
1799 swf_SetShapeBits(tag,shape);
1800 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1801 swflastx = swflasty = 0;
1807 swf_ShapeSetEnd(tag);
1811 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1812 swf_SetU16(tag,buttonid); //id
1813 swf_ButtonSetFlags(tag, 0); //menu=no
1814 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1815 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1816 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1817 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1819 swf_ActionSet(tag,actions1);
1824 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1825 swf_SetU16(tag,buttonid); //id
1826 swf_ButtonSetFlags(tag, 0); //menu=no
1827 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1828 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1829 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1830 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1831 swf_SetU8(tag,0); // end of button records
1832 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1833 swf_ActionSet(tag,actions1);
1835 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1836 swf_ActionSet(tag,actions2);
1838 swf_ButtonPostProcess(tag, 2);
1841 swf_ButtonPostProcess(tag, 1);
1845 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1847 if(posx!=0 || posy!=0) {
1849 swf_GetMatrix(0,&m);
1850 m.tx = (int)(posx*20);
1851 m.ty = (int)(posy*20);
1852 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1855 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1859 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1860 double x1,double y1,
1861 double x2,double y2,
1862 double x3,double y3,
1863 double x4,double y4)
1869 struct plotxy p1,p2,p3,p4;
1871 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1872 if(x2>xmax) xmax=x2;
1873 if(y2>ymax) ymax=y2;
1874 if(x2<xmin) xmin=x2;
1875 if(y2<ymin) ymin=y2;
1876 if(x3>xmax) xmax=x3;
1877 if(y3>ymax) ymax=y3;
1878 if(x3<xmin) xmin=x3;
1879 if(y3<ymin) ymin=y3;
1880 if(x4>xmax) xmax=x4;
1881 if(y4>ymax) ymax=y4;
1882 if(x4<xmin) xmin=x4;
1883 if(y4<ymin) ymin=y4;
1889 {p1.x = (int)(p1.x*20)/20.0;
1890 p1.y = (int)(p1.y*20)/20.0;
1891 p2.x = (int)(p2.x*20)/20.0;
1892 p2.y = (int)(p2.y*20)/20.0;
1893 p3.x = (int)(p3.x*20)/20.0;
1894 p3.y = (int)(p3.y*20)/20.0;
1895 p4.x = (int)(p4.x*20)/20.0;
1896 p4.y = (int)(p4.y*20)/20.0;}
1899 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1900 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1901 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1902 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1904 m.tx = (int)(p1.x*20);
1905 m.ty = (int)(p1.y*20);
1908 myshapeid = ++currentswfid;
1909 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1910 swf_ShapeNew(&shape);
1911 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1912 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1913 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1914 swf_SetU16(tag, myshapeid);
1915 r.xmin = (int)(xmin*20);
1916 r.ymin = (int)(ymin*20);
1917 r.xmax = (int)(xmax*20);
1918 r.ymax = (int)(ymax*20);
1919 swf_SetRect(tag,&r);
1920 swf_SetShapeStyles(tag,shape);
1921 swf_ShapeCountBits(shape,NULL,NULL);
1922 swf_SetShapeBits(tag,shape);
1923 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1924 swflastx = swflasty = 0;
1931 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1932 ShapeSetLine (tag, shape, (int)(x1*20);
1933 ShapeSetLine (tag, shape, x*20,0);
1934 ShapeSetLine (tag, shape, 0,-y*20);
1935 ShapeSetLine (tag, shape, -x*20,0);*/
1936 swf_ShapeSetEnd(tag);
1939 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1940 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1943 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1944 double x1,double y1,
1945 double x2,double y2,
1946 double x3,double y3,
1947 double x4,double y4)
1955 int bitid = ++currentswfid;
1957 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1958 swf_SetU16(tag, bitid);
1959 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1965 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1969 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1970 double x1,double y1,
1971 double x2,double y2,
1972 double x3,double y3,
1973 double x4,double y4)
1983 int bitid = ++currentswfid;
1985 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1986 swf_SetU16(tag, bitid);
1987 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1988 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1992 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1993 double x1,double y1,
1994 double x2,double y2,
1995 double x3,double y3,
1996 double x4,double y4)
2004 int bitid = ++currentswfid;
2006 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2007 swf_SetU16(tag, bitid);
2008 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2014 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2018 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2019 double x1,double y1,
2020 double x2,double y2,
2021 double x3,double y3,
2022 double x4,double y4, int n)
2033 /* SWF expects scanlines to be 4 byte aligned */
2036 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2038 for(y=0;y<sizey;y++)
2040 for(x=0;x<sizex;x++)
2041 *ptr++ = mem[y*sizex+x];
2042 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2047 int bitid = ++currentswfid;
2049 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2050 swf_SetU16(tag, bitid);
2051 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2059 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2063 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2064 double x1,double y1,
2065 double x2,double y2,
2066 double x3,double y3,
2067 double x4,double y4)
2075 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);