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;
65 static int linewidth = 0;
68 static int shapeid = -1;
69 static int textid = -1;
71 static int fillstyleid;
72 static int linestyleid;
73 static int swflastx=0;
74 static int swflasty=0;
75 static int lastwasfill = 0;
76 static int shapeisempty = 1;
88 char fillstylechanged = 0;
93 static void startshape(struct swfoutput* obj);
94 static void starttext(struct swfoutput* obj);
95 static void endshape(int clip);
96 static void endtext(struct swfoutput* obj);
98 // matrix multiplication. changes p0
99 static void transform (plotxy*p0,struct swfmatrix*m)
102 x = m->m11*p0->x+m->m12*p0->y;
103 y = m->m21*p0->x+m->m22*p0->y;
108 // write a move-to command into the swf
109 static int moveto(TAG*tag, plotxy p0)
111 int rx = (int)(p0.x*20);
112 int ry = (int)(p0.y*20);
113 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
114 swf_ShapeSetMove (tag, shape, rx,ry);
115 fillstylechanged = 0;
123 static void addPointToBBox(int px, int py)
129 swf_ExpandRect(&bboxrect, p);
131 swf_ExpandRect3(&bboxrect, p, linewidth*3/2);
135 // write a line-to command into the swf
136 static void lineto(TAG*tag, plotxy p0)
138 int px = (int)(p0.x*20);
139 int py = (int)(p0.y*20);
140 int rx = (px-swflastx);
141 int ry = (py-swflasty);
142 /* we can't skip this for rx=0,ry=0, those
144 swf_ShapeSetLine (tag, shape, rx,ry);
146 addPointToBBox(swflastx,swflasty);
147 addPointToBBox(px,py);
154 // write a spline-to command into the swf
155 static void splineto(TAG*tag, plotxy control,plotxy end)
157 int lastlastx = swflastx;
158 int lastlasty = swflasty;
160 int cx = ((int)(control.x*20)-swflastx);
161 int cy = ((int)(control.y*20)-swflasty);
164 int ex = ((int)(end.x*20)-swflastx);
165 int ey = ((int)(end.y*20)-swflasty);
169 if(cx || cy || ex || ey) {
170 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
171 addPointToBBox(lastlastx ,lastlasty );
172 addPointToBBox(lastlastx+cx,lastlasty+cy);
173 addPointToBBox(lastlastx+cx+ex,lastlasty+cy+ey);
178 /* write a line, given two points and the transformation
180 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
188 /* write a cubic (!) spline. This involves calling the approximate()
189 function out of spline.cc to convert it to a quadratic spline. */
190 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
193 struct qspline q[128];
207 /* fonts use a different approximation than shapes */
208 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
209 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
211 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
215 moveto(tag,q[t].start);
216 splineto(tag,q[t].control, q[t].end);
226 static void stopFill()
230 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
231 fillstylechanged = 1;
235 static void startFill()
239 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
240 fillstylechanged = 1;
245 /* draw an outline. These are generated by pdf2swf and by t1lib
246 (representing characters). */
247 void drawpath(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int log)
249 if( tag->id != ST_DEFINESHAPE &&
250 tag->id != ST_DEFINESHAPE2 &&
251 tag->id != ST_DEFINESHAPE3)
253 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
257 double lastx=0,lasty=0;
258 double firstx=0,firsty=0;
263 x += (outline->dest.x/(float)0xffff);
264 y += (outline->dest.y/(float)0xffff);
265 if(outline->type == SWF_PATHTYPE_MOVE)
267 if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
268 /* drawmode=FILL (not EOFILL) means that
269 seperate shapes do not cancel each other out.
270 On SWF side, we need to start a new shape for each
271 closed polygon, because SWF only knows EOFILL.
278 if(((int)(lastx*20) != (int)(firstx*20) ||
279 (int)(lasty*20) != (int)(firsty*20)) &&
288 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
289 line(tag, p0, p1, m);
295 else if(outline->type == SWF_PATHTYPE_LINE)
303 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
306 else if(outline->type == SWF_PATHTYPE_BEZIER)
312 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
315 p1.x=o2->C.x/(float)0xffff+lastx;
316 p1.y=o2->C.y/(float)0xffff+lasty;
317 p2.x=o2->B.x/(float)0xffff+lastx;
318 p2.y=o2->B.y/(float)0xffff+lasty;
321 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
322 spline(tag,p0,p1,p2,p3,m);
325 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
329 outline = outline->link;
331 if(((int)(lastx*20) != (int)(firstx*20) ||
332 (int)(lasty*20) != (int)(firsty*20)) &&
341 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
342 line(tag, p0, p1, m);
346 plotxy getPivot(SWF_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
348 SWF_PATHPOINT next, next2;
349 double xv=0,yv=0, xv2=0, yv2=0;
354 if(outline->type == SWF_PATHTYPE_LINE) {
355 next = outline->dest;
357 next = ((SWF_BEZIERSEGMENT*)outline)->B;
358 if(next.x==0 && next.y==0) {
359 next = ((SWF_BEZIERSEGMENT*)outline)->C;
361 if(next.x==0 && next.y==0) {
362 next = ((SWF_BEZIERSEGMENT*)outline)->dest;
366 if(trytwo && outline->last && outline->last->type != SWF_PATHTYPE_MOVE) {
367 if(outline->type == SWF_PATHTYPE_LINE) {
368 next2 = outline->last->dest;
370 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)(outline->last))->C;
371 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)(outline->last))->B;
372 next2.x = outline->last->dest.x - c.x;
373 next2.y = outline->last->dest.y - c.y;
374 if(next2.x==0 && next2.y==0) {
375 next2.x = outline->last->dest.x - b.x;
376 next2.y = outline->last->dest.y - b.y;
378 if(next2.x==0 && next2.y==0) {
379 next2.x = outline->last->dest.x;
380 next2.y = outline->last->dest.y;
386 if(outline->type == SWF_PATHTYPE_LINE) {
387 next = outline->dest;
389 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)outline)->C;
390 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)outline)->B;
391 next.x = outline->dest.x - c.x;
392 next.y = outline->dest.y - c.y;
393 if(next.x==0 && next.y==0) {
394 next.x = outline->dest.x - b.x;
395 next.y = outline->dest.y - b.y;
397 if(next.x==0 && next.y==0) {
398 next.x = outline->dest.x;
399 next.y = outline->dest.y;
403 if(trytwo && outline->link && outline->link->type != SWF_PATHTYPE_MOVE) {
404 if(outline->type == SWF_PATHTYPE_LINE) {
405 next2 = outline->link->dest;
407 next2 = ((SWF_BEZIERSEGMENT*)(outline->link))->B;
408 if(next2.x==0 && next2.y==0) {
409 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->C;
411 if(next2.x==0 && next2.y==0) {
412 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->dest;
420 xv = next.y/(float)0xffff;
421 yv = -next.x/(float)0xffff;
423 xv = -next.y/(float)0xffff;
424 yv = next.x/(float)0xffff;
427 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
433 xv2 = next2.y/(float)0xffff;
434 yv2 = -next2.x/(float)0xffff;
436 xv2 = -next2.y/(float)0xffff;
437 yv2 = next2.x/(float)0xffff;
440 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
445 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
455 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline)
457 double lastx=x, lasty=y;
458 while (outline && outline->type != SWF_PATHTYPE_MOVE)
460 x += (outline->dest.x/(float)0xffff);
461 y += (outline->dest.y/(float)0xffff);
463 if(outline->type == SWF_PATHTYPE_LINE)
470 line(tag, p0, p1, m);
472 else if(outline->type == SWF_PATHTYPE_BEZIER)
475 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
478 p1.x=o2->C.x/(float)0xffff+lastx;
479 p1.y=o2->C.y/(float)0xffff+lasty;
480 p2.x=o2->B.x/(float)0xffff+lastx;
481 p2.y=o2->B.y/(float)0xffff+lasty;
484 spline(tag,p0,p1,p2,p3,m);
488 outline = outline->link;
492 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)
497 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
500 SWF_OUTLINE *last, *tmp=outline;
501 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
507 while(tmp && tmp->type != SWF_PATHTYPE_MOVE) {
509 lx += (tmp->dest.x/(float)0xffff);
510 ly += (tmp->dest.y/(float)0xffff);
513 s = getPivot(outline, 0, line_width, 0, 0);
514 e = getPivot(last, 0, line_width, 1, 0);
516 if(line_cap == LINE_CAP_BUTT) {
517 /* make the clipping rectangle slighly bigger
518 than the line ending, so that it get's clipped
528 p2.x = x2 - s.y - s.x*ee;
529 p2.y = y2 + s.x - s.y*ee;
530 p3.x = x2 - s.y + s.x*ee;
531 p3.y = y2 + s.x + s.y*ee;
536 m2.x = lx + e.y - e.x*ee;
537 m2.y = ly - e.x - e.y*ee;
538 m3.x = lx + e.y + e.x*ee;
539 m3.y = ly - e.x + e.y*ee;
541 for(nr=0;nr<2;nr++) {
543 struct plotxy q0,q1,q2,q3,q4,q5;
546 if(line_cap == LINE_CAP_BUTT) {
549 q1.x = sizex; q1.y = 0;
550 q2.x = sizex; q2.y = sizey;
551 q3.x = 0; q3.y = sizey;
553 q0.x = sizex; q0.y = sizey;
554 q1.x = 0; q1.y = sizey;
556 q3.x = sizex; q3.y = 0;
570 line(tag, p0, p1, m);
571 line(tag, p1, p2, m);
572 line(tag, p2, p3, m);
573 line(tag, p3, p0, m);
575 if(line_cap == LINE_CAP_BUTT) {
577 endshape(depth+2-nr);
589 drawShortPath(output,x,y,m,outline);
591 if(line_cap == LINE_CAP_BUTT) {
597 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)
599 plotxy d1,d2,p1,p2,p3,p4;
601 d1.x = (outline->dest.x/(float)0xffff);
602 d1.y = (outline->dest.y/(float)0xffff);
603 d2 = getPivot(outline, 0, line_width, 0, 0);
605 assert(line_cap != LINE_CAP_ROUND);
606 if(line_cap == LINE_CAP_SQUARE) {
615 p2.x = x + d2.x + d1.x;
616 p2.y = y + d2.y + d1.y;
617 p3.x = x - d2.x + d1.x;
618 p3.y = y - d2.y + d1.y;
628 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)
630 SWF_OUTLINE*tmp=outline;
636 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
638 while(tmp->link && tmp->link->type!=SWF_PATHTYPE_MOVE) {
639 xx += (tmp->dest.x/(float)0xffff);
640 yy += (tmp->dest.y/(float)0xffff);
644 assert(tmp->type == SWF_PATHTYPE_LINE);
645 assert(outline->type == SWF_PATHTYPE_LINE);
649 if(outline->link == tmp) {
650 /* the two straight line segments (which are everything we
651 need to draw) are very likely to overlap. To avoid that
652 they cancel each other out at the end points, start a new
653 shape for the second one */
654 endshape(0);startshape(output);
658 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
660 if(outline->link != tmp)
664 tmp->type = SWF_PATHTYPE_MOVE;
665 x += (outline->dest.x/(float)0xffff);
666 y += (outline->dest.y/(float)0xffff);
667 outline = outline->link;
668 drawShortPath(output, x, y, m, outline);
676 static int t1len(SWF_OUTLINE*line)
679 while(line && line->type != SWF_PATHTYPE_MOVE) {
686 static float t1linelen(SWF_OUTLINE*line)
689 x = (line->dest.x/(float)0xffff);
690 y = (line->dest.y/(float)0xffff);
691 return sqrt(x*x+y*y);
694 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)
696 if( tag->id != ST_DEFINESHAPE &&
697 tag->id != ST_DEFINESHAPE2 &&
698 tag->id != ST_DEFINESHAPE3) {
699 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
704 double lastx=0,lasty=0;
707 SWF_OUTLINE*tmp = outline, *last = 0;
712 x += (tmp->dest.x/(float)0xffff);
713 y += (tmp->dest.y/(float)0xffff);
715 if(!tmp || tmp->type == SWF_PATHTYPE_MOVE) {
717 if(last->type == SWF_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
718 lastwasline && line_cap != LINE_CAP_ROUND)
719 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
721 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
735 if(tmp && tmp->type == SWF_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
741 tmp->link->last = tmp; // make sure list is properly linked in both directions
746 static inline int colorcompare(RGBA*a,RGBA*b)
758 static const int CHARDATAMAX = 8192;
766 } chardata[CHARDATAMAX];
769 static SRECT getcharacterbbox(SWFFONT*font)
773 memset(&r, 0, sizeof(r));
776 if(debug) printf("\n");
777 for(t=0;t<chardatapos;t++)
779 if(chardata[t].fontid != font->id) {
780 msg("<error> Internal error: fontid %d != fontid %d", chardata[t].fontid, font->id);
783 SRECT b = font->layout->bounds[chardata[t].charid];
784 b.xmin *= chardata[t].size;
785 b.ymin *= chardata[t].size;
786 b.xmax *= chardata[t].size;
787 b.ymax *= chardata[t].size;
792 b.xmin += chardata[t].x;
793 b.ymin += chardata[t].y;
794 b.xmax += chardata[t].x;
795 b.ymax += chardata[t].y;
797 /* until we solve the INTERNAL_SCALING problem (see below)
798 make sure the bounding box is big enough */
804 if(debug) printf("(%f,%f,%f,%f) -> (%f,%f,%f,%f) [font %d/%d, char %d]\n",
805 font->layout->bounds[chardata[t].charid].xmin/20.0,
806 font->layout->bounds[chardata[t].charid].ymin/20.0,
807 font->layout->bounds[chardata[t].charid].xmax/20.0,
808 font->layout->bounds[chardata[t].charid].ymax/20.0,
817 swf_ExpandRect2(&r, &b);
819 if(debug) printf("-----> (%f,%f,%f,%f)\n",
827 static void putcharacters(TAG*tag)
832 color.r = chardata[0].color.r^255;
841 int charadvance[128];
844 int glyphbits=1; //TODO: can this be zero?
847 if(tag->id != ST_DEFINETEXT &&
848 tag->id != ST_DEFINETEXT2) {
849 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
853 msg("<warning> putcharacters called with zero characters");
856 for(pass = 0; pass < 2; pass++)
866 advancebits++; // add sign bit
867 swf_SetU8(tag, glyphbits);
868 swf_SetU8(tag, advancebits);
871 for(t=0;t<=chardatapos;t++)
873 if(lastfontid != chardata[t].fontid ||
874 lastx!=chardata[t].x ||
875 lasty!=chardata[t].y ||
876 !colorcompare(&color, &chardata[t].color) ||
878 lastsize != chardata[t].size ||
881 if(charstorepos && pass==0)
884 for(s=0;s<charstorepos;s++)
886 while(charids[s]>=(1<<glyphbits))
888 while(charadvance[s]>=(1<<advancebits))
892 if(charstorepos && pass==1)
894 tag->writeBit = 0; // Q&D
895 swf_SetBits(tag, 0, 1); // GLYPH Record
896 swf_SetBits(tag, charstorepos, 7); // number of glyphs
898 for(s=0;s<charstorepos;s++)
900 swf_SetBits(tag, charids[s], glyphbits);
901 swf_SetBits(tag, charadvance[s], advancebits);
906 if(pass == 1 && t<chardatapos)
912 if(lastx != chardata[t].x ||
913 lasty != chardata[t].y)
915 newx = chardata[t].x;
916 newy = chardata[t].y;
922 if(!colorcompare(&color, &chardata[t].color))
924 color = chardata[t].color;
927 font.id = chardata[t].fontid;
928 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
931 tag->writeBit = 0; // Q&D
932 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
935 lastfontid = chardata[t].fontid;
936 lastx = chardata[t].x;
937 lasty = chardata[t].y;
938 lastsize = chardata[t].size;
945 int nextt = t==chardatapos-1?t:t+1;
946 int rel = chardata[nextt].x-chardata[t].x;
947 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
949 lastx=chardata[nextt].x;
955 charids[charstorepos] = chardata[t].charid;
956 charadvance[charstorepos] = advance;
963 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
964 int x,int y, int size)
966 if(chardatapos == CHARDATAMAX)
968 msg("<warning> Character buffer too small. SWF will be slightly bigger");
972 chardata[chardatapos].fontid = fontid;
973 chardata[chardatapos].charid = charid;
974 chardata[chardatapos].x = x;
975 chardata[chardatapos].y = y;
976 chardata[chardatapos].color = obj->fillrgb;
977 chardata[chardatapos].size = size;
987 /* todo: why don't higher values (64, 1024) work here? */
988 #define FONT_INTERNAL_SIZE 1
990 /* process a character. */
991 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
994 msg("<warning> Font is NULL");
998 int charid = getCharID(swffont, charnr, character, u);
1001 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
1002 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
1013 float det = ((m->m11*m->m22)-(m->m21*m->m12));
1014 if(fabs(det) < 0.0005) {
1015 /* x direction equals y direction- the text is invisible */
1018 det = 20*FONT_INTERNAL_SIZE / det;
1021 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
1022 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
1024 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
1025 swf_FontUseGlyph(swffont, charid);
1030 SWF_OUTLINE*outline = font->getOutline(character, charnr);
1031 char* charname = character;
1034 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
1035 FIXNULL(character),charnr,FIXNULL(font->getName()));
1054 drawpath(tag, outline, &m2, 0);
1059 static void endtext(swfoutput*obj)
1064 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1065 swf_SetU16(tag, textid);
1068 r = getcharacterbbox(obj->swffont);
1070 swf_SetRect(tag,&r);
1073 swf_GetMatrix(0, &m);
1074 swf_SetMatrix(tag,&m);
1078 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1079 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1084 /* draw a curved polygon. */
1085 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1091 /* Multiple polygons in one shape don't overlap correctly,
1092 so we better start a new shape here if the polygon is filled
1094 if(shapeid>=0 && fill && !ignoredraworder) {
1106 drawpath(output, outline,m, 0);
1109 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1119 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1122 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1126 for(t=0;t<font->numchars;t++) {
1127 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1131 /* if we didn't find the character, maybe
1132 we can find the capitalized version */
1133 for(t=0;t<font->numchars;t++) {
1134 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1141 /* try to use the unicode id */
1142 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1143 return font->ascii2glyph[u];
1147 if(charnr>=0 && charnr<font->numchars) {
1151 /* the following is technically wrong, and only works if the font encoding
1152 is US-ASCII based. It's needed for fonts which return broken unicode
1154 /* if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1155 return font->ascii2glyph[charnr];
1162 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1163 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1165 fontlist_t*last=0,*iterator;
1167 msg("<error> No fontid");
1171 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1174 /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
1175 with multiple fonts */
1178 iterator = fontlist;
1180 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1181 obj->swffont = iterator->swffont;
1185 iterator = iterator->next;
1189 msg("<error> No filename given for font- internal error?");
1193 swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1);
1194 SWFFONT*swffont = swf_LoadFont(filename);
1197 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1198 swffont = swf_LoadFont(0);
1201 swf_FontSetID(swffont, ++currentswfid);
1203 if(screenloglevel >= LOGLEVEL_DEBUG) {
1204 // print font information
1205 msg("<debug> Font %s (%s)",swffont->name, filename);
1206 msg("<debug> | ID: %d", swffont->id);
1207 msg("<debug> | Version: %d", swffont->version);
1208 msg("<debug> | Name: %s", fontid);
1209 msg("<debug> | Numchars: %d", swffont->numchars);
1210 msg("<debug> | Maxascii: %d", swffont->maxascii);
1211 msg("<debug> | Style: %d", swffont->style);
1212 msg("<debug> | Encoding: %d", swffont->encoding);
1213 for(int iii=0; iii<swffont->numchars;iii++) {
1214 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,
1215 swffont->layout->bounds[iii].xmin/20.0,
1216 swffont->layout->bounds[iii].ymin/20.0,
1217 swffont->layout->bounds[iii].xmax/20.0,
1218 swffont->layout->bounds[iii].ymax/20.0
1223 /* set the font name to the ID we use here */
1224 if(swffont->name) free(swffont->name);
1225 swffont->name = (U8*)strdup(fontid);
1227 iterator = new fontlist_t;
1228 iterator->swffont = swffont;
1232 last->next = iterator;
1234 fontlist = iterator;
1236 obj->swffont = swffont;
1239 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1241 fontlist_t *iterator = fontlist;
1243 if(!strcmp((char*)iterator->swffont->name,fontid))
1245 iterator = iterator->next;
1250 /* set's the matrix which is to be applied to characters drawn by
1251 swfoutput_drawchar() */
1252 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1253 double m21,double m22)
1255 if(obj->fontm11 == m11 &&
1256 obj->fontm12 == m12 &&
1257 obj->fontm21 == m21 &&
1258 obj->fontm22 == m22)
1268 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1269 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1272 obj->fontmatrix = m;
1275 /* draws a character at x,y. */
1276 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1279 m.m11 = obj->fontm11;
1280 m.m12 = obj->fontm12;
1281 m.m21 = obj->fontm21;
1282 m.m22 = obj->fontm22;
1285 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1288 /* initialize the swf writer */
1289 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1293 memset(obj, 0, sizeof(struct swfoutput));
1294 filename = _filename;
1298 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1303 memset(&swf,0x00,sizeof(SWF));
1305 swf.fileVersion = flashversion;
1306 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1307 swf.movieSize.xmin = 20*x1;
1308 swf.movieSize.ymin = 20*y1;
1309 swf.movieSize.xmax = 20*x2;
1310 swf.movieSize.ymax = 20*y2;
1314 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1316 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1317 swf_SetRGB(tag,&rgb);
1319 if(1)/* add white rectangle */
1324 int shapeid = ++currentswfid;
1329 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1331 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1332 swf_SetU16(tag,shapeid);
1333 swf_SetRect(tag,&r);
1334 swf_SetShapeHeader(tag,s);
1335 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1336 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1337 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1338 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1339 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1340 swf_ShapeSetEnd(tag);
1342 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1343 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1344 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1345 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1349 tag = swf_InsertTag(tag, ST_PROTECT);
1354 void swfoutput_setprotected() //write PROTECT tag
1359 static void startshape(struct swfoutput*obj)
1367 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1369 swf_ShapeNew(&shape);
1370 linestyleid = swf_ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1371 rgb.r = obj->fillrgb.r;
1372 rgb.g = obj->fillrgb.g;
1373 rgb.b = obj->fillrgb.b;
1374 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1376 shapeid = ++currentswfid;
1377 swf_SetU16(tag,shapeid); // ID
1379 /* TODO: patch back */
1380 bboxrectpos = tag->len;
1385 swf_SetRect(tag,&r);
1387 memset(&bboxrect, 0, sizeof(bboxrect));
1389 swf_SetShapeStyles(tag,shape);
1390 swf_ShapeCountBits(shape,NULL,NULL);
1391 swf_SetShapeBits(tag,shape);
1393 /* TODO: do we really need this? */
1394 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1395 swflastx=swflasty=0;
1400 static void starttext(struct swfoutput*obj)
1405 textid = ++currentswfid;
1407 swflastx=swflasty=0;
1411 /* TODO: move to ../lib/rfxswf */
1412 void changeRect(TAG*tag, int pos, SRECT*newrect)
1414 /* determine length of old rect */
1418 swf_GetRect(tag, &old);
1419 swf_ResetReadBits(tag);
1420 int pos_end = tag->pos;
1422 int len = tag->len - pos_end;
1423 U8*data = (U8*)malloc(len);
1424 memcpy(data, &tag->data[pos_end], len);
1427 swf_SetRect(tag, newrect);
1428 swf_SetBlock(tag, data, len);
1430 tag->pos = tag->readBit = 0;
1433 static void endshape(int clipdepth)
1437 swf_ShapeSetEnd(tag);
1440 // delete the tag again, we didn't do anything
1443 swf_DeleteTag(todel);
1449 changeRect(tag, bboxrectpos, &bboxrect);
1451 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1453 swf_ObjectPlaceClip(tag,shapeid,depth++,NULL,NULL,NULL,clipdepth);
1455 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1461 static void endpage(struct swfoutput*obj)
1468 swfoutput_endclip(obj);
1472 atag = action_Stop(atag);
1473 atag = action_End(atag);
1474 tag = swf_InsertTag(tag,ST_DOACTION);
1475 swf_ActionSet(tag,atag);
1477 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1480 void swfoutput_newpage(struct swfoutput*obj)
1484 for(depth--;depth>=startdepth;depth--) {
1485 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1486 swf_SetU16(tag,depth);
1492 /* Perform cleaning up, complete the swf, and write it out. */
1493 void swfoutput_destroy(struct swfoutput* obj)
1496 fontlist_t *tmp,*iterator = fontlist;
1498 TAG*mtag = swf.firstTag;
1499 if(iterator->swffont) {
1500 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1501 /*if(!storeallcharacters)
1502 swf_FontReduce(iterator->swffont);*/
1503 swf_FontSetDefine2(mtag, iterator->swffont);
1504 swf_FontFree(iterator->swffont);
1508 iterator = iterator->next;
1515 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1520 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1524 tag = swf_InsertTag(tag,ST_END);
1526 if(enablezlib || flashversion>=6) {
1527 if FAILED(swf_WriteSWC(fi,&swf))
1528 msg("<error> WriteSWC() failed.\n");
1530 if FAILED(swf_WriteSWF(fi,&swf))
1531 msg("<error> WriteSWF() failed.\n");
1536 msg("<notice> SWF written\n");
1539 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1541 obj->drawmode = mode;
1542 if(mode == DRAWMODE_FILL)
1544 else if(mode == DRAWMODE_EOFILL)
1546 else if(mode == DRAWMODE_STROKE)
1548 else if(mode == DRAWMODE_CLIP)
1550 else if(mode == DRAWMODE_EOCLIP)
1554 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1556 if(obj->fillrgb.r == r &&
1557 obj->fillrgb.g == g &&
1558 obj->fillrgb.b == b &&
1559 obj->fillrgb.a == a) return;
1569 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1571 if(obj->strokergb.r == r &&
1572 obj->strokergb.g == g &&
1573 obj->strokergb.b == b &&
1574 obj->strokergb.a == a) return;
1578 obj->strokergb.r = r;
1579 obj->strokergb.g = g;
1580 obj->strokergb.b = b;
1581 obj->strokergb.a = a;
1584 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1586 if(linewidth == (u16)(linewidth*20))
1591 linewidth = (u16)(linewidth*20);
1595 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1604 msg("<warning> Too many clip levels.");
1609 int olddrawmode = obj->drawmode;
1610 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1611 swfoutput_drawpath(obj, outline, m);
1612 swf_ShapeSetEnd(tag);
1613 swfoutput_setdrawmode(obj, olddrawmode);
1615 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1616 cliptags[clippos] = tag;
1617 clipshapes[clippos] = shapeid;
1618 clipdepths[clippos] = depth++;
1623 void swfoutput_endclip(swfoutput*obj)
1631 msg("<error> Invalid end of clipping region");
1635 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1638 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1640 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1643 if(!strncmp("http://pdf2swf:", url, 15)) {
1644 char*tmp = strdup(url);
1645 int l = strlen(tmp);
1648 swfoutput_namedlink(obj, tmp+15, points);
1659 actions = action_GetUrl(0, url, "_parent");
1661 actions = action_GetUrl(0, url, "_this");
1662 actions = action_End(actions);
1664 drawlink(obj, actions, 0, points,0);
1666 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1675 actions = action_GotoFrame(0, page);
1676 actions = action_End(actions);
1678 drawlink(obj, actions, 0, points,0);
1681 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1682 of the viewer objects, like subtitles, index elements etc.
1684 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1686 ActionTAG *actions1,*actions2;
1687 char*tmp = strdup(name);
1695 if(!strncmp(tmp, "call:", 5))
1697 char*x = strchr(&tmp[5], ':');
1699 actions1 = action_PushInt(0, 0); //number of parameters (0)
1700 actions1 = action_PushString(actions1, &tmp[5]); //function name
1701 actions1 = action_CallFunction(actions1);
1704 actions1 = action_PushString(0, x+1); //parameter
1705 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1706 actions1 = action_PushString(actions1, &tmp[5]); //function name
1707 actions1 = action_CallFunction(actions1);
1709 actions2 = action_End(0);
1714 actions1 = action_PushString(0, "/:subtitle");
1715 actions1 = action_PushString(actions1, name);
1716 actions1 = action_SetVariable(actions1);
1717 actions1 = action_End(actions1);
1719 actions2 = action_PushString(0, "/:subtitle");
1720 actions2 = action_PushString(actions2, "");
1721 actions2 = action_SetVariable(actions2);
1722 actions2 = action_End(actions2);
1725 drawlink(obj, actions1, actions2, points,mouseover);
1727 swf_ActionFree(actions1);
1728 swf_ActionFree(actions2);
1732 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1738 struct plotxy p1,p2,p3,p4;
1742 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1746 int buttonid = ++currentswfid;
1749 if(points[t].x>xmax) xmax=points[t].x;
1750 if(points[t].y>ymax) ymax=points[t].y;
1751 if(points[t].x<xmin) xmin=points[t].x;
1752 if(points[t].y<ymin) ymin=points[t].y;
1755 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1756 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1758 /* the following code subtracts the upper left edge from all coordinates,
1759 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1760 Necessary for preprocessing with swfcombine. */
1761 posx = xmin; posy = ymin;
1762 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1763 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1764 xmin -= posx; ymin -= posy;
1765 xmax -= posx; ymax -= posy;
1768 myshapeid = ++currentswfid;
1769 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1770 swf_ShapeNew(&shape);
1771 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1772 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1773 swf_SetU16(tag, myshapeid);
1774 r.xmin = (int)(xmin*20);
1775 r.ymin = (int)(ymin*20);
1776 r.xmax = (int)(xmax*20);
1777 r.ymax = (int)(ymax*20);
1778 swf_SetRect(tag,&r);
1779 swf_SetShapeStyles(tag,shape);
1780 swf_ShapeCountBits(shape,NULL,NULL);
1781 swf_SetShapeBits(tag,shape);
1782 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1783 swflastx = swflasty = 0;
1789 swf_ShapeSetEnd(tag);
1792 myshapeid2 = ++currentswfid;
1793 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1794 swf_ShapeNew(&shape);
1795 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1797 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1798 swf_SetU16(tag, myshapeid2);
1799 r.xmin = (int)(xmin*20);
1800 r.ymin = (int)(ymin*20);
1801 r.xmax = (int)(xmax*20);
1802 r.ymax = (int)(ymax*20);
1803 swf_SetRect(tag,&r);
1804 swf_SetShapeStyles(tag,shape);
1805 swf_ShapeCountBits(shape,NULL,NULL);
1806 swf_SetShapeBits(tag,shape);
1807 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1808 swflastx = swflasty = 0;
1814 swf_ShapeSetEnd(tag);
1818 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1819 swf_SetU16(tag,buttonid); //id
1820 swf_ButtonSetFlags(tag, 0); //menu=no
1821 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1822 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1823 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1824 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1826 swf_ActionSet(tag,actions1);
1831 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1832 swf_SetU16(tag,buttonid); //id
1833 swf_ButtonSetFlags(tag, 0); //menu=no
1834 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1835 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1836 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1837 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1838 swf_SetU8(tag,0); // end of button records
1839 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1840 swf_ActionSet(tag,actions1);
1842 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1843 swf_ActionSet(tag,actions2);
1845 swf_ButtonPostProcess(tag, 2);
1848 swf_ButtonPostProcess(tag, 1);
1852 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1854 if(posx!=0 || posy!=0) {
1856 swf_GetMatrix(0,&m);
1857 m.tx = (int)(posx*20);
1858 m.ty = (int)(posy*20);
1859 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1862 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1866 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1867 double x1,double y1,
1868 double x2,double y2,
1869 double x3,double y3,
1870 double x4,double y4)
1876 struct plotxy p1,p2,p3,p4;
1878 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1879 if(x2>xmax) xmax=x2;
1880 if(y2>ymax) ymax=y2;
1881 if(x2<xmin) xmin=x2;
1882 if(y2<ymin) ymin=y2;
1883 if(x3>xmax) xmax=x3;
1884 if(y3>ymax) ymax=y3;
1885 if(x3<xmin) xmin=x3;
1886 if(y3<ymin) ymin=y3;
1887 if(x4>xmax) xmax=x4;
1888 if(y4>ymax) ymax=y4;
1889 if(x4<xmin) xmin=x4;
1890 if(y4<ymin) ymin=y4;
1896 {p1.x = (int)(p1.x*20)/20.0;
1897 p1.y = (int)(p1.y*20)/20.0;
1898 p2.x = (int)(p2.x*20)/20.0;
1899 p2.y = (int)(p2.y*20)/20.0;
1900 p3.x = (int)(p3.x*20)/20.0;
1901 p3.y = (int)(p3.y*20)/20.0;
1902 p4.x = (int)(p4.x*20)/20.0;
1903 p4.y = (int)(p4.y*20)/20.0;}
1906 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1907 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1908 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1909 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1911 m.tx = (int)(p1.x*20);
1912 m.ty = (int)(p1.y*20);
1915 myshapeid = ++currentswfid;
1916 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1917 swf_ShapeNew(&shape);
1918 //lsid = ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1919 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1920 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1921 swf_SetU16(tag, myshapeid);
1922 r.xmin = (int)(xmin*20);
1923 r.ymin = (int)(ymin*20);
1924 r.xmax = (int)(xmax*20);
1925 r.ymax = (int)(ymax*20);
1926 swf_SetRect(tag,&r);
1927 swf_SetShapeStyles(tag,shape);
1928 swf_ShapeCountBits(shape,NULL,NULL);
1929 swf_SetShapeBits(tag,shape);
1930 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1931 swflastx = swflasty = 0;
1938 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1939 ShapeSetLine (tag, shape, (int)(x1*20);
1940 ShapeSetLine (tag, shape, x*20,0);
1941 ShapeSetLine (tag, shape, 0,-y*20);
1942 ShapeSetLine (tag, shape, -x*20,0);*/
1943 swf_ShapeSetEnd(tag);
1946 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1947 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1950 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1951 double x1,double y1,
1952 double x2,double y2,
1953 double x3,double y3,
1954 double x4,double y4)
1962 int bitid = ++currentswfid;
1964 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1965 swf_SetU16(tag, bitid);
1966 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1972 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1976 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1977 double x1,double y1,
1978 double x2,double y2,
1979 double x3,double y3,
1980 double x4,double y4)
1990 int bitid = ++currentswfid;
1992 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1993 swf_SetU16(tag, bitid);
1994 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1995 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1999 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2000 double x1,double y1,
2001 double x2,double y2,
2002 double x3,double y3,
2003 double x4,double y4)
2011 int bitid = ++currentswfid;
2013 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2014 swf_SetU16(tag, bitid);
2015 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2021 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2025 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2026 double x1,double y1,
2027 double x2,double y2,
2028 double x3,double y3,
2029 double x4,double y4, int n)
2040 /* SWF expects scanlines to be 4 byte aligned */
2043 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2045 for(y=0;y<sizey;y++)
2047 for(x=0;x<sizex;x++)
2048 *ptr++ = mem[y*sizex+x];
2049 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2054 int bitid = ++currentswfid;
2056 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2057 swf_SetU16(tag, bitid);
2058 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2066 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2070 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2071 double x1,double y1,
2072 double x2,double y2,
2073 double x3,double y3,
2074 double x4,double y4)
2082 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);