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;
52 static char storefont = 0;
53 static int flag_protected = 0;
55 typedef unsigned char u8;
56 typedef unsigned short int u16;
57 typedef unsigned long int u32;
60 static char* filename = 0;
63 static int currentswfid = 0;
65 static int startdepth = 1;
66 static int linewidth = 0;
69 static int shapeid = -1;
70 static int textid = -1;
72 static int fillstyleid;
73 static int linestyleid;
74 static int swflastx=0;
75 static int swflasty=0;
76 static int lastwasfill = 0;
77 static int shapeisempty = 1;
89 char fillstylechanged = 0;
94 static void startshape(struct swfoutput* obj);
95 static void starttext(struct swfoutput* obj);
96 static void endshape(int clip);
97 static void endtext(struct swfoutput* obj);
99 // matrix multiplication. changes p0
100 static void transform (plotxy*p0,struct swfmatrix*m)
103 x = m->m11*p0->x+m->m12*p0->y;
104 y = m->m21*p0->x+m->m22*p0->y;
109 // write a move-to command into the swf
110 static int moveto(TAG*tag, plotxy p0)
112 int rx = (int)(p0.x*20);
113 int ry = (int)(p0.y*20);
114 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
115 swf_ShapeSetMove (tag, shape, rx,ry);
116 fillstylechanged = 0;
123 static int moveto(TAG*tag, float x, float y)
128 return moveto(tag, p);
130 static void addPointToBBox(int px, int py)
136 swf_ExpandRect(&bboxrect, p);
138 swf_ExpandRect3(&bboxrect, p, linewidth*3/2);
142 // write a line-to command into the swf
143 static void lineto(TAG*tag, plotxy p0)
145 int px = (int)(p0.x*20);
146 int py = (int)(p0.y*20);
147 int rx = (px-swflastx);
148 int ry = (py-swflasty);
149 /* we can't skip this for rx=0,ry=0, those
151 swf_ShapeSetLine (tag, shape, rx,ry);
153 addPointToBBox(swflastx,swflasty);
154 addPointToBBox(px,py);
160 static void lineto(TAG*tag, float x, float y)
169 // write a spline-to command into the swf
170 static void splineto(TAG*tag, plotxy control,plotxy end)
172 int lastlastx = swflastx;
173 int lastlasty = swflasty;
175 int cx = ((int)(control.x*20)-swflastx);
176 int cy = ((int)(control.y*20)-swflasty);
179 int ex = ((int)(end.x*20)-swflastx);
180 int ey = ((int)(end.y*20)-swflasty);
184 if(cx || cy || ex || ey) {
185 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
186 addPointToBBox(lastlastx ,lastlasty );
187 addPointToBBox(lastlastx+cx,lastlasty+cy);
188 addPointToBBox(lastlastx+cx+ex,lastlasty+cy+ey);
193 /* write a line, given two points and the transformation
195 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
203 /* write a cubic (!) spline. This involves calling the approximate()
204 function out of spline.cc to convert it to a quadratic spline. */
205 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
208 struct qspline q[128];
222 /* fonts use a different approximation than shapes */
223 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
224 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
226 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
230 moveto(tag,q[t].start);
231 splineto(tag,q[t].control, q[t].end);
241 static void stopFill()
245 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
246 fillstylechanged = 1;
250 static void startFill()
254 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
255 fillstylechanged = 1;
260 /* draw an outline. These are generated by pdf2swf and by t1lib
261 (representing characters). */
262 void drawpath(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int log)
264 if( tag->id != ST_DEFINESHAPE &&
265 tag->id != ST_DEFINESHAPE2 &&
266 tag->id != ST_DEFINESHAPE3)
268 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
272 double lastx=0,lasty=0;
273 double firstx=0,firsty=0;
278 x += (outline->dest.x/(float)0xffff);
279 y += (outline->dest.y/(float)0xffff);
280 if(outline->type == SWF_PATHTYPE_MOVE)
282 //if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
283 if(filloverlap && !init && fill && output->drawmode != DRAWMODE_EOFILL) {
284 /* drawmode=FILL (not EOFILL) means that
285 seperate shapes do not cancel each other out.
286 On SWF side, we need to start a new shape for each
287 closed polygon, because SWF only knows EOFILL.
294 if(((int)(lastx*20) != (int)(firstx*20) ||
295 (int)(lasty*20) != (int)(firsty*20)) &&
304 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
305 line(tag, p0, p1, m);
311 else if(outline->type == SWF_PATHTYPE_LINE)
319 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
322 else if(outline->type == SWF_PATHTYPE_BEZIER)
328 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
331 p1.x=o2->C.x/(float)0xffff+lastx;
332 p1.y=o2->C.y/(float)0xffff+lasty;
333 p2.x=o2->B.x/(float)0xffff+lastx;
334 p2.y=o2->B.y/(float)0xffff+lasty;
337 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
338 spline(tag,p0,p1,p2,p3,m);
341 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
345 outline = outline->link;
347 if(((int)(lastx*20) != (int)(firstx*20) ||
348 (int)(lasty*20) != (int)(firsty*20)) &&
357 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
358 line(tag, p0, p1, m);
362 plotxy getPivot(SWF_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
364 SWF_PATHPOINT next, next2;
365 double xv=0,yv=0, xv2=0, yv2=0;
370 if(outline->type == SWF_PATHTYPE_LINE) {
371 next = outline->dest;
373 next = ((SWF_BEZIERSEGMENT*)outline)->B;
374 if(next.x==0 && next.y==0) {
375 next = ((SWF_BEZIERSEGMENT*)outline)->C;
377 if(next.x==0 && next.y==0) {
378 next = ((SWF_BEZIERSEGMENT*)outline)->dest;
382 if(trytwo && outline->last && outline->last->type != SWF_PATHTYPE_MOVE) {
383 if(outline->type == SWF_PATHTYPE_LINE) {
384 next2 = outline->last->dest;
386 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)(outline->last))->C;
387 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)(outline->last))->B;
388 next2.x = outline->last->dest.x - c.x;
389 next2.y = outline->last->dest.y - c.y;
390 if(next2.x==0 && next2.y==0) {
391 next2.x = outline->last->dest.x - b.x;
392 next2.y = outline->last->dest.y - b.y;
394 if(next2.x==0 && next2.y==0) {
395 next2.x = outline->last->dest.x;
396 next2.y = outline->last->dest.y;
402 if(outline->type == SWF_PATHTYPE_LINE) {
403 next = outline->dest;
405 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)outline)->C;
406 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)outline)->B;
407 next.x = outline->dest.x - c.x;
408 next.y = outline->dest.y - c.y;
409 if(next.x==0 && next.y==0) {
410 next.x = outline->dest.x - b.x;
411 next.y = outline->dest.y - b.y;
413 if(next.x==0 && next.y==0) {
414 next.x = outline->dest.x;
415 next.y = outline->dest.y;
419 if(trytwo && outline->link && outline->link->type != SWF_PATHTYPE_MOVE) {
420 if(outline->type == SWF_PATHTYPE_LINE) {
421 next2 = outline->link->dest;
423 next2 = ((SWF_BEZIERSEGMENT*)(outline->link))->B;
424 if(next2.x==0 && next2.y==0) {
425 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->C;
427 if(next2.x==0 && next2.y==0) {
428 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->dest;
436 xv = next.y/(float)0xffff;
437 yv = -next.x/(float)0xffff;
439 xv = -next.y/(float)0xffff;
440 yv = next.x/(float)0xffff;
443 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
449 xv2 = next2.y/(float)0xffff;
450 yv2 = -next2.x/(float)0xffff;
452 xv2 = -next2.y/(float)0xffff;
453 yv2 = next2.x/(float)0xffff;
456 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
461 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
471 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline)
473 double lastx=x, lasty=y;
474 while (outline && outline->type != SWF_PATHTYPE_MOVE)
476 x += (outline->dest.x/(float)0xffff);
477 y += (outline->dest.y/(float)0xffff);
479 if(outline->type == SWF_PATHTYPE_LINE)
486 line(tag, p0, p1, m);
488 else if(outline->type == SWF_PATHTYPE_BEZIER)
491 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
494 p1.x=o2->C.x/(float)0xffff+lastx;
495 p1.y=o2->C.y/(float)0xffff+lasty;
496 p2.x=o2->B.x/(float)0xffff+lastx;
497 p2.y=o2->B.y/(float)0xffff+lasty;
500 spline(tag,p0,p1,p2,p3,m);
504 outline = outline->link;
508 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)
513 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
516 SWF_OUTLINE *last, *tmp=outline;
517 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
523 while(tmp && tmp->type != SWF_PATHTYPE_MOVE) {
525 lx += (tmp->dest.x/(float)0xffff);
526 ly += (tmp->dest.y/(float)0xffff);
529 s = getPivot(outline, 0, line_width, 0, 0);
530 e = getPivot(last, 0, line_width, 1, 0);
532 if(line_cap == LINE_CAP_BUTT) {
533 /* make the clipping rectangle slighly bigger
534 than the line ending, so that it get's clipped
544 p2.x = x2 - s.y - s.x*ee;
545 p2.y = y2 + s.x - s.y*ee;
546 p3.x = x2 - s.y + s.x*ee;
547 p3.y = y2 + s.x + s.y*ee;
552 m2.x = lx + e.y - e.x*ee;
553 m2.y = ly - e.x - e.y*ee;
554 m3.x = lx + e.y + e.x*ee;
555 m3.y = ly - e.x + e.y*ee;
557 for(nr=0;nr<2;nr++) {
559 struct plotxy q0,q1,q2,q3,q4,q5;
562 if(line_cap == LINE_CAP_BUTT) {
565 q1.x = sizex; q1.y = 0;
566 q2.x = sizex; q2.y = sizey;
567 q3.x = 0; q3.y = sizey;
569 q0.x = sizex; q0.y = sizey;
570 q1.x = 0; q1.y = sizey;
572 q3.x = sizex; q3.y = 0;
586 line(tag, p0, p1, m);
587 line(tag, p1, p2, m);
588 line(tag, p2, p3, m);
589 line(tag, p3, p0, m);
591 if(line_cap == LINE_CAP_BUTT) {
593 endshape(depth+2-nr);
605 drawShortPath(output,x,y,m,outline);
607 if(line_cap == LINE_CAP_BUTT) {
613 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)
615 plotxy d1,d2,p1,p2,p3,p4;
617 d1.x = (outline->dest.x/(float)0xffff);
618 d1.y = (outline->dest.y/(float)0xffff);
619 d2 = getPivot(outline, 0, line_width, 0, 0);
621 assert(line_cap != LINE_CAP_ROUND);
622 if(line_cap == LINE_CAP_SQUARE) {
631 p2.x = x + d2.x + d1.x;
632 p2.y = y + d2.y + d1.y;
633 p3.x = x - d2.x + d1.x;
634 p3.y = y - d2.y + d1.y;
644 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)
646 SWF_OUTLINE*tmp=outline;
652 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
654 while(tmp->link && tmp->link->type!=SWF_PATHTYPE_MOVE) {
655 xx += (tmp->dest.x/(float)0xffff);
656 yy += (tmp->dest.y/(float)0xffff);
660 assert(tmp->type == SWF_PATHTYPE_LINE);
661 assert(outline->type == SWF_PATHTYPE_LINE);
665 if(outline->link == tmp) {
666 /* the two straight line segments (which are everything we
667 need to draw) are very likely to overlap. To avoid that
668 they cancel each other out at the end points, start a new
669 shape for the second one */
670 endshape(0);startshape(output);
674 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
676 if(outline->link != tmp)
680 tmp->type = SWF_PATHTYPE_MOVE;
681 x += (outline->dest.x/(float)0xffff);
682 y += (outline->dest.y/(float)0xffff);
683 outline = outline->link;
684 drawShortPath(output, x, y, m, outline);
692 static int t1len(SWF_OUTLINE*line)
695 while(line && line->type != SWF_PATHTYPE_MOVE) {
702 static float t1linelen(SWF_OUTLINE*line)
705 x = (line->dest.x/(float)0xffff);
706 y = (line->dest.y/(float)0xffff);
707 return sqrt(x*x+y*y);
710 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)
712 if( tag->id != ST_DEFINESHAPE &&
713 tag->id != ST_DEFINESHAPE2 &&
714 tag->id != ST_DEFINESHAPE3) {
715 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
720 double lastx=0,lasty=0;
723 SWF_OUTLINE*tmp = outline, *last = 0;
728 x += (tmp->dest.x/(float)0xffff);
729 y += (tmp->dest.y/(float)0xffff);
731 if(!tmp || tmp->type == SWF_PATHTYPE_MOVE) {
733 if(last->type == SWF_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
734 lastwasline && line_cap != LINE_CAP_ROUND)
735 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
737 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
751 if(tmp && tmp->type == SWF_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
757 tmp->link->last = tmp; // make sure list is properly linked in both directions
762 static inline int colorcompare(RGBA*a,RGBA*b)
774 static const int CHARDATAMAX = 8192;
782 } chardata[CHARDATAMAX];
785 static SRECT getcharacterbbox(SWFFONT*font)
789 memset(&r, 0, sizeof(r));
792 if(debug) printf("\n");
793 for(t=0;t<chardatapos;t++)
795 if(chardata[t].fontid != font->id) {
796 msg("<error> Internal error: fontid %d != fontid %d", chardata[t].fontid, font->id);
799 SRECT b = font->layout->bounds[chardata[t].charid];
800 b.xmin *= chardata[t].size;
801 b.ymin *= chardata[t].size;
802 b.xmax *= chardata[t].size;
803 b.ymax *= chardata[t].size;
808 b.xmin += chardata[t].x;
809 b.ymin += chardata[t].y;
810 b.xmax += chardata[t].x;
811 b.ymax += chardata[t].y;
813 /* until we solve the INTERNAL_SCALING problem (see below)
814 make sure the bounding box is big enough */
820 if(debug) printf("(%f,%f,%f,%f) -> (%f,%f,%f,%f) [font %d/%d, char %d]\n",
821 font->layout->bounds[chardata[t].charid].xmin/20.0,
822 font->layout->bounds[chardata[t].charid].ymin/20.0,
823 font->layout->bounds[chardata[t].charid].xmax/20.0,
824 font->layout->bounds[chardata[t].charid].ymax/20.0,
833 swf_ExpandRect2(&r, &b);
835 if(debug) printf("-----> (%f,%f,%f,%f)\n",
843 static void putcharacters(TAG*tag)
848 color.r = chardata[0].color.r^255;
857 int charadvance[128];
860 int glyphbits=1; //TODO: can this be zero?
863 if(tag->id != ST_DEFINETEXT &&
864 tag->id != ST_DEFINETEXT2) {
865 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
869 msg("<warning> putcharacters called with zero characters");
872 for(pass = 0; pass < 2; pass++)
882 advancebits++; // add sign bit
883 swf_SetU8(tag, glyphbits);
884 swf_SetU8(tag, advancebits);
887 for(t=0;t<=chardatapos;t++)
889 if(lastfontid != chardata[t].fontid ||
890 lastx!=chardata[t].x ||
891 lasty!=chardata[t].y ||
892 !colorcompare(&color, &chardata[t].color) ||
894 lastsize != chardata[t].size ||
897 if(charstorepos && pass==0)
900 for(s=0;s<charstorepos;s++)
902 while(charids[s]>=(1<<glyphbits))
904 while(charadvance[s]>=(1<<advancebits))
908 if(charstorepos && pass==1)
910 tag->writeBit = 0; // Q&D
911 swf_SetBits(tag, 0, 1); // GLYPH Record
912 swf_SetBits(tag, charstorepos, 7); // number of glyphs
914 for(s=0;s<charstorepos;s++)
916 swf_SetBits(tag, charids[s], glyphbits);
917 swf_SetBits(tag, charadvance[s], advancebits);
922 if(pass == 1 && t<chardatapos)
928 if(lastx != chardata[t].x ||
929 lasty != chardata[t].y)
931 newx = chardata[t].x;
932 newy = chardata[t].y;
938 if(!colorcompare(&color, &chardata[t].color))
940 color = chardata[t].color;
943 font.id = chardata[t].fontid;
944 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
947 tag->writeBit = 0; // Q&D
948 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
951 lastfontid = chardata[t].fontid;
952 lastx = chardata[t].x;
953 lasty = chardata[t].y;
954 lastsize = chardata[t].size;
961 int nextt = t==chardatapos-1?t:t+1;
962 int rel = chardata[nextt].x-chardata[t].x;
963 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
965 lastx=chardata[nextt].x;
971 charids[charstorepos] = chardata[t].charid;
972 charadvance[charstorepos] = advance;
979 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
980 int x,int y, int size)
982 if(chardatapos == CHARDATAMAX)
984 msg("<warning> Character buffer too small. SWF will be slightly bigger");
988 chardata[chardatapos].fontid = fontid;
989 chardata[chardatapos].charid = charid;
990 chardata[chardatapos].x = x;
991 chardata[chardatapos].y = y;
992 chardata[chardatapos].color = obj->fillrgb;
993 chardata[chardatapos].size = size;
1003 /* todo: why don't higher values (64, 1024) work here? */
1004 #define FONT_INTERNAL_SIZE 1
1006 /* process a character. */
1007 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
1010 msg("<warning> Font is NULL");
1014 int charid = getCharID(swffont, charnr, character, u);
1017 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
1018 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
1029 float det = ((m->m11*m->m22)-(m->m21*m->m12));
1030 if(fabs(det) < 0.0005) {
1031 /* x direction equals y direction- the text is invisible */
1034 det = 20*FONT_INTERNAL_SIZE / det;
1037 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
1038 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
1040 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
1041 swf_FontUseGlyph(swffont, charid);
1046 SWF_OUTLINE*outline = font->getOutline(character, charnr);
1047 char* charname = character;
1050 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
1051 FIXNULL(character),charnr,FIXNULL(font->getName()));
1070 drawpath(tag, outline, &m2, 0);
1075 static void endtext(swfoutput*obj)
1080 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1081 swf_SetU16(tag, textid);
1084 r = getcharacterbbox(obj->swffont);
1086 swf_SetRect(tag,&r);
1089 swf_GetMatrix(0, &m);
1090 swf_SetMatrix(tag,&m);
1094 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1095 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1100 /* draw a curved polygon. */
1101 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1107 /* Multiple polygons in one shape don't overlap correctly,
1108 so we better start a new shape here if the polygon is filled
1110 if(shapeid>=0 && fill && !ignoredraworder) {
1122 drawpath(output, outline,m, 0);
1125 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1135 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1138 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1142 for(t=0;t<font->numchars;t++) {
1143 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1147 /* if we didn't find the character, maybe
1148 we can find the capitalized version */
1149 for(t=0;t<font->numchars;t++) {
1150 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1157 /* try to use the unicode id */
1158 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1159 return font->ascii2glyph[u];
1163 if(charnr>=0 && charnr<font->numchars) {
1167 if(font->encoding != FONT_ENCODING_UNICODE) {
1168 /* the following only works if the font encoding
1169 is US-ASCII based. It's needed for fonts which return broken unicode
1171 if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1172 return font->ascii2glyph[charnr];
1180 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1181 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1183 fontlist_t*last=0,*iterator;
1185 msg("<error> No fontid");
1189 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1192 /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
1193 with multiple fonts */
1196 iterator = fontlist;
1198 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1199 obj->swffont = iterator->swffont;
1203 iterator = iterator->next;
1207 msg("<error> No filename given for font- internal error?");
1211 swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1);
1212 SWFFONT*swffont = swf_LoadFont(filename);
1215 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1216 swffont = swf_LoadFont(0);
1219 swf_FontSetID(swffont, ++currentswfid);
1221 if(screenloglevel >= LOGLEVEL_DEBUG) {
1222 // print font information
1223 msg("<debug> Font %s (%s)",swffont->name, filename);
1224 msg("<debug> | ID: %d", swffont->id);
1225 msg("<debug> | Version: %d", swffont->version);
1226 msg("<debug> | Name: %s", fontid);
1227 msg("<debug> | Numchars: %d", swffont->numchars);
1228 msg("<debug> | Maxascii: %d", swffont->maxascii);
1229 msg("<debug> | Style: %d", swffont->style);
1230 msg("<debug> | Encoding: %d", swffont->encoding);
1231 for(int iii=0; iii<swffont->numchars;iii++) {
1232 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,
1233 swffont->layout->bounds[iii].xmin/20.0,
1234 swffont->layout->bounds[iii].ymin/20.0,
1235 swffont->layout->bounds[iii].xmax/20.0,
1236 swffont->layout->bounds[iii].ymax/20.0
1239 for(t=0;t<swffont->maxascii;t++) {
1240 if(swffont->ascii2glyph[t] == iii)
1241 msg("<debug> | - maps to %d",t);
1246 /* set the font name to the ID we use here */
1247 if(swffont->name) free(swffont->name);
1248 swffont->name = (U8*)strdup(fontid);
1250 iterator = new fontlist_t;
1251 iterator->swffont = swffont;
1255 last->next = iterator;
1257 fontlist = iterator;
1259 obj->swffont = swffont;
1262 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1264 fontlist_t *iterator = fontlist;
1266 if(!strcmp((char*)iterator->swffont->name,fontid))
1268 iterator = iterator->next;
1273 /* set's the matrix which is to be applied to characters drawn by
1274 swfoutput_drawchar() */
1275 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1276 double m21,double m22)
1278 if(obj->fontm11 == m11 &&
1279 obj->fontm12 == m12 &&
1280 obj->fontm21 == m21 &&
1281 obj->fontm22 == m22)
1291 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1292 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1295 obj->fontmatrix = m;
1298 /* draws a character at x,y. */
1299 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1302 m.m11 = obj->fontm11;
1303 m.m12 = obj->fontm12;
1304 m.m21 = obj->fontm21;
1305 m.m22 = obj->fontm22;
1308 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1311 /* initialize the swf writer */
1312 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1316 memset(obj, 0, sizeof(struct swfoutput));
1317 filename = _filename;
1321 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1326 memset(&swf,0x00,sizeof(SWF));
1328 swf.fileVersion = flashversion;
1329 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1330 swf.movieSize.xmin = 20*x1;
1331 swf.movieSize.ymin = 20*y1;
1332 swf.movieSize.xmax = 20*x2;
1333 swf.movieSize.ymax = 20*y2;
1337 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1339 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1340 swf_SetRGB(tag,&rgb);
1342 if(1)/* add white rectangle */
1347 int shapeid = ++currentswfid;
1352 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1354 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1355 swf_SetU16(tag,shapeid);
1356 swf_SetRect(tag,&r);
1357 swf_SetShapeHeader(tag,s);
1358 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1359 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1360 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1361 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1362 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1363 swf_ShapeSetEnd(tag);
1365 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1366 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1367 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1368 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1372 tag = swf_InsertTag(tag, ST_PROTECT);
1377 void swfoutput_setprotected() //write PROTECT tag
1382 static void startshape(struct swfoutput*obj)
1390 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1392 swf_ShapeNew(&shape);
1393 linestyleid = swf_ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1394 rgb.r = obj->fillrgb.r;
1395 rgb.g = obj->fillrgb.g;
1396 rgb.b = obj->fillrgb.b;
1397 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1399 shapeid = ++currentswfid;
1400 swf_SetU16(tag,shapeid); // ID
1402 /* TODO: patch back */
1403 bboxrectpos = tag->len;
1408 swf_SetRect(tag,&r);
1410 memset(&bboxrect, 0, sizeof(bboxrect));
1412 swf_SetShapeStyles(tag,shape);
1413 swf_ShapeCountBits(shape,NULL,NULL);
1414 swf_SetShapeBits(tag,shape);
1416 /* TODO: do we really need this? */
1417 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1418 swflastx=swflasty=0;
1423 static void starttext(struct swfoutput*obj)
1428 textid = ++currentswfid;
1430 swflastx=swflasty=0;
1434 /* TODO: move to ../lib/rfxswf */
1435 void changeRect(TAG*tag, int pos, SRECT*newrect)
1437 /* determine length of old rect */
1441 swf_GetRect(tag, &old);
1442 swf_ResetReadBits(tag);
1443 int pos_end = tag->pos;
1445 int len = tag->len - pos_end;
1446 U8*data = (U8*)malloc(len);
1447 memcpy(data, &tag->data[pos_end], len);
1450 swf_SetRect(tag, newrect);
1451 swf_SetBlock(tag, data, len);
1453 tag->pos = tag->readBit = 0;
1458 if(!shapeisempty && fill &&
1459 (bboxrect.xmin == bboxrect.xmax ||
1460 bboxrect.ymin == bboxrect.ymax)) {
1461 msg("<debug> Shape has size 0");
1463 if(bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax) {
1464 /* this thing comes down to a single dot- nothing to fix here */
1469 if(bboxrect.xmin == bboxrect.xmax) {
1474 /* warning: doing this inside endshape() is dangerous */
1475 moveto(tag, bboxrect.xmin/20.0, bboxrect.ymin/20.0);
1476 lineto(tag, bboxrect.xmax/20.0 + x, bboxrect.ymin/20.0);
1477 lineto(tag, bboxrect.xmax/20.0 + x, bboxrect.ymax/20.0 + y);
1478 lineto(tag, bboxrect.xmin/20.0, bboxrect.ymax/20.0 + y);
1479 lineto(tag, bboxrect.xmin/20.0, bboxrect.ymin/20.0);
1484 static void endshape(int clipdepth)
1493 (bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax))
1495 // delete the tag again, we didn't do anything
1498 swf_DeleteTag(todel);
1504 swf_ShapeSetEnd(tag);
1506 changeRect(tag, bboxrectpos, &bboxrect);
1508 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1510 swf_ObjectPlaceClip(tag,shapeid,depth++,NULL,NULL,NULL,clipdepth);
1512 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1518 static void endpage(struct swfoutput*obj)
1525 swfoutput_endclip(obj);
1529 atag = action_Stop(atag);
1530 atag = action_End(atag);
1531 tag = swf_InsertTag(tag,ST_DOACTION);
1532 swf_ActionSet(tag,atag);
1534 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1537 void swfoutput_newpage(struct swfoutput*obj)
1541 for(depth--;depth>=startdepth;depth--) {
1542 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1543 swf_SetU16(tag,depth);
1549 /* Perform cleaning up, complete the swf, and write it out. */
1550 void swfoutput_destroy(struct swfoutput* obj)
1553 fontlist_t *tmp,*iterator = fontlist;
1555 TAG*mtag = swf.firstTag;
1556 if(iterator->swffont) {
1557 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1558 /*if(!storeallcharacters)
1559 swf_FontReduce(iterator->swffont);*/
1560 swf_FontSetDefine2(mtag, iterator->swffont);
1561 swf_FontFree(iterator->swffont);
1565 iterator = iterator->next;
1572 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1577 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1581 tag = swf_InsertTag(tag,ST_END);
1583 if(enablezlib || flashversion>=6) {
1584 if FAILED(swf_WriteSWC(fi,&swf))
1585 msg("<error> WriteSWC() failed.\n");
1587 if FAILED(swf_WriteSWF(fi,&swf))
1588 msg("<error> WriteSWF() failed.\n");
1593 msg("<notice> SWF written\n");
1596 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1598 obj->drawmode = mode;
1599 if(mode == DRAWMODE_FILL)
1601 else if(mode == DRAWMODE_EOFILL)
1603 else if(mode == DRAWMODE_STROKE)
1605 else if(mode == DRAWMODE_CLIP)
1607 else if(mode == DRAWMODE_EOCLIP)
1611 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1613 if(obj->fillrgb.r == r &&
1614 obj->fillrgb.g == g &&
1615 obj->fillrgb.b == b &&
1616 obj->fillrgb.a == a) return;
1626 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1628 if(obj->strokergb.r == r &&
1629 obj->strokergb.g == g &&
1630 obj->strokergb.b == b &&
1631 obj->strokergb.a == a) return;
1635 obj->strokergb.r = r;
1636 obj->strokergb.g = g;
1637 obj->strokergb.b = b;
1638 obj->strokergb.a = a;
1641 void swfoutput_setlinewidth(struct swfoutput*obj, double _linewidth)
1643 if(linewidth == (u16)(_linewidth*20))
1648 linewidth = (u16)(_linewidth*20);
1652 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1661 msg("<warning> Too many clip levels.");
1666 int olddrawmode = obj->drawmode;
1667 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1668 swfoutput_drawpath(obj, outline, m);
1669 swf_ShapeSetEnd(tag);
1670 swfoutput_setdrawmode(obj, olddrawmode);
1672 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1673 cliptags[clippos] = tag;
1674 clipshapes[clippos] = shapeid;
1675 clipdepths[clippos] = depth++;
1680 void swfoutput_endclip(swfoutput*obj)
1688 msg("<error> Invalid end of clipping region");
1692 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1695 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1697 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1700 if(!strncmp("http://pdf2swf:", url, 15)) {
1701 char*tmp = strdup(url);
1702 int l = strlen(tmp);
1705 swfoutput_namedlink(obj, tmp+15, points);
1716 actions = action_GetUrl(0, url, "_parent");
1718 actions = action_GetUrl(0, url, "_this");
1719 actions = action_End(actions);
1721 drawlink(obj, actions, 0, points,0);
1723 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1732 actions = action_GotoFrame(0, page);
1733 actions = action_End(actions);
1735 drawlink(obj, actions, 0, points,0);
1738 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1739 of the viewer objects, like subtitles, index elements etc.
1741 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1743 ActionTAG *actions1,*actions2;
1744 char*tmp = strdup(name);
1752 if(!strncmp(tmp, "call:", 5))
1754 char*x = strchr(&tmp[5], ':');
1756 actions1 = action_PushInt(0, 0); //number of parameters (0)
1757 actions1 = action_PushString(actions1, &tmp[5]); //function name
1758 actions1 = action_CallFunction(actions1);
1761 actions1 = action_PushString(0, x+1); //parameter
1762 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1763 actions1 = action_PushString(actions1, &tmp[5]); //function name
1764 actions1 = action_CallFunction(actions1);
1766 actions2 = action_End(0);
1771 actions1 = action_PushString(0, "/:subtitle");
1772 actions1 = action_PushString(actions1, name);
1773 actions1 = action_SetVariable(actions1);
1774 actions1 = action_End(actions1);
1776 actions2 = action_PushString(0, "/:subtitle");
1777 actions2 = action_PushString(actions2, "");
1778 actions2 = action_SetVariable(actions2);
1779 actions2 = action_End(actions2);
1782 drawlink(obj, actions1, actions2, points,mouseover);
1784 swf_ActionFree(actions1);
1785 swf_ActionFree(actions2);
1789 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1795 struct plotxy p1,p2,p3,p4;
1799 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1803 int buttonid = ++currentswfid;
1806 if(points[t].x>xmax) xmax=points[t].x;
1807 if(points[t].y>ymax) ymax=points[t].y;
1808 if(points[t].x<xmin) xmin=points[t].x;
1809 if(points[t].y<ymin) ymin=points[t].y;
1812 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1813 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1815 /* the following code subtracts the upper left edge from all coordinates,
1816 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1817 Necessary for preprocessing with swfcombine. */
1818 posx = xmin; posy = ymin;
1819 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1820 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1821 xmin -= posx; ymin -= posy;
1822 xmax -= posx; ymax -= posy;
1825 myshapeid = ++currentswfid;
1826 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1827 swf_ShapeNew(&shape);
1828 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1829 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1830 swf_SetU16(tag, myshapeid);
1831 r.xmin = (int)(xmin*20);
1832 r.ymin = (int)(ymin*20);
1833 r.xmax = (int)(xmax*20);
1834 r.ymax = (int)(ymax*20);
1835 swf_SetRect(tag,&r);
1836 swf_SetShapeStyles(tag,shape);
1837 swf_ShapeCountBits(shape,NULL,NULL);
1838 swf_SetShapeBits(tag,shape);
1839 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1840 swflastx = swflasty = 0;
1846 swf_ShapeSetEnd(tag);
1849 myshapeid2 = ++currentswfid;
1850 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1851 swf_ShapeNew(&shape);
1852 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1854 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1855 swf_SetU16(tag, myshapeid2);
1856 r.xmin = (int)(xmin*20);
1857 r.ymin = (int)(ymin*20);
1858 r.xmax = (int)(xmax*20);
1859 r.ymax = (int)(ymax*20);
1860 swf_SetRect(tag,&r);
1861 swf_SetShapeStyles(tag,shape);
1862 swf_ShapeCountBits(shape,NULL,NULL);
1863 swf_SetShapeBits(tag,shape);
1864 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1865 swflastx = swflasty = 0;
1871 swf_ShapeSetEnd(tag);
1875 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1876 swf_SetU16(tag,buttonid); //id
1877 swf_ButtonSetFlags(tag, 0); //menu=no
1878 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1879 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1880 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1881 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1883 swf_ActionSet(tag,actions1);
1888 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1889 swf_SetU16(tag,buttonid); //id
1890 swf_ButtonSetFlags(tag, 0); //menu=no
1891 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1892 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1893 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1894 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1895 swf_SetU8(tag,0); // end of button records
1896 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1897 swf_ActionSet(tag,actions1);
1899 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1900 swf_ActionSet(tag,actions2);
1902 swf_ButtonPostProcess(tag, 2);
1905 swf_ButtonPostProcess(tag, 1);
1909 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1911 if(posx!=0 || posy!=0) {
1913 swf_GetMatrix(0,&m);
1914 m.tx = (int)(posx*20);
1915 m.ty = (int)(posy*20);
1916 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1919 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1923 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1924 double x1,double y1,
1925 double x2,double y2,
1926 double x3,double y3,
1927 double x4,double y4)
1933 struct plotxy p1,p2,p3,p4;
1935 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1936 if(x2>xmax) xmax=x2;
1937 if(y2>ymax) ymax=y2;
1938 if(x2<xmin) xmin=x2;
1939 if(y2<ymin) ymin=y2;
1940 if(x3>xmax) xmax=x3;
1941 if(y3>ymax) ymax=y3;
1942 if(x3<xmin) xmin=x3;
1943 if(y3<ymin) ymin=y3;
1944 if(x4>xmax) xmax=x4;
1945 if(y4>ymax) ymax=y4;
1946 if(x4<xmin) xmin=x4;
1947 if(y4<ymin) ymin=y4;
1953 {p1.x = (int)(p1.x*20)/20.0;
1954 p1.y = (int)(p1.y*20)/20.0;
1955 p2.x = (int)(p2.x*20)/20.0;
1956 p2.y = (int)(p2.y*20)/20.0;
1957 p3.x = (int)(p3.x*20)/20.0;
1958 p3.y = (int)(p3.y*20)/20.0;
1959 p4.x = (int)(p4.x*20)/20.0;
1960 p4.y = (int)(p4.y*20)/20.0;}
1963 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1964 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1965 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1966 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1968 m.tx = (int)(p1.x*20);
1969 m.ty = (int)(p1.y*20);
1972 myshapeid = ++currentswfid;
1973 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1974 swf_ShapeNew(&shape);
1975 //lsid = ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1976 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1977 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1978 swf_SetU16(tag, myshapeid);
1979 r.xmin = (int)(xmin*20);
1980 r.ymin = (int)(ymin*20);
1981 r.xmax = (int)(xmax*20);
1982 r.ymax = (int)(ymax*20);
1983 swf_SetRect(tag,&r);
1984 swf_SetShapeStyles(tag,shape);
1985 swf_ShapeCountBits(shape,NULL,NULL);
1986 swf_SetShapeBits(tag,shape);
1987 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1988 swflastx = swflasty = 0;
1995 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1996 ShapeSetLine (tag, shape, (int)(x1*20);
1997 ShapeSetLine (tag, shape, x*20,0);
1998 ShapeSetLine (tag, shape, 0,-y*20);
1999 ShapeSetLine (tag, shape, -x*20,0);*/
2000 swf_ShapeSetEnd(tag);
2003 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
2004 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
2007 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
2008 double x1,double y1,
2009 double x2,double y2,
2010 double x3,double y3,
2011 double x4,double y4)
2019 int bitid = ++currentswfid;
2021 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2022 swf_SetU16(tag, bitid);
2023 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
2029 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2033 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2034 double x1,double y1,
2035 double x2,double y2,
2036 double x3,double y3,
2037 double x4,double y4)
2047 int bitid = ++currentswfid;
2049 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2050 swf_SetU16(tag, bitid);
2051 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2052 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2056 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2057 double x1,double y1,
2058 double x2,double y2,
2059 double x3,double y3,
2060 double x4,double y4)
2068 int bitid = ++currentswfid;
2070 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2071 swf_SetU16(tag, bitid);
2072 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2078 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2082 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2083 double x1,double y1,
2084 double x2,double y2,
2085 double x3,double y3,
2086 double x4,double y4, int n)
2097 /* SWF expects scanlines to be 4 byte aligned */
2100 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2102 for(y=0;y<sizey;y++)
2104 for(x=0;x<sizex;x++)
2105 *ptr++ = mem[y*sizex+x];
2106 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2111 int bitid = ++currentswfid;
2113 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2114 swf_SetU16(tag, bitid);
2115 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2123 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2127 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2128 double x1,double y1,
2129 double x2,double y2,
2130 double x3,double y3,
2131 double x4,double y4)
2139 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2142 void swfoutput_setparameter(char*name, char*value)
2144 if(!strcmp(name, "drawonlyshapes")) {
2145 drawonlyshapes = atoi(value);
2146 } else if(!strcmp(name, "ignoredraworder")) {
2147 ignoredraworder = atoi(value);
2148 } else if(!strcmp(name, "filloverlap")) {
2149 filloverlap = atoi(value);
2150 } else if(!strcmp(name, "linksopennewwindow")) {
2151 opennewwindow = atoi(value);
2152 } else if(!strcmp(name, "opennewwindow")) {
2153 opennewwindow = atoi(value);
2154 } else if(!strcmp(name, "storeallcharacters")) {
2155 storeallcharacters = atoi(value);
2156 } else if(!strcmp(name, "enablezlib")) {
2157 enablezlib = atoi(value);
2158 } else if(!strcmp(name, "insertstop")) {
2159 insertstoptag = atoi(value);
2160 } else if(!strcmp(name, "flashversion")) {
2161 flashversion = atoi(value);
2162 } else if(!strcmp(name, "jpegquality")) {
2163 int val = atoi(value);
2165 if(val>100) val=100;
2167 } else if(!strcmp(name, "splinequality")) {
2168 int v = atoi(value);
2169 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2172 } else if(!strcmp(name, "fontquality")) {
2173 int v = atoi(value);
2174 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2176 fontsplinemaxerror = v;
2178 fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);