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"
41 int ignoredraworder=0;
44 int storeallcharacters=0;
49 int fontsplinemaxerror=1;
51 static char storefont = 0;
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 fillstyleid;
71 static int linestyleid;
72 static int swflastx=0;
73 static int swflasty=0;
74 static int lastwasfill = 0;
75 static int shapeisempty = 1;
87 char fillstylechanged = 0;
89 static void startshape(struct swfoutput* obj);
90 static void starttext(struct swfoutput* obj);
91 static void endshape();
92 static void endtext(struct swfoutput* obj);
94 // matrix multiplication. changes p0
95 static void transform (plotxy*p0,struct swfmatrix*m)
98 x = m->m11*p0->x+m->m12*p0->y;
99 y = m->m21*p0->x+m->m22*p0->y;
104 // write a move-to command into the swf
105 static int moveto(TAG*tag, plotxy p0)
107 int rx = (int)(p0.x*20);
108 int ry = (int)(p0.y*20);
109 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
110 swf_ShapeSetMove (tag, shape, rx,ry);
111 fillstylechanged = 0;
119 // write a line-to command into the swf
120 static void lineto(TAG*tag, plotxy p0)
122 int px = (int)(p0.x*20);
123 int py = (int)(p0.y*20);
124 int rx = (px-swflastx);
125 int ry = (py-swflasty);
126 /* we can't skip this for rx=0,ry=0, those
128 swf_ShapeSetLine (tag, shape, rx,ry);
130 //swf_ExpandRect3(boundingBox, px, py, linewidth);
131 //swf_ExpandRect3(boundingBox, swflastx, swflasty, linewidth);
138 // write a spline-to command into the swf
139 static void splineto(TAG*tag, plotxy control,plotxy end)
141 int cx = ((int)(control.x*20)-swflastx);
142 int cy = ((int)(control.y*20)-swflasty);
145 int ex = ((int)(end.x*20)-swflastx);
146 int ey = ((int)(end.y*20)-swflasty);
149 if(cx || cy || ex || ey)
150 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
154 /* write a line, given two points and the transformation
156 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
164 /* write a cubic (!) spline. This involves calling the approximate()
165 function out of spline.cc to convert it to a quadratic spline. */
166 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
169 struct qspline q[128];
183 /* fonts use a different approximation than shapes */
184 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
185 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
187 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
191 moveto(tag,q[t].start);
192 splineto(tag,q[t].control, q[t].end);
202 static void stopFill()
206 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
207 fillstylechanged = 1;
211 static void startFill()
215 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
216 fillstylechanged = 1;
221 /* draw an outline. These are generated by pdf2swf and by t1lib
222 (representing characters). */
223 void drawpath(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int log)
225 if( tag->id != ST_DEFINESHAPE &&
226 tag->id != ST_DEFINESHAPE2 &&
227 tag->id != ST_DEFINESHAPE3)
229 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
233 double lastx=0,lasty=0;
234 double firstx=0,firsty=0;
239 x += (outline->dest.x/(float)0xffff);
240 y += (outline->dest.y/(float)0xffff);
241 if(outline->type == SWF_PATHTYPE_MOVE)
243 if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
244 /* drawmode=FILL (not EOFILL) means that
245 seperate shapes do not cancel each other out.
246 On SWF side, we need to start a new shape for each
247 closed polygon, because SWF only knows EOFILL.
254 if(((int)(lastx*20) != (int)(firstx*20) ||
255 (int)(lasty*20) != (int)(firsty*20)) &&
264 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
265 line(tag, p0, p1, m);
271 else if(outline->type == SWF_PATHTYPE_LINE)
279 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
282 else if(outline->type == SWF_PATHTYPE_BEZIER)
288 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
291 p1.x=o2->C.x/(float)0xffff+lastx;
292 p1.y=o2->C.y/(float)0xffff+lasty;
293 p2.x=o2->B.x/(float)0xffff+lastx;
294 p2.y=o2->B.y/(float)0xffff+lasty;
297 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
298 spline(tag,p0,p1,p2,p3,m);
301 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
305 outline = outline->link;
307 if(((int)(lastx*20) != (int)(firstx*20) ||
308 (int)(lasty*20) != (int)(firsty*20)) &&
317 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
318 line(tag, p0, p1, m);
322 plotxy getPivot(SWF_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
324 SWF_PATHPOINT next, next2;
325 double xv=0,yv=0, xv2=0, yv2=0;
330 if(outline->type == SWF_PATHTYPE_LINE) {
331 next = outline->dest;
333 next = ((SWF_BEZIERSEGMENT*)outline)->B;
334 if(next.x==0 && next.y==0) {
335 next = ((SWF_BEZIERSEGMENT*)outline)->C;
337 if(next.x==0 && next.y==0) {
338 next = ((SWF_BEZIERSEGMENT*)outline)->dest;
342 if(trytwo && outline->last && outline->last->type != SWF_PATHTYPE_MOVE) {
343 if(outline->type == SWF_PATHTYPE_LINE) {
344 next2 = outline->last->dest;
346 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)(outline->last))->C;
347 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)(outline->last))->B;
348 next2.x = outline->last->dest.x - c.x;
349 next2.y = outline->last->dest.y - c.y;
350 if(next2.x==0 && next2.y==0) {
351 next2.x = outline->last->dest.x - b.x;
352 next2.y = outline->last->dest.y - b.y;
354 if(next2.x==0 && next2.y==0) {
355 next2.x = outline->last->dest.x;
356 next2.y = outline->last->dest.y;
362 if(outline->type == SWF_PATHTYPE_LINE) {
363 next = outline->dest;
365 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)outline)->C;
366 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)outline)->B;
367 next.x = outline->dest.x - c.x;
368 next.y = outline->dest.y - c.y;
369 if(next.x==0 && next.y==0) {
370 next.x = outline->dest.x - b.x;
371 next.y = outline->dest.y - b.y;
373 if(next.x==0 && next.y==0) {
374 next.x = outline->dest.x;
375 next.y = outline->dest.y;
379 if(trytwo && outline->link && outline->link->type != SWF_PATHTYPE_MOVE) {
380 if(outline->type == SWF_PATHTYPE_LINE) {
381 next2 = outline->link->dest;
383 next2 = ((SWF_BEZIERSEGMENT*)(outline->link))->B;
384 if(next2.x==0 && next2.y==0) {
385 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->C;
387 if(next2.x==0 && next2.y==0) {
388 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->dest;
396 xv = next.y/(float)0xffff;
397 yv = -next.x/(float)0xffff;
399 xv = -next.y/(float)0xffff;
400 yv = next.x/(float)0xffff;
403 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
409 xv2 = next2.y/(float)0xffff;
410 yv2 = -next2.x/(float)0xffff;
412 xv2 = -next2.y/(float)0xffff;
413 yv2 = next2.x/(float)0xffff;
416 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
421 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
431 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline)
433 double lastx=x, lasty=y;
434 while (outline && outline->type != SWF_PATHTYPE_MOVE)
436 x += (outline->dest.x/(float)0xffff);
437 y += (outline->dest.y/(float)0xffff);
439 if(outline->type == SWF_PATHTYPE_LINE)
446 line(tag, p0, p1, m);
448 else if(outline->type == SWF_PATHTYPE_BEZIER)
451 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
454 p1.x=o2->C.x/(float)0xffff+lastx;
455 p1.y=o2->C.y/(float)0xffff+lasty;
456 p2.x=o2->B.x/(float)0xffff+lastx;
457 p2.y=o2->B.y/(float)0xffff+lasty;
460 spline(tag,p0,p1,p2,p3,m);
464 outline = outline->link;
468 void drawShortPathWithEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
473 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
476 SWF_OUTLINE *last, *tmp=outline;
477 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
483 while(tmp && tmp->type != SWF_PATHTYPE_MOVE) {
485 lx += (tmp->dest.x/(float)0xffff);
486 ly += (tmp->dest.y/(float)0xffff);
489 s = getPivot(outline, 0, line_width, 0, 0);
490 e = getPivot(last, 0, line_width, 1, 0);
492 if(line_cap == LINE_CAP_BUTT) {
493 /* make the clipping rectangle slighly bigger
494 than the line ending, so that it get's clipped
504 p2.x = x2 - s.y - s.x*ee;
505 p2.y = y2 + s.x - s.y*ee;
506 p3.x = x2 - s.y + s.x*ee;
507 p3.y = y2 + s.x + s.y*ee;
512 m2.x = lx + e.y - e.x*ee;
513 m2.y = ly - e.x - e.y*ee;
514 m3.x = lx + e.y + e.x*ee;
515 m3.y = ly - e.x + e.y*ee;
517 for(nr=0;nr<2;nr++) {
519 struct plotxy q0,q1,q2,q3,q4,q5;
521 if(line_cap == LINE_CAP_BUTT) {
524 q1.x = sizex; q1.y = 0;
525 q2.x = sizex; q2.y = sizey;
526 q3.x = 0; q3.y = sizey;
528 q0.x = sizex; q0.y = sizey;
529 q1.x = 0; q1.y = sizey;
531 q3.x = sizex; q3.y = 0;
545 line(tag, p0, p1, m);
546 line(tag, p1, p2, m);
547 line(tag, p2, p3, m);
548 line(tag, p3, p0, m);
550 if(line_cap == LINE_CAP_BUTT) {
552 swf_ShapeSetEnd(tag);
553 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
554 swf_ObjectPlaceClip(tag,shapeid,depth,NULL,NULL,NULL,depth+2-nr);
568 drawShortPath(output,x,y,m,outline);
570 if(line_cap == LINE_CAP_BUTT) {
576 void drawT1toRect(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
578 plotxy d1,d2,p1,p2,p3,p4;
580 d1.x = (outline->dest.x/(float)0xffff);
581 d1.y = (outline->dest.y/(float)0xffff);
582 d2 = getPivot(outline, 0, line_width, 0, 0);
584 assert(line_cap != LINE_CAP_ROUND);
585 if(line_cap == LINE_CAP_SQUARE) {
594 p2.x = x + d2.x + d1.x;
595 p2.y = y + d2.y + d1.y;
596 p3.x = x - d2.x + d1.x;
597 p3.y = y - d2.y + d1.y;
607 void drawShortPathWithStraightEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
609 SWF_OUTLINE*tmp=outline;
615 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
617 while(tmp->link && tmp->link->type!=SWF_PATHTYPE_MOVE) {
618 xx += (tmp->dest.x/(float)0xffff);
619 yy += (tmp->dest.y/(float)0xffff);
623 assert(tmp->type == SWF_PATHTYPE_LINE);
624 assert(outline->type == SWF_PATHTYPE_LINE);
628 if(outline->link == tmp) {
629 /* the two straight line segments (which are everything we
630 need to draw) are very likely to overlap. To avoid that
631 they cancel each other out at the end points, start a new
632 shape for the second one */
633 endshape();startshape(output);
637 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
639 if(outline->link != tmp)
643 tmp->type = SWF_PATHTYPE_MOVE;
644 x += (outline->dest.x/(float)0xffff);
645 y += (outline->dest.y/(float)0xffff);
646 outline = outline->link;
647 drawShortPath(output, x, y, m, outline);
655 static int t1len(SWF_OUTLINE*line)
658 while(line && line->type != SWF_PATHTYPE_MOVE) {
665 static float t1linelen(SWF_OUTLINE*line)
668 x = (line->dest.x/(float)0xffff);
669 y = (line->dest.y/(float)0xffff);
670 return sqrt(x*x+y*y);
673 void drawpath2poly(struct swfoutput *output, SWF_OUTLINE*outline, struct swfmatrix*m, int log, int line_join, int line_cap, double line_width, double miter_limit)
675 if( tag->id != ST_DEFINESHAPE &&
676 tag->id != ST_DEFINESHAPE2 &&
677 tag->id != ST_DEFINESHAPE3) {
678 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
683 double lastx=0,lasty=0;
686 SWF_OUTLINE*tmp = outline, *last = 0;
691 x += (tmp->dest.x/(float)0xffff);
692 y += (tmp->dest.y/(float)0xffff);
694 if(!tmp || tmp->type == SWF_PATHTYPE_MOVE) {
696 if(last->type == SWF_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
697 lastwasline && line_cap != LINE_CAP_ROUND)
698 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
700 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
714 if(tmp && tmp->type == SWF_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
720 tmp->link->last = tmp; // make sure list is properly linked in both directions
725 static inline int colorcompare(RGBA*a,RGBA*b)
737 static const int CHARDATAMAX = 8192;
745 } chardata[CHARDATAMAX];
748 static SRECT getcharacterbbox(SWFFONT*font)
751 memset(&r, 0, sizeof(r));
755 for(t=0;t<chardatapos;t++)
757 SRECT b = font->layout->bounds[chardata[t].charid];
758 b.xmin *= chardata[t].size;
759 b.ymin *= chardata[t].size;
760 b.xmax *= chardata[t].size;
761 b.ymax *= chardata[t].size;
766 b.xmin += chardata[t].x;
767 b.ymin += chardata[t].y;
768 b.xmax += chardata[t].x;
769 b.ymax += chardata[t].y;
770 printf("(%d,%d,%d,%d) -> (%d,%d,%d,%d)\n",
771 font->layout->bounds[chardata[t].charid].xmin,
772 font->layout->bounds[chardata[t].charid].ymin,
773 font->layout->bounds[chardata[t].charid].xmax,
774 font->layout->bounds[chardata[t].charid].ymax,
779 swf_ExpandRect2(&r, &b);
781 printf("-----> (%d,%d,%d,%d)\n",
789 static void putcharacters(TAG*tag)
794 color.r = chardata[0].color.r^255;
803 int charadvance[128];
806 int glyphbits=1; //TODO: can this be zero?
809 if(tag->id != ST_DEFINETEXT &&
810 tag->id != ST_DEFINETEXT2) {
811 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
815 msg("<warning> putcharacters called with zero characters");
818 for(pass = 0; pass < 2; pass++)
828 advancebits++; // add sign bit
829 swf_SetU8(tag, glyphbits);
830 swf_SetU8(tag, advancebits);
833 for(t=0;t<=chardatapos;t++)
835 if(lastfontid != chardata[t].fontid ||
836 lastx!=chardata[t].x ||
837 lasty!=chardata[t].y ||
838 !colorcompare(&color, &chardata[t].color) ||
840 lastsize != chardata[t].size ||
843 if(charstorepos && pass==0)
846 for(s=0;s<charstorepos;s++)
848 while(charids[s]>=(1<<glyphbits))
850 while(charadvance[s]>=(1<<advancebits))
854 if(charstorepos && pass==1)
856 tag->writeBit = 0; // Q&D
857 swf_SetBits(tag, 0, 1); // GLYPH Record
858 swf_SetBits(tag, charstorepos, 7); // number of glyphs
860 for(s=0;s<charstorepos;s++)
862 swf_SetBits(tag, charids[s], glyphbits);
863 swf_SetBits(tag, charadvance[s], advancebits);
868 if(pass == 1 && t<chardatapos)
874 if(lastx != chardata[t].x ||
875 lasty != chardata[t].y)
877 newx = chardata[t].x;
878 newy = chardata[t].y;
884 if(!colorcompare(&color, &chardata[t].color))
886 color = chardata[t].color;
889 font.id = chardata[t].fontid;
890 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
893 tag->writeBit = 0; // Q&D
894 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
897 lastfontid = chardata[t].fontid;
898 lastx = chardata[t].x;
899 lasty = chardata[t].y;
900 lastsize = chardata[t].size;
907 int nextt = t==chardatapos-1?t:t+1;
908 int rel = chardata[nextt].x-chardata[t].x;
909 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
911 lastx=chardata[nextt].x;
917 charids[charstorepos] = chardata[t].charid;
918 charadvance[charstorepos] = advance;
925 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
926 int x,int y, int size)
928 if(chardatapos == CHARDATAMAX)
930 msg("<warning> Character buffer too small. SWF will be slightly bigger");
934 chardata[chardatapos].fontid = fontid;
935 chardata[chardatapos].charid = charid;
936 chardata[chardatapos].x = x;
937 chardata[chardatapos].y = y;
938 chardata[chardatapos].color = obj->fillrgb;
939 chardata[chardatapos].size = size;
949 #define FONT_INTERNAL_SIZE 1
951 /* process a character. */
952 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
955 msg("<warning> Font is NULL");
959 int charid = getCharID(swffont, charnr, character, u);
962 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
963 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
974 float det = ((m->m11*m->m22)-(m->m21*m->m12));
975 if(fabs(det) < 0.0005) {
976 /* x direction equals y direction- the text is invisible */
979 det = 20*FONT_INTERNAL_SIZE / det;
982 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
983 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
985 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
986 swf_FontUseGlyph(swffont, charid);
991 SWF_OUTLINE*outline = font->getOutline(character, charnr);
992 char* charname = character;
995 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
996 FIXNULL(character),charnr,FIXNULL(font->getName()));
1015 drawpath(tag, outline, &m2, 0);
1020 static void endtext(swfoutput*obj)
1025 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1026 swf_SetU16(tag, textid);
1029 r = getcharacterbbox(obj->swffont);
1031 swf_SetRect(tag,&r);
1034 swf_GetMatrix(0, &m);
1035 swf_SetMatrix(tag,&m);
1039 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1040 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1045 /* draw a curved polygon. */
1046 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1052 /* Multiple polygons in one shape don't overlap correctly,
1053 so we better start a new shape here if the polygon is filled
1055 if(shapeid>=0 && fill && !ignoredraworder) {
1067 drawpath(output, outline,m, 0);
1070 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1080 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1083 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1087 for(t=0;t<font->numchars;t++) {
1088 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1092 /* if we didn't find the character, maybe
1093 we can find the capitalized version */
1094 for(t=0;t<font->numchars;t++) {
1095 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1102 /* try to use the unicode id */
1103 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1104 return font->ascii2glyph[u];
1108 if(charnr>=0 && charnr<font->numchars) {
1112 /* the following is technically wrong, and only works if the font encoding
1113 is US-ASCII based. It's needed for fonts which return broken unicode
1115 /* if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1116 return font->ascii2glyph[charnr];
1123 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1124 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1126 fontlist_t*last=0,*iterator;
1128 msg("<error> No fontid");
1132 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1135 iterator = fontlist;
1137 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1138 obj->swffont = iterator->swffont;
1142 iterator = iterator->next;
1146 msg("<error> No filename given for font- internal error?");
1150 swf_SetLoadFontParameters(0,/*skip unused*/0,/*full unicode*/1);
1151 SWFFONT*swffont = swf_LoadFont(filename);
1154 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1155 swffont = swf_LoadFont(0);
1158 swf_FontSetID(swffont, ++currentswfid);
1160 if(screenloglevel >= LOGLEVEL_DEBUG) {
1161 // print font information
1162 msg("<debug> Font %s (%s)",swffont->name, filename);
1163 msg("<debug> | ID: %d", swffont->id);
1164 msg("<debug> | Version: %d", swffont->version);
1165 msg("<debug> | Name: %s", fontid);
1166 msg("<debug> | Numchars: %d", swffont->numchars);
1167 msg("<debug> | Maxascii: %d", swffont->maxascii);
1168 msg("<debug> | Style: %d", swffont->style);
1169 msg("<debug> | Encoding: %d", swffont->encoding);
1170 for(int iii=0; iii<swffont->numchars;iii++) {
1171 msg("<debug> | Glyph %d) name=%s, unicode=%d size=%d bbox=(%.2f,%.2f,%.2f,%.2f)\n", iii, swffont->glyphnames[iii], swffont->glyph2ascii[iii], swffont->glyph[iii].shape->bitlen,
1172 swffont->layout->bounds[iii].xmin/20.0,
1173 swffont->layout->bounds[iii].ymin/20.0,
1174 swffont->layout->bounds[iii].xmax/20.0,
1175 swffont->layout->bounds[iii].ymax/20.0
1180 /* set the font name to the ID we use here */
1181 if(swffont->name) free(swffont->name);
1182 swffont->name = (U8*)strdup(fontid);
1184 iterator = new fontlist_t;
1185 iterator->swffont = swffont;
1189 last->next = iterator;
1191 fontlist = iterator;
1193 obj->swffont = swffont;
1196 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1198 fontlist_t *iterator = fontlist;
1200 if(!strcmp((char*)iterator->swffont->name,fontid))
1202 iterator = iterator->next;
1207 /* set's the matrix which is to be applied to characters drawn by
1208 swfoutput_drawchar() */
1209 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1210 double m21,double m22)
1212 if(obj->fontm11 == m11 &&
1213 obj->fontm12 == m12 &&
1214 obj->fontm21 == m21 &&
1215 obj->fontm22 == m22)
1225 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1226 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1229 obj->fontmatrix = m;
1232 /* draws a character at x,y. */
1233 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1236 m.m11 = obj->fontm11;
1237 m.m12 = obj->fontm12;
1238 m.m21 = obj->fontm21;
1239 m.m22 = obj->fontm22;
1242 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1245 /* initialize the swf writer */
1246 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1250 memset(obj, 0, sizeof(struct swfoutput));
1251 filename = _filename;
1255 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1260 memset(&swf,0x00,sizeof(SWF));
1262 swf.fileVersion = flashversion;
1263 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1264 swf.movieSize.xmin = 20*x1;
1265 swf.movieSize.ymin = 20*y1;
1266 swf.movieSize.xmax = 20*x2;
1267 swf.movieSize.ymax = 20*y2;
1271 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1273 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1274 swf_SetRGB(tag,&rgb);
1276 if(1)/* add white rectangle */
1281 int shapeid = ++currentswfid;
1286 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1288 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1289 swf_SetU16(tag,shapeid);
1290 swf_SetRect(tag,&r);
1291 swf_SetShapeHeader(tag,s);
1292 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1293 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1294 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1295 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1296 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1297 swf_ShapeSetEnd(tag);
1299 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1300 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1301 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1302 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1306 tag = swf_InsertTag(tag, ST_PROTECT);
1311 void swfoutput_setprotected() //write PROTECT tag
1316 static void startshape(struct swfoutput*obj)
1324 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1326 swf_ShapeNew(&shape);
1327 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1328 rgb.r = obj->fillrgb.r;
1329 rgb.g = obj->fillrgb.g;
1330 rgb.b = obj->fillrgb.b;
1331 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1333 shapeid = ++currentswfid;
1334 swf_SetU16(tag,shapeid); // ID
1336 /* TODO: patch back */
1342 swf_SetRect(tag,&r);
1344 swf_SetShapeStyles(tag,shape);
1345 swf_ShapeCountBits(shape,NULL,NULL);
1346 swf_SetShapeBits(tag,shape);
1348 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1349 swflastx=swflasty=0;
1354 static void starttext(struct swfoutput*obj)
1359 textid = ++currentswfid;
1361 swflastx=swflasty=0;
1364 static void endshape()
1368 swf_ShapeSetEnd(tag);
1371 // delete the tag again, we didn't do anything
1374 swf_DeleteTag(todel);
1376 /* TODO: fix bounding box */
1377 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1378 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1383 static void endpage(struct swfoutput*obj)
1390 swfoutput_endclip(obj);
1394 atag = action_Stop(atag);
1395 atag = action_End(atag);
1396 tag = swf_InsertTag(tag,ST_DOACTION);
1397 swf_ActionSet(tag,atag);
1399 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1402 void swfoutput_newpage(struct swfoutput*obj)
1406 for(depth--;depth>=startdepth;depth--) {
1407 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1408 swf_SetU16(tag,depth);
1414 /* Perform cleaning up, complete the swf, and write it out. */
1415 void swfoutput_destroy(struct swfoutput* obj)
1418 fontlist_t *tmp,*iterator = fontlist;
1420 TAG*mtag = swf.firstTag;
1421 if(iterator->swffont) {
1422 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1423 /*if(!storeallcharacters)
1424 swf_FontReduce(iterator->swffont);*/
1425 swf_FontSetDefine2(mtag, iterator->swffont);
1426 swf_FontFree(iterator->swffont);
1430 iterator = iterator->next;
1437 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1442 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1446 tag = swf_InsertTag(tag,ST_END);
1448 if(enablezlib || flashversion>=6) {
1449 if FAILED(swf_WriteSWC(fi,&swf))
1450 msg("<error> WriteSWC() failed.\n");
1452 if FAILED(swf_WriteSWF(fi,&swf))
1453 msg("<error> WriteSWF() failed.\n");
1458 msg("<notice> SWF written\n");
1461 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1463 obj->drawmode = mode;
1464 if(mode == DRAWMODE_FILL)
1466 else if(mode == DRAWMODE_EOFILL)
1468 else if(mode == DRAWMODE_STROKE)
1470 else if(mode == DRAWMODE_CLIP)
1472 else if(mode == DRAWMODE_EOCLIP)
1476 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1478 if(obj->fillrgb.r == r &&
1479 obj->fillrgb.g == g &&
1480 obj->fillrgb.b == b &&
1481 obj->fillrgb.a == a) return;
1491 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1493 if(obj->strokergb.r == r &&
1494 obj->strokergb.g == g &&
1495 obj->strokergb.b == b &&
1496 obj->strokergb.a == a) return;
1500 obj->strokergb.r = r;
1501 obj->strokergb.g = g;
1502 obj->strokergb.b = b;
1503 obj->strokergb.a = a;
1506 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1508 if(obj->linewidth == (u16)(linewidth*20))
1513 obj->linewidth = (u16)(linewidth*20);
1517 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1526 msg("<warning> Too many clip levels.");
1531 int olddrawmode = obj->drawmode;
1532 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1533 swfoutput_drawpath(obj, outline, m);
1534 swf_ShapeSetEnd(tag);
1535 swfoutput_setdrawmode(obj, olddrawmode);
1537 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1538 cliptags[clippos] = tag;
1539 clipshapes[clippos] = shapeid;
1540 clipdepths[clippos] = depth++;
1545 void swfoutput_endclip(swfoutput*obj)
1553 msg("<error> Invalid end of clipping region");
1557 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1560 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1562 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1565 if(!strncmp("http://pdf2swf:", url, 15)) {
1566 char*tmp = strdup(url);
1567 int l = strlen(tmp);
1570 swfoutput_namedlink(obj, tmp+15, points);
1581 actions = action_GetUrl(0, url, "_parent");
1583 actions = action_GetUrl(0, url, "_this");
1584 actions = action_End(actions);
1586 drawlink(obj, actions, 0, points,0);
1588 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1597 actions = action_GotoFrame(0, page);
1598 actions = action_End(actions);
1600 drawlink(obj, actions, 0, points,0);
1603 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1604 of the viewer objects, like subtitles, index elements etc.
1606 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1608 ActionTAG *actions1,*actions2;
1609 char*tmp = strdup(name);
1617 if(!strncmp(tmp, "call:", 5))
1619 char*x = strchr(&tmp[5], ':');
1621 actions1 = action_PushInt(0, 0); //number of parameters (0)
1622 actions1 = action_PushString(actions1, &tmp[5]); //function name
1623 actions1 = action_CallFunction(actions1);
1626 actions1 = action_PushString(0, x+1); //parameter
1627 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1628 actions1 = action_PushString(actions1, &tmp[5]); //function name
1629 actions1 = action_CallFunction(actions1);
1631 actions2 = action_End(0);
1636 actions1 = action_PushString(0, "/:subtitle");
1637 actions1 = action_PushString(actions1, name);
1638 actions1 = action_SetVariable(actions1);
1639 actions1 = action_End(actions1);
1641 actions2 = action_PushString(0, "/:subtitle");
1642 actions2 = action_PushString(actions2, "");
1643 actions2 = action_SetVariable(actions2);
1644 actions2 = action_End(actions2);
1647 drawlink(obj, actions1, actions2, points,mouseover);
1649 swf_ActionFree(actions1);
1650 swf_ActionFree(actions2);
1654 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1660 struct plotxy p1,p2,p3,p4;
1664 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1668 int buttonid = ++currentswfid;
1671 if(points[t].x>xmax) xmax=points[t].x;
1672 if(points[t].y>ymax) ymax=points[t].y;
1673 if(points[t].x<xmin) xmin=points[t].x;
1674 if(points[t].y<ymin) ymin=points[t].y;
1677 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1678 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1680 /* the following code subtracts the upper left edge from all coordinates,
1681 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1682 Necessary for preprocessing with swfcombine. */
1683 posx = xmin; posy = ymin;
1684 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1685 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1686 xmin -= posx; ymin -= posy;
1687 xmax -= posx; ymax -= posy;
1690 myshapeid = ++currentswfid;
1691 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1692 swf_ShapeNew(&shape);
1693 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1694 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1695 swf_SetU16(tag, myshapeid);
1696 r.xmin = (int)(xmin*20);
1697 r.ymin = (int)(ymin*20);
1698 r.xmax = (int)(xmax*20);
1699 r.ymax = (int)(ymax*20);
1700 swf_SetRect(tag,&r);
1701 swf_SetShapeStyles(tag,shape);
1702 swf_ShapeCountBits(shape,NULL,NULL);
1703 swf_SetShapeBits(tag,shape);
1704 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1705 swflastx = swflasty = 0;
1711 swf_ShapeSetEnd(tag);
1714 myshapeid2 = ++currentswfid;
1715 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1716 swf_ShapeNew(&shape);
1717 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1719 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1720 swf_SetU16(tag, myshapeid2);
1721 r.xmin = (int)(xmin*20);
1722 r.ymin = (int)(ymin*20);
1723 r.xmax = (int)(xmax*20);
1724 r.ymax = (int)(ymax*20);
1725 swf_SetRect(tag,&r);
1726 swf_SetShapeStyles(tag,shape);
1727 swf_ShapeCountBits(shape,NULL,NULL);
1728 swf_SetShapeBits(tag,shape);
1729 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1730 swflastx = swflasty = 0;
1736 swf_ShapeSetEnd(tag);
1740 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1741 swf_SetU16(tag,buttonid); //id
1742 swf_ButtonSetFlags(tag, 0); //menu=no
1743 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1744 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1745 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1746 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1748 swf_ActionSet(tag,actions1);
1753 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1754 swf_SetU16(tag,buttonid); //id
1755 swf_ButtonSetFlags(tag, 0); //menu=no
1756 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1757 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1758 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1759 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1760 swf_SetU8(tag,0); // end of button records
1761 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1762 swf_ActionSet(tag,actions1);
1764 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1765 swf_ActionSet(tag,actions2);
1767 swf_ButtonPostProcess(tag, 2);
1770 swf_ButtonPostProcess(tag, 1);
1774 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1776 if(posx!=0 || posy!=0) {
1778 swf_GetMatrix(0,&m);
1779 m.tx = (int)(posx*20);
1780 m.ty = (int)(posy*20);
1781 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1784 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1788 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1789 double x1,double y1,
1790 double x2,double y2,
1791 double x3,double y3,
1792 double x4,double y4)
1798 struct plotxy p1,p2,p3,p4;
1800 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1801 if(x2>xmax) xmax=x2;
1802 if(y2>ymax) ymax=y2;
1803 if(x2<xmin) xmin=x2;
1804 if(y2<ymin) ymin=y2;
1805 if(x3>xmax) xmax=x3;
1806 if(y3>ymax) ymax=y3;
1807 if(x3<xmin) xmin=x3;
1808 if(y3<ymin) ymin=y3;
1809 if(x4>xmax) xmax=x4;
1810 if(y4>ymax) ymax=y4;
1811 if(x4<xmin) xmin=x4;
1812 if(y4<ymin) ymin=y4;
1818 {p1.x = (int)(p1.x*20)/20.0;
1819 p1.y = (int)(p1.y*20)/20.0;
1820 p2.x = (int)(p2.x*20)/20.0;
1821 p2.y = (int)(p2.y*20)/20.0;
1822 p3.x = (int)(p3.x*20)/20.0;
1823 p3.y = (int)(p3.y*20)/20.0;
1824 p4.x = (int)(p4.x*20)/20.0;
1825 p4.y = (int)(p4.y*20)/20.0;}
1828 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1829 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1830 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1831 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1833 m.tx = (int)(p1.x*20);
1834 m.ty = (int)(p1.y*20);
1837 myshapeid = ++currentswfid;
1838 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1839 swf_ShapeNew(&shape);
1840 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1841 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1842 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1843 swf_SetU16(tag, myshapeid);
1844 r.xmin = (int)(xmin*20);
1845 r.ymin = (int)(ymin*20);
1846 r.xmax = (int)(xmax*20);
1847 r.ymax = (int)(ymax*20);
1848 swf_SetRect(tag,&r);
1849 swf_SetShapeStyles(tag,shape);
1850 swf_ShapeCountBits(shape,NULL,NULL);
1851 swf_SetShapeBits(tag,shape);
1852 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1853 swflastx = swflasty = 0;
1860 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1861 ShapeSetLine (tag, shape, (int)(x1*20);
1862 ShapeSetLine (tag, shape, x*20,0);
1863 ShapeSetLine (tag, shape, 0,-y*20);
1864 ShapeSetLine (tag, shape, -x*20,0);*/
1865 swf_ShapeSetEnd(tag);
1868 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1869 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1872 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1873 double x1,double y1,
1874 double x2,double y2,
1875 double x3,double y3,
1876 double x4,double y4)
1884 int bitid = ++currentswfid;
1886 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1887 swf_SetU16(tag, bitid);
1888 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1894 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1898 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1899 double x1,double y1,
1900 double x2,double y2,
1901 double x3,double y3,
1902 double x4,double y4)
1912 int bitid = ++currentswfid;
1914 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1915 swf_SetU16(tag, bitid);
1916 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1917 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1921 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1922 double x1,double y1,
1923 double x2,double y2,
1924 double x3,double y3,
1925 double x4,double y4)
1933 int bitid = ++currentswfid;
1935 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1936 swf_SetU16(tag, bitid);
1937 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
1943 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1947 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
1948 double x1,double y1,
1949 double x2,double y2,
1950 double x3,double y3,
1951 double x4,double y4, int n)
1962 /* SWF expects scanlines to be 4 byte aligned */
1965 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
1967 for(y=0;y<sizey;y++)
1969 for(x=0;x<sizex;x++)
1970 *ptr++ = mem[y*sizex+x];
1971 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
1976 int bitid = ++currentswfid;
1978 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
1979 swf_SetU16(tag, bitid);
1980 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
1988 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1992 void swfoutput_drawimageagain(struct swfoutput*obj, int id, 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 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);