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 %s in current charset (%s)",
904 FIXNULL(character),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 %s in current charset (%s)",
921 FIXNULL(character),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 standardtable[t] = strdup(name);
1020 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1021 charname = (char**)malloc(charnum*sizeof(char*));
1022 width = (int*)malloc(charnum*sizeof(int));
1023 memset(width, 0, charnum*sizeof(int));
1024 memset(charname, 0, charnum*sizeof(char*));
1025 used = (char*)malloc(charnum*sizeof(char));
1026 char2swfcharid = (U16*)malloc(charnum*2);
1027 swfcharid2char = (U16*)malloc(charnum*2);
1030 memset(used,0,charnum*sizeof(char));
1032 this->swfid = ++currentswfid;
1037 map[t] = strdup(*a);
1045 int ret = T1_ReencodeFont(id, map);
1049 int ret = T1_ReencodeFont(id, map);
1051 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1052 /* Deleting the font invalidates the charname array,
1053 so we have to ask for it again now.
1054 We continue at the position we were, hoping the font
1055 didn't shrink in the meantime or something.
1057 a = T1_GetAllCharNames(id) + (a - charnamebase);
1063 char* name = T1_GetCharName(id, s);
1064 if(!name) name = "";
1065 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1066 this->width[outlinepos] = T1_GetCharWidth(id, s);
1067 this->charname[outlinepos] = strdup(name);
1078 /* free all tables, write out definefont tags */
1084 if(storeallcharacters)
1087 for(t=0;t<this->charnum;t++)
1089 if(this->charname[t])
1090 getSWFCharID(this->charname[t], -1);
1094 ptr = (int*)malloc(swfcharpos*sizeof(int));
1096 for(t=0;t<charnum;t++)
1097 if(used[t]) usednum++;
1099 if(usednum && !drawonlyshapes)
1101 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1102 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1103 swf_SetU16(ftag, this->swfid);
1104 int initpos = swf_GetTagLen(ftag);
1111 for(t=0;t<swfcharpos;t++)
1113 ptr[t] = swf_GetTagLen(ftag);
1114 swf_SetU16(ftag, 0x1234);
1116 for(t=0;t<swfcharpos;t++)
1118 *(U16*)&ftag->data[ptr[t]] =
1119 SWAP16(swf_GetTagLen(ftag)-initpos);
1123 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1127 swf_ShapeSetStyle(ftag,&s,0,1,0);
1128 fillstylechanged = 1;
1129 int lastfill = fill;
1132 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1135 swf_ShapeSetEnd(ftag);
1137 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1138 swf_SetU16(ftag, this->swfid);
1140 swf_SetU8(ftag, strlen(this->fontid));
1141 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1145 swf_SetU8(ftag, 0); //flags
1146 for(t=0;t<swfcharpos;t++)
1149 char * name = this->charname[this->swfcharid2char[t]];
1150 for(s=0;s<256;s++) {
1151 if(standardEncodingNames[s] &&
1152 !strcmp(name,standardEncodingNames[s]))
1155 swf_SetU8(ftag, (U8)s);
1161 for(t=0;t<charnum;t++)
1163 for(t=0;t<standardtablesize;t++)
1164 if(standardtable[t]) {
1165 free(standardtable[t]);
1167 free(standardtable);
1171 free(swfcharid2char);
1172 free(char2swfcharid);
1175 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1178 for(t=0;t<this->charnum;t++) {
1179 if(!strcmp(this->charname[t],name)) {
1184 /* if we didn't find the character, maybe
1185 we can find the capitalized version */
1186 for(t=0;t<this->charnum;t++) {
1187 if(!strcasecmp(this->charname[t],name))
1191 /* if we didn't find it by name, use the names of the first 256 characters
1192 of the font to try a new name based on charnr */
1193 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1194 return getOutline(this->standardtable[charnr], -1);
1197 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1201 int SWFFont::getSWFCharID(char*name, int charnr)
1204 for(t=0;t<this->charnum;t++) {
1205 if(!strcmp(this->charname[t],name)) {
1208 swfcharid2char[swfcharpos] = t;
1209 char2swfcharid[t] = swfcharpos++;
1212 return char2swfcharid[t];
1216 /* if we didn't find the character, maybe
1217 we can find the capitalized version */
1218 for(t=0;t<this->charnum;t++) {
1219 if(!strcasecmp(this->charname[t],name)) {
1222 swfcharid2char[swfcharpos] = t;
1223 char2swfcharid[t] = swfcharpos++;
1226 return char2swfcharid[t];
1230 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1231 of the font to try a new name based on charnr */
1232 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1233 return getSWFCharID(this->standardtable[charnr], -1);
1235 msg("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
1239 int SWFFont::getWidth(char*name)
1242 for(t=0;t<this->charnum;t++) {
1243 if(!strcmp(this->charname[t],name)) {
1244 return this->width[t];
1250 char*SWFFont::getName()
1261 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1262 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1264 fontlist_t*last=0,*iterator;
1265 if(obj->font && !strcmp(obj->font->fontid,fontid))
1268 iterator = fontlist;
1270 if(!strcmp(iterator->font->fontid,fontid))
1273 iterator = iterator->next;
1277 obj->font = iterator->font;
1282 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1285 SWFFont*font = new SWFFont(fontid, t1id, filename);
1286 iterator = new fontlist_t;
1287 iterator->font = font;
1291 last->next = iterator;
1293 fontlist = iterator;
1297 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1299 fontlist_t *iterator = fontlist;
1301 if(!strcmp(iterator->font->fontid,fontid))
1303 iterator = iterator->next;
1308 /* set's the matrix which is to be applied to characters drawn by
1309 swfoutput_drawchar() */
1310 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1311 double m21,double m22)
1313 if(obj->fontm11 == m11 &&
1314 obj->fontm12 == m12 &&
1315 obj->fontm21 == m21 &&
1316 obj->fontm22 == m22)
1326 /* draws a character at x,y. */
1327 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1330 m.m11 = obj->fontm11;
1331 m.m12 = obj->fontm12;
1332 m.m21 = obj->fontm21;
1333 m.m22 = obj->fontm22;
1336 drawchar(obj, obj->font, character, charnr, &m);
1339 /* initialize the swf writer */
1340 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
1345 memset(obj, 0, sizeof(struct swfoutput));
1346 filename = _filename;
1350 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1354 memset(&swf,0x00,sizeof(SWF));
1356 swf.fileVersion = flashversion;
1357 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1358 swf.movieSize.xmax = 20*sizex;
1359 swf.movieSize.ymax = 20*sizey;
1361 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1366 swf_SetRGB(tag,&rgb);
1367 if(flag_protected) // good practice! /r
1368 tag = swf_InsertTag(tag, ST_PROTECT);
1373 void swfoutput_setprotected() //write PROTECT tag
1378 static void startshape(struct swfoutput*obj)
1386 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1388 swf_ShapeNew(&shape);
1389 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1390 rgb.r = obj->fillrgb.r;
1391 rgb.g = obj->fillrgb.g;
1392 rgb.b = obj->fillrgb.b;
1393 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1395 shapeid = ++currentswfid;
1396 swf_SetU16(tag,shapeid); // ID
1403 swf_SetRect(tag,&r);
1405 swf_SetShapeStyles(tag,shape);
1406 swf_ShapeCountBits(shape,NULL,NULL);
1407 swf_SetShapeBits(tag,shape);
1409 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1410 swflastx=swflasty=0;
1414 static void starttext(struct swfoutput*obj)
1420 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1421 textid = ++currentswfid;
1422 swf_SetU16(tag, textid);
1429 swf_SetRect(tag,&r);
1438 swf_SetMatrix(tag,&m);
1439 swflastx=swflasty=0;
1442 static void endshape()
1446 swf_ShapeSetEnd(tag);
1447 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1448 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1452 static void endtext()
1458 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1459 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1463 static void endpage(struct swfoutput*obj)
1470 swfoutput_endclip(obj);
1474 atag = action_Stop(atag);
1475 atag = action_End(atag);
1476 tag = swf_InsertTag(tag,ST_DOACTION);
1477 swf_ActionSet(tag,atag);
1479 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1482 void swfoutput_newpage(struct swfoutput*obj)
1486 for(depth--;depth>=startdepth;depth--) {
1487 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1488 swf_SetU16(tag,depth);
1495 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1496 up, complete the swf, and write it out. */
1497 void swfoutput_destroy(struct swfoutput* obj)
1500 fontlist_t *tmp,*iterator = fontlist;
1502 delete iterator->font;
1505 iterator = iterator->next;
1513 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1518 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1522 tag = swf_InsertTag(tag,ST_END);
1525 if FAILED(swf_WriteSWC(fi,&swf))
1526 msg("<error> WriteSWC() failed.\n");
1528 if FAILED(swf_WriteSWF(fi,&swf))
1529 msg("<error> WriteSWF() failed.\n");
1534 msg("<notice> SWF written\n");
1537 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1540 if(mode == DRAWMODE_FILL)
1542 else if(mode == DRAWMODE_EOFILL)
1544 else if(mode == DRAWMODE_STROKE)
1546 else if(mode == DRAWMODE_CLIP)
1548 else if(mode == DRAWMODE_EOCLIP)
1552 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1554 if(obj->fillrgb.r == r &&
1555 obj->fillrgb.g == g &&
1556 obj->fillrgb.b == b &&
1557 obj->fillrgb.a == a) return;
1567 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1569 if(obj->strokergb.r == r &&
1570 obj->strokergb.g == g &&
1571 obj->strokergb.b == b &&
1572 obj->strokergb.a == a) return;
1576 obj->strokergb.r = r;
1577 obj->strokergb.g = g;
1578 obj->strokergb.b = b;
1579 obj->strokergb.a = a;
1582 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1584 if(obj->linewidth == (u16)(linewidth*20))
1589 obj->linewidth = (u16)(linewidth*20);
1593 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1602 msg("<warning> Too many clip levels.");
1607 int olddrawmode = drawmode;
1608 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1609 swfoutput_drawpath(obj, outline, m);
1610 swf_ShapeSetEnd(tag);
1611 swfoutput_setdrawmode(obj, olddrawmode);
1613 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1614 cliptags[clippos] = tag;
1615 clipshapes[clippos] = shapeid;
1616 clipdepths[clippos] = depth++;
1621 void swfoutput_endclip(swfoutput*obj)
1629 msg("<error> Invalid end of clipping region");
1633 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1636 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1638 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1641 if(!strncmp("http://pdf2swf:", url, 15)) {
1642 char*tmp = strdup(url);
1643 int l = strlen(tmp);
1646 swfoutput_namedlink(obj, tmp+15, points);
1657 actions = action_GetUrl(0, url, "_parent");
1659 actions = action_GetUrl(0, url, "_this");
1660 actions = action_End(actions);
1662 drawlink(obj, actions, 0, points,0);
1664 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1673 actions = action_GotoFrame(0, page);
1674 actions = action_End(actions);
1676 drawlink(obj, actions, 0, points,0);
1679 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1680 of the viewer objects, like subtitles, index elements etc.
1682 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1684 ActionTAG *actions1,*actions2;
1685 char*tmp = strdup(name);
1693 if(!strncmp(tmp, "call:", 5))
1695 char*x = strchr(&tmp[5], ':');
1697 actions1 = action_PushInt(0, 0); //number of parameters (0)
1698 actions1 = action_PushString(actions1, &tmp[5]); //function name
1699 actions1 = action_CallFunction(actions1);
1702 actions1 = action_PushString(0, x+1); //parameter
1703 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1704 actions1 = action_PushString(actions1, &tmp[5]); //function name
1705 actions1 = action_CallFunction(actions1);
1707 actions2 = action_End(0);
1712 actions1 = action_PushString(0, "/:subtitle");
1713 actions1 = action_PushString(actions1, name);
1714 actions1 = action_SetVariable(actions1);
1715 actions1 = action_End(actions1);
1717 actions2 = action_PushString(0, "/:subtitle");
1718 actions2 = action_PushString(actions2, "");
1719 actions2 = action_SetVariable(actions2);
1720 actions2 = action_End(actions2);
1723 drawlink(obj, actions1, actions2, points,mouseover);
1725 swf_ActionFree(actions1);
1726 swf_ActionFree(actions2);
1730 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1736 struct plotxy p1,p2,p3,p4;
1740 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1744 int buttonid = ++currentswfid;
1747 if(points[t].x>xmax) xmax=points[t].x;
1748 if(points[t].y>ymax) ymax=points[t].y;
1749 if(points[t].x<xmin) xmin=points[t].x;
1750 if(points[t].y<ymin) ymin=points[t].y;
1753 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1754 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1756 /* the following code subtracts the upper left edge from all coordinates,
1757 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1758 Necessary for preprocessing with swfcombine. */
1759 posx = xmin; posy = ymin;
1760 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1761 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1762 xmin -= posx; ymin -= posy;
1763 xmax -= posx; ymax -= posy;
1766 myshapeid = ++currentswfid;
1767 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1768 swf_ShapeNew(&shape);
1769 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1770 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1771 swf_SetU16(tag, myshapeid);
1772 r.xmin = (int)(xmin*20);
1773 r.ymin = (int)(ymin*20);
1774 r.xmax = (int)(xmax*20);
1775 r.ymax = (int)(ymax*20);
1776 swf_SetRect(tag,&r);
1777 swf_SetShapeStyles(tag,shape);
1778 swf_ShapeCountBits(shape,NULL,NULL);
1779 swf_SetShapeBits(tag,shape);
1780 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1781 swflastx = swflasty = 0;
1787 swf_ShapeSetEnd(tag);
1790 myshapeid2 = ++currentswfid;
1791 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1792 swf_ShapeNew(&shape);
1793 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1795 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1796 swf_SetU16(tag, myshapeid2);
1797 r.xmin = (int)(xmin*20);
1798 r.ymin = (int)(ymin*20);
1799 r.xmax = (int)(xmax*20);
1800 r.ymax = (int)(ymax*20);
1801 swf_SetRect(tag,&r);
1802 swf_SetShapeStyles(tag,shape);
1803 swf_ShapeCountBits(shape,NULL,NULL);
1804 swf_SetShapeBits(tag,shape);
1805 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1806 swflastx = swflasty = 0;
1812 swf_ShapeSetEnd(tag);
1816 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1817 swf_SetU16(tag,buttonid); //id
1818 swf_ButtonSetFlags(tag, 0); //menu=no
1819 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1820 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1821 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1822 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1824 swf_ActionSet(tag,actions1);
1829 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1830 swf_SetU16(tag,buttonid); //id
1831 swf_ButtonSetFlags(tag, 0); //menu=no
1832 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1833 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1834 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1835 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1836 swf_SetU8(tag,0); // end of button records
1837 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1838 swf_ActionSet(tag,actions1);
1840 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1841 swf_ActionSet(tag,actions2);
1843 swf_ButtonPostProcess(tag, 2);
1846 swf_ButtonPostProcess(tag, 1);
1850 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1852 if(posx!=0 || posy!=0) {
1854 swf_GetMatrix(0,&m);
1855 m.tx = (int)(posx*20);
1856 m.ty = (int)(posy*20);
1857 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1860 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1864 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1865 double x1,double y1,
1866 double x2,double y2,
1867 double x3,double y3,
1868 double x4,double y4)
1874 struct plotxy p1,p2,p3,p4;
1876 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1877 if(x2>xmax) xmax=x2;
1878 if(y2>ymax) ymax=y2;
1879 if(x2<xmin) xmin=x2;
1880 if(y2<ymin) ymin=y2;
1881 if(x3>xmax) xmax=x3;
1882 if(y3>ymax) ymax=y3;
1883 if(x3<xmin) xmin=x3;
1884 if(y3<ymin) ymin=y3;
1885 if(x4>xmax) xmax=x4;
1886 if(y4>ymax) ymax=y4;
1887 if(x4<xmin) xmin=x4;
1888 if(y4<ymin) ymin=y4;
1894 {p1.x = (int)(p1.x*20)/20.0;
1895 p1.y = (int)(p1.y*20)/20.0;
1896 p2.x = (int)(p2.x*20)/20.0;
1897 p2.y = (int)(p2.y*20)/20.0;
1898 p3.x = (int)(p3.x*20)/20.0;
1899 p3.y = (int)(p3.y*20)/20.0;
1900 p4.x = (int)(p4.x*20)/20.0;
1901 p4.y = (int)(p4.y*20)/20.0;}
1904 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1905 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1906 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1907 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1909 m.tx = (int)(p1.x*20);
1910 m.ty = (int)(p1.y*20);
1913 myshapeid = ++currentswfid;
1914 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1915 swf_ShapeNew(&shape);
1916 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1917 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1918 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1919 swf_SetU16(tag, myshapeid);
1920 r.xmin = (int)(xmin*20);
1921 r.ymin = (int)(ymin*20);
1922 r.xmax = (int)(xmax*20);
1923 r.ymax = (int)(ymax*20);
1924 swf_SetRect(tag,&r);
1925 swf_SetShapeStyles(tag,shape);
1926 swf_ShapeCountBits(shape,NULL,NULL);
1927 swf_SetShapeBits(tag,shape);
1928 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1929 swflastx = swflasty = 0;
1936 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1937 ShapeSetLine (tag, shape, (int)(x1*20);
1938 ShapeSetLine (tag, shape, x*20,0);
1939 ShapeSetLine (tag, shape, 0,-y*20);
1940 ShapeSetLine (tag, shape, -x*20,0);*/
1941 swf_ShapeSetEnd(tag);
1944 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1945 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1948 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1949 double x1,double y1,
1950 double x2,double y2,
1951 double x3,double y3,
1952 double x4,double y4)
1960 int bitid = ++currentswfid;
1962 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1963 swf_SetU16(tag, bitid);
1964 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1970 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1974 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1975 double x1,double y1,
1976 double x2,double y2,
1977 double x3,double y3,
1978 double x4,double y4)
1988 int bitid = ++currentswfid;
1990 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1991 swf_SetU16(tag, bitid);
1992 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1993 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1997 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1998 double x1,double y1,
1999 double x2,double y2,
2000 double x3,double y3,
2001 double x4,double y4)
2009 int bitid = ++currentswfid;
2011 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2012 swf_SetU16(tag, bitid);
2013 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2019 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2023 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2024 double x1,double y1,
2025 double x2,double y2,
2026 double x3,double y3,
2027 double x4,double y4, int n)
2038 /* SWF expects scanlines to be 4 byte aligned */
2041 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2043 for(y=0;y<sizey;y++)
2045 for(x=0;x<sizex;x++)
2046 *ptr++ = mem[y*sizex+x];
2047 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2052 int bitid = ++currentswfid;
2054 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2055 swf_SetU16(tag, bitid);
2056 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2064 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2068 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2069 double x1,double y1,
2070 double x2,double y2,
2071 double x3,double y3,
2072 double x4,double y4)
2080 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);