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);
903 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
904 FIXNULL(character),charnr, FIXNULL(font->getName()));
911 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
912 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
916 T1_OUTLINE*outline = font->getOutline(character, charnr);
917 char* charname = character;
920 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
921 FIXNULL(character),charnr,FIXNULL(font->getName()));
940 drawpath(tag, outline, &m2, 0);
945 /* draw a curved polygon. */
946 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
952 /* Multiple polygons in one shape don't overlap correctly,
953 so we better start a new shape here if the polygon is filled
955 if(shapeid>=0 && fill && !ignoredraworder) {
967 drawpath(tag, outline,m, 0);
970 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
980 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
983 /* SWFFont: copy all t1 font outlines to a local
985 SWFFont::SWFFont(char*name, int id, char*filename)
987 if(!T1_GetFontName(id))
990 this->name = strdup(T1_GetFontFileName(id));
991 this->fontid = strdup(name);
994 char**charnamebase= T1_GetAllCharNames(id);
995 char**a= charnamebase;
1006 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
1008 this->standardtablesize = 256;
1009 if(this->charnum < this->standardtablesize)
1010 this->standardtablesize = this->charnum;
1011 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1013 for(t = 0; t < this->standardtablesize; t++) {
1014 char*name = T1_GetCharName(id,t);
1017 if(!name || !strstr(name, "notdef")) {
1018 if(t<standardEncodingSize) {
1019 name = standardEncodingNames[t];
1022 name = ""; //TODO: store something like <%d>
1025 standardtable[t] = strdup(name);
1026 msg("<debug> Char %d is named %s\n", t, name);
1029 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1030 charname = (char**)malloc(charnum*sizeof(char*));
1031 width = (int*)malloc(charnum*sizeof(int));
1032 memset(width, 0, charnum*sizeof(int));
1033 memset(charname, 0, charnum*sizeof(char*));
1034 used = (char*)malloc(charnum*sizeof(char));
1035 char2swfcharid = (U16*)malloc(charnum*2);
1036 swfcharid2char = (U16*)malloc(charnum*2);
1039 memset(used,0,charnum*sizeof(char));
1041 this->swfid = ++currentswfid;
1046 map[t] = strdup(*a);
1054 int ret = T1_ReencodeFont(id, map);
1058 int ret = T1_ReencodeFont(id, map);
1060 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1061 /* Deleting the font invalidates the charname array,
1062 so we have to ask for it again now.
1063 We continue at the position we were, hoping the font
1064 didn't shrink in the meantime or something.
1066 a = T1_GetAllCharNames(id) + (a - charnamebase);
1072 char* name = T1_GetCharName(id, s);
1073 if(!name) name = "";
1074 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1075 this->width[outlinepos] = T1_GetCharWidth(id, s);
1076 this->charname[outlinepos] = strdup(name);
1087 /* free all tables, write out definefont tags */
1093 if(storeallcharacters)
1096 for(t=0;t<this->charnum;t++)
1098 if(this->charname[t])
1099 getSWFCharID(this->charname[t], -1);
1103 ptr = (int*)malloc(swfcharpos*sizeof(int));
1105 for(t=0;t<charnum;t++)
1106 if(used[t]) usednum++;
1108 if(usednum && !drawonlyshapes)
1110 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1111 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1112 swf_SetU16(ftag, this->swfid);
1113 int initpos = swf_GetTagLen(ftag);
1120 for(t=0;t<swfcharpos;t++)
1122 ptr[t] = swf_GetTagLen(ftag);
1123 swf_SetU16(ftag, 0x1234);
1125 for(t=0;t<swfcharpos;t++)
1127 *(U16*)&ftag->data[ptr[t]] =
1128 SWAP16(swf_GetTagLen(ftag)-initpos);
1132 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1136 swf_ShapeSetStyle(ftag,&s,0,1,0);
1137 fillstylechanged = 1;
1138 int lastfill = fill;
1141 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1144 swf_ShapeSetEnd(ftag);
1146 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1147 swf_SetU16(ftag, this->swfid);
1149 swf_SetU8(ftag, strlen(this->fontid));
1150 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1154 swf_SetU8(ftag, 0); //flags
1155 for(t=0;t<swfcharpos;t++)
1158 char * name = this->charname[this->swfcharid2char[t]];
1159 for(s=0;s<256;s++) {
1160 if(standardEncodingNames[s] &&
1161 !strcmp(name,standardEncodingNames[s]))
1164 swf_SetU8(ftag, (U8)s);
1170 for(t=0;t<charnum;t++)
1172 for(t=0;t<standardtablesize;t++)
1173 if(standardtable[t]) {
1174 free(standardtable[t]);
1176 free(standardtable);
1180 free(swfcharid2char);
1181 free(char2swfcharid);
1184 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1187 for(t=0;t<this->charnum;t++) {
1188 if(!strcmp(this->charname[t],name)) {
1193 /* if we didn't find the character, maybe
1194 we can find the capitalized version */
1195 for(t=0;t<this->charnum;t++) {
1196 if(!strcasecmp(this->charname[t],name))
1200 /* if we didn't find it by name, use the names of the first 256 characters
1201 of the font to try a new name based on charnr */
1202 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1203 T1_OUTLINE*ret = getOutline(this->standardtable[charnr], -1);
1210 int SWFFont::getSWFCharID(char*name, int charnr)
1213 for(t=0;t<this->charnum;t++) {
1214 if(!strcmp(this->charname[t],name)) {
1217 swfcharid2char[swfcharpos] = t;
1218 char2swfcharid[t] = swfcharpos++;
1221 return char2swfcharid[t];
1225 /* if we didn't find the character, maybe
1226 we can find the capitalized version */
1227 for(t=0;t<this->charnum;t++) {
1228 if(!strcasecmp(this->charname[t],name)) {
1231 swfcharid2char[swfcharpos] = t;
1232 char2swfcharid[t] = swfcharpos++;
1235 return char2swfcharid[t];
1239 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1240 of the font to try a new name based on charnr */
1241 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1242 int ret = getSWFCharID(this->standardtable[charnr], -1);
1248 int SWFFont::getWidth(char*name)
1251 for(t=0;t<this->charnum;t++) {
1252 if(!strcmp(this->charname[t],name)) {
1253 return this->width[t];
1259 char*SWFFont::getName()
1270 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1271 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1273 fontlist_t*last=0,*iterator;
1274 if(obj->font && !strcmp(obj->font->fontid,fontid))
1277 iterator = fontlist;
1279 if(!strcmp(iterator->font->fontid,fontid))
1282 iterator = iterator->next;
1286 obj->font = iterator->font;
1291 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1294 SWFFont*font = new SWFFont(fontid, t1id, filename);
1295 iterator = new fontlist_t;
1296 iterator->font = font;
1300 last->next = iterator;
1302 fontlist = iterator;
1306 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1308 fontlist_t *iterator = fontlist;
1310 if(!strcmp(iterator->font->fontid,fontid))
1312 iterator = iterator->next;
1317 /* set's the matrix which is to be applied to characters drawn by
1318 swfoutput_drawchar() */
1319 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1320 double m21,double m22)
1322 if(obj->fontm11 == m11 &&
1323 obj->fontm12 == m12 &&
1324 obj->fontm21 == m21 &&
1325 obj->fontm22 == m22)
1335 /* draws a character at x,y. */
1336 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1339 m.m11 = obj->fontm11;
1340 m.m12 = obj->fontm12;
1341 m.m21 = obj->fontm21;
1342 m.m22 = obj->fontm22;
1345 drawchar(obj, obj->font, character, charnr, &m);
1348 /* initialize the swf writer */
1349 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1354 memset(obj, 0, sizeof(struct swfoutput));
1355 filename = _filename;
1359 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1363 memset(&swf,0x00,sizeof(SWF));
1365 swf.fileVersion = flashversion;
1366 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1367 swf.movieSize.xmax = 20*sizex;
1368 swf.movieSize.ymax = 20*sizey;
1370 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1375 swf_SetRGB(tag,&rgb);
1376 if(flag_protected) // good practice! /r
1377 tag = swf_InsertTag(tag, ST_PROTECT);
1382 void swfoutput_setprotected() //write PROTECT tag
1387 static void startshape(struct swfoutput*obj)
1395 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1397 swf_ShapeNew(&shape);
1398 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1399 rgb.r = obj->fillrgb.r;
1400 rgb.g = obj->fillrgb.g;
1401 rgb.b = obj->fillrgb.b;
1402 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1404 shapeid = ++currentswfid;
1405 swf_SetU16(tag,shapeid); // ID
1412 swf_SetRect(tag,&r);
1414 swf_SetShapeStyles(tag,shape);
1415 swf_ShapeCountBits(shape,NULL,NULL);
1416 swf_SetShapeBits(tag,shape);
1418 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1419 swflastx=swflasty=0;
1423 static void starttext(struct swfoutput*obj)
1429 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1430 textid = ++currentswfid;
1431 swf_SetU16(tag, textid);
1438 swf_SetRect(tag,&r);
1447 swf_SetMatrix(tag,&m);
1448 swflastx=swflasty=0;
1451 static void endshape()
1455 swf_ShapeSetEnd(tag);
1456 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1457 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1461 static void endtext()
1467 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1468 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1472 static void endpage(struct swfoutput*obj)
1479 swfoutput_endclip(obj);
1483 atag = action_Stop(atag);
1484 atag = action_End(atag);
1485 tag = swf_InsertTag(tag,ST_DOACTION);
1486 swf_ActionSet(tag,atag);
1488 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1491 void swfoutput_newpage(struct swfoutput*obj)
1495 for(depth--;depth>=startdepth;depth--) {
1496 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1497 swf_SetU16(tag,depth);
1504 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1505 up, complete the swf, and write it out. */
1506 void swfoutput_destroy(struct swfoutput* obj)
1509 fontlist_t *tmp,*iterator = fontlist;
1511 delete iterator->font;
1514 iterator = iterator->next;
1522 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1527 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1531 tag = swf_InsertTag(tag,ST_END);
1534 if FAILED(swf_WriteSWC(fi,&swf))
1535 msg("<error> WriteSWC() failed.\n");
1537 if FAILED(swf_WriteSWF(fi,&swf))
1538 msg("<error> WriteSWF() failed.\n");
1543 msg("<notice> SWF written\n");
1546 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1549 if(mode == DRAWMODE_FILL)
1551 else if(mode == DRAWMODE_EOFILL)
1553 else if(mode == DRAWMODE_STROKE)
1555 else if(mode == DRAWMODE_CLIP)
1557 else if(mode == DRAWMODE_EOCLIP)
1561 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1563 if(obj->fillrgb.r == r &&
1564 obj->fillrgb.g == g &&
1565 obj->fillrgb.b == b &&
1566 obj->fillrgb.a == a) return;
1576 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1578 if(obj->strokergb.r == r &&
1579 obj->strokergb.g == g &&
1580 obj->strokergb.b == b &&
1581 obj->strokergb.a == a) return;
1585 obj->strokergb.r = r;
1586 obj->strokergb.g = g;
1587 obj->strokergb.b = b;
1588 obj->strokergb.a = a;
1591 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1593 if(obj->linewidth == (u16)(linewidth*20))
1598 obj->linewidth = (u16)(linewidth*20);
1602 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1611 msg("<warning> Too many clip levels.");
1616 int olddrawmode = drawmode;
1617 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1618 swfoutput_drawpath(obj, outline, m);
1619 swf_ShapeSetEnd(tag);
1620 swfoutput_setdrawmode(obj, olddrawmode);
1622 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1623 cliptags[clippos] = tag;
1624 clipshapes[clippos] = shapeid;
1625 clipdepths[clippos] = depth++;
1630 void swfoutput_endclip(swfoutput*obj)
1638 msg("<error> Invalid end of clipping region");
1642 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1645 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1647 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1650 if(!strncmp("http://pdf2swf:", url, 15)) {
1651 char*tmp = strdup(url);
1652 int l = strlen(tmp);
1655 swfoutput_namedlink(obj, tmp+15, points);
1666 actions = action_GetUrl(0, url, "_parent");
1668 actions = action_GetUrl(0, url, "_this");
1669 actions = action_End(actions);
1671 drawlink(obj, actions, 0, points,0);
1673 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1682 actions = action_GotoFrame(0, page);
1683 actions = action_End(actions);
1685 drawlink(obj, actions, 0, points,0);
1688 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1689 of the viewer objects, like subtitles, index elements etc.
1691 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1693 ActionTAG *actions1,*actions2;
1694 char*tmp = strdup(name);
1702 if(!strncmp(tmp, "call:", 5))
1704 char*x = strchr(&tmp[5], ':');
1706 actions1 = action_PushInt(0, 0); //number of parameters (0)
1707 actions1 = action_PushString(actions1, &tmp[5]); //function name
1708 actions1 = action_CallFunction(actions1);
1711 actions1 = action_PushString(0, x+1); //parameter
1712 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1713 actions1 = action_PushString(actions1, &tmp[5]); //function name
1714 actions1 = action_CallFunction(actions1);
1716 actions2 = action_End(0);
1721 actions1 = action_PushString(0, "/:subtitle");
1722 actions1 = action_PushString(actions1, name);
1723 actions1 = action_SetVariable(actions1);
1724 actions1 = action_End(actions1);
1726 actions2 = action_PushString(0, "/:subtitle");
1727 actions2 = action_PushString(actions2, "");
1728 actions2 = action_SetVariable(actions2);
1729 actions2 = action_End(actions2);
1732 drawlink(obj, actions1, actions2, points,mouseover);
1734 swf_ActionFree(actions1);
1735 swf_ActionFree(actions2);
1739 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1745 struct plotxy p1,p2,p3,p4;
1749 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1753 int buttonid = ++currentswfid;
1756 if(points[t].x>xmax) xmax=points[t].x;
1757 if(points[t].y>ymax) ymax=points[t].y;
1758 if(points[t].x<xmin) xmin=points[t].x;
1759 if(points[t].y<ymin) ymin=points[t].y;
1762 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1763 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1765 /* the following code subtracts the upper left edge from all coordinates,
1766 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1767 Necessary for preprocessing with swfcombine. */
1768 posx = xmin; posy = ymin;
1769 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1770 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1771 xmin -= posx; ymin -= posy;
1772 xmax -= posx; ymax -= posy;
1775 myshapeid = ++currentswfid;
1776 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1777 swf_ShapeNew(&shape);
1778 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1779 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1780 swf_SetU16(tag, myshapeid);
1781 r.xmin = (int)(xmin*20);
1782 r.ymin = (int)(ymin*20);
1783 r.xmax = (int)(xmax*20);
1784 r.ymax = (int)(ymax*20);
1785 swf_SetRect(tag,&r);
1786 swf_SetShapeStyles(tag,shape);
1787 swf_ShapeCountBits(shape,NULL,NULL);
1788 swf_SetShapeBits(tag,shape);
1789 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1790 swflastx = swflasty = 0;
1796 swf_ShapeSetEnd(tag);
1799 myshapeid2 = ++currentswfid;
1800 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1801 swf_ShapeNew(&shape);
1802 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1804 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1805 swf_SetU16(tag, myshapeid2);
1806 r.xmin = (int)(xmin*20);
1807 r.ymin = (int)(ymin*20);
1808 r.xmax = (int)(xmax*20);
1809 r.ymax = (int)(ymax*20);
1810 swf_SetRect(tag,&r);
1811 swf_SetShapeStyles(tag,shape);
1812 swf_ShapeCountBits(shape,NULL,NULL);
1813 swf_SetShapeBits(tag,shape);
1814 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1815 swflastx = swflasty = 0;
1821 swf_ShapeSetEnd(tag);
1825 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
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);
1833 swf_ActionSet(tag,actions1);
1838 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1839 swf_SetU16(tag,buttonid); //id
1840 swf_ButtonSetFlags(tag, 0); //menu=no
1841 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1842 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1843 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1844 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1845 swf_SetU8(tag,0); // end of button records
1846 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1847 swf_ActionSet(tag,actions1);
1849 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1850 swf_ActionSet(tag,actions2);
1852 swf_ButtonPostProcess(tag, 2);
1855 swf_ButtonPostProcess(tag, 1);
1859 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1861 if(posx!=0 || posy!=0) {
1863 swf_GetMatrix(0,&m);
1864 m.tx = (int)(posx*20);
1865 m.ty = (int)(posy*20);
1866 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1869 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1873 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1874 double x1,double y1,
1875 double x2,double y2,
1876 double x3,double y3,
1877 double x4,double y4)
1883 struct plotxy p1,p2,p3,p4;
1885 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1886 if(x2>xmax) xmax=x2;
1887 if(y2>ymax) ymax=y2;
1888 if(x2<xmin) xmin=x2;
1889 if(y2<ymin) ymin=y2;
1890 if(x3>xmax) xmax=x3;
1891 if(y3>ymax) ymax=y3;
1892 if(x3<xmin) xmin=x3;
1893 if(y3<ymin) ymin=y3;
1894 if(x4>xmax) xmax=x4;
1895 if(y4>ymax) ymax=y4;
1896 if(x4<xmin) xmin=x4;
1897 if(y4<ymin) ymin=y4;
1903 {p1.x = (int)(p1.x*20)/20.0;
1904 p1.y = (int)(p1.y*20)/20.0;
1905 p2.x = (int)(p2.x*20)/20.0;
1906 p2.y = (int)(p2.y*20)/20.0;
1907 p3.x = (int)(p3.x*20)/20.0;
1908 p3.y = (int)(p3.y*20)/20.0;
1909 p4.x = (int)(p4.x*20)/20.0;
1910 p4.y = (int)(p4.y*20)/20.0;}
1913 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1914 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1915 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1916 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1918 m.tx = (int)(p1.x*20);
1919 m.ty = (int)(p1.y*20);
1922 myshapeid = ++currentswfid;
1923 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1924 swf_ShapeNew(&shape);
1925 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1926 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1927 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1928 swf_SetU16(tag, myshapeid);
1929 r.xmin = (int)(xmin*20);
1930 r.ymin = (int)(ymin*20);
1931 r.xmax = (int)(xmax*20);
1932 r.ymax = (int)(ymax*20);
1933 swf_SetRect(tag,&r);
1934 swf_SetShapeStyles(tag,shape);
1935 swf_ShapeCountBits(shape,NULL,NULL);
1936 swf_SetShapeBits(tag,shape);
1937 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1938 swflastx = swflasty = 0;
1945 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1946 ShapeSetLine (tag, shape, (int)(x1*20);
1947 ShapeSetLine (tag, shape, x*20,0);
1948 ShapeSetLine (tag, shape, 0,-y*20);
1949 ShapeSetLine (tag, shape, -x*20,0);*/
1950 swf_ShapeSetEnd(tag);
1953 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1954 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1957 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1958 double x1,double y1,
1959 double x2,double y2,
1960 double x3,double y3,
1961 double x4,double y4)
1969 int bitid = ++currentswfid;
1971 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1972 swf_SetU16(tag, bitid);
1973 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1979 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1983 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1984 double x1,double y1,
1985 double x2,double y2,
1986 double x3,double y3,
1987 double x4,double y4)
1997 int bitid = ++currentswfid;
1999 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2000 swf_SetU16(tag, bitid);
2001 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2002 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2006 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2007 double x1,double y1,
2008 double x2,double y2,
2009 double x3,double y3,
2010 double x4,double y4)
2018 int bitid = ++currentswfid;
2020 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2021 swf_SetU16(tag, bitid);
2022 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2028 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2032 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2033 double x1,double y1,
2034 double x2,double y2,
2035 double x3,double y3,
2036 double x4,double y4, int n)
2047 /* SWF expects scanlines to be 4 byte aligned */
2050 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2052 for(y=0;y<sizey;y++)
2054 for(x=0;x<sizex;x++)
2055 *ptr++ = mem[y*sizex+x];
2056 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2061 int bitid = ++currentswfid;
2063 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2064 swf_SetU16(tag, bitid);
2065 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2073 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2077 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2078 double x1,double y1,
2079 double x2,double y2,
2080 double x3,double y3,
2081 double x4,double y4)
2089 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);