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 float minlinewidth=0.05;
53 static char storefont = 0;
54 static int flag_protected = 0;
56 typedef unsigned char u8;
57 typedef unsigned short int u16;
58 typedef unsigned long int u32;
61 static char* filename = 0;
64 static int currentswfid = 0;
66 static int startdepth = 1;
67 static int linewidth = 0;
70 static int shapeid = -1;
71 static int textid = -1;
73 static int fillstyleid;
74 static int linestyleid;
75 static int swflastx=0;
76 static int swflasty=0;
77 static int lastwasfill = 0;
78 static int shapeisempty = 1;
90 char fillstylechanged = 0;
95 static void startshape(struct swfoutput* obj);
96 static void starttext(struct swfoutput* obj);
97 static void endshape(struct swfoutput* obj,int clip);
98 static void endtext(struct swfoutput* obj);
100 // matrix multiplication. changes p0
101 static void transform (plotxy*p0,struct swfmatrix*m)
104 x = m->m11*p0->x+m->m12*p0->y;
105 y = m->m21*p0->x+m->m22*p0->y;
110 // write a move-to command into the swf
111 static int moveto(TAG*tag, plotxy p0)
113 int rx = (int)(p0.x*20);
114 int ry = (int)(p0.y*20);
115 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
116 swf_ShapeSetMove (tag, shape, rx,ry);
117 fillstylechanged = 0;
124 static int moveto(TAG*tag, float x, float y)
129 return moveto(tag, p);
131 static void addPointToBBox(int px, int py)
137 swf_ExpandRect(&bboxrect, p);
139 swf_ExpandRect3(&bboxrect, p, linewidth*3/2);
143 // write a line-to command into the swf
144 static void lineto(TAG*tag, plotxy p0)
146 int px = (int)(p0.x*20);
147 int py = (int)(p0.y*20);
148 int rx = (px-swflastx);
149 int ry = (py-swflasty);
150 /* we can't skip this for rx=0,ry=0, those
152 swf_ShapeSetLine (tag, shape, rx,ry);
154 addPointToBBox(swflastx,swflasty);
155 addPointToBBox(px,py);
161 static void lineto(TAG*tag, double x, double y)
170 // write a spline-to command into the swf
171 static void splineto(TAG*tag, plotxy control,plotxy end)
173 int lastlastx = swflastx;
174 int lastlasty = swflasty;
176 int cx = ((int)(control.x*20)-swflastx);
177 int cy = ((int)(control.y*20)-swflasty);
180 int ex = ((int)(end.x*20)-swflastx);
181 int ey = ((int)(end.y*20)-swflasty);
185 if(cx || cy || ex || ey) {
186 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
187 addPointToBBox(lastlastx ,lastlasty );
188 addPointToBBox(lastlastx+cx,lastlasty+cy);
189 addPointToBBox(lastlastx+cx+ex,lastlasty+cy+ey);
194 /* write a line, given two points and the transformation
196 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
204 /* write a cubic (!) spline. This involves calling the approximate()
205 function out of spline.cc to convert it to a quadratic spline. */
206 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
209 struct qspline q[128];
223 /* fonts use a different approximation than shapes */
224 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
225 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
227 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
231 moveto(tag,q[t].start);
232 splineto(tag,q[t].control, q[t].end);
242 static void stopFill()
246 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
247 fillstylechanged = 1;
251 static void startFill()
255 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
256 fillstylechanged = 1;
261 /* draw an outline. These are generated by pdf2swf and by t1lib
262 (representing characters). */
263 void drawpath(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int log)
265 if( tag->id != ST_DEFINESHAPE &&
266 tag->id != ST_DEFINESHAPE2 &&
267 tag->id != ST_DEFINESHAPE3)
269 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
273 double lastx=0,lasty=0;
274 double firstx=0,firsty=0;
279 x += (outline->dest.x/(float)0xffff);
280 y += (outline->dest.y/(float)0xffff);
281 if(outline->type == SWF_PATHTYPE_MOVE)
283 //if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
284 if(filloverlap && !init && fill && output->drawmode != DRAWMODE_EOFILL) {
285 /* drawmode=FILL (not EOFILL) means that
286 seperate shapes do not cancel each other out.
287 On SWF side, we need to start a new shape for each
288 closed polygon, because SWF only knows EOFILL.
295 if(((int)(lastx*20) != (int)(firstx*20) ||
296 (int)(lasty*20) != (int)(firsty*20)) &&
305 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
306 line(tag, p0, p1, m);
312 else if(outline->type == SWF_PATHTYPE_LINE)
320 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
323 else if(outline->type == SWF_PATHTYPE_BEZIER)
329 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
332 p1.x=o2->C.x/(float)0xffff+lastx;
333 p1.y=o2->C.y/(float)0xffff+lasty;
334 p2.x=o2->B.x/(float)0xffff+lastx;
335 p2.y=o2->B.y/(float)0xffff+lasty;
338 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
339 spline(tag,p0,p1,p2,p3,m);
342 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
346 outline = outline->link;
348 if(((int)(lastx*20) != (int)(firstx*20) ||
349 (int)(lasty*20) != (int)(firsty*20)) &&
358 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
359 line(tag, p0, p1, m);
363 plotxy getPivot(SWF_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
365 SWF_PATHPOINT next, next2;
366 double xv=0,yv=0, xv2=0, yv2=0;
371 if(outline->type == SWF_PATHTYPE_LINE) {
372 next = outline->dest;
374 next = ((SWF_BEZIERSEGMENT*)outline)->B;
375 if(next.x==0 && next.y==0) {
376 next = ((SWF_BEZIERSEGMENT*)outline)->C;
378 if(next.x==0 && next.y==0) {
379 next = ((SWF_BEZIERSEGMENT*)outline)->dest;
383 if(trytwo && outline->last && outline->last->type != SWF_PATHTYPE_MOVE) {
384 if(outline->type == SWF_PATHTYPE_LINE) {
385 next2 = outline->last->dest;
387 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)(outline->last))->C;
388 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)(outline->last))->B;
389 next2.x = outline->last->dest.x - c.x;
390 next2.y = outline->last->dest.y - c.y;
391 if(next2.x==0 && next2.y==0) {
392 next2.x = outline->last->dest.x - b.x;
393 next2.y = outline->last->dest.y - b.y;
395 if(next2.x==0 && next2.y==0) {
396 next2.x = outline->last->dest.x;
397 next2.y = outline->last->dest.y;
403 if(outline->type == SWF_PATHTYPE_LINE) {
404 next = outline->dest;
406 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)outline)->C;
407 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)outline)->B;
408 next.x = outline->dest.x - c.x;
409 next.y = outline->dest.y - c.y;
410 if(next.x==0 && next.y==0) {
411 next.x = outline->dest.x - b.x;
412 next.y = outline->dest.y - b.y;
414 if(next.x==0 && next.y==0) {
415 next.x = outline->dest.x;
416 next.y = outline->dest.y;
420 if(trytwo && outline->link && outline->link->type != SWF_PATHTYPE_MOVE) {
421 if(outline->type == SWF_PATHTYPE_LINE) {
422 next2 = outline->link->dest;
424 next2 = ((SWF_BEZIERSEGMENT*)(outline->link))->B;
425 if(next2.x==0 && next2.y==0) {
426 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->C;
428 if(next2.x==0 && next2.y==0) {
429 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->dest;
437 xv = next.y/(float)0xffff;
438 yv = -next.x/(float)0xffff;
440 xv = -next.y/(float)0xffff;
441 yv = next.x/(float)0xffff;
444 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
450 xv2 = next2.y/(float)0xffff;
451 yv2 = -next2.x/(float)0xffff;
453 xv2 = -next2.y/(float)0xffff;
454 yv2 = next2.x/(float)0xffff;
457 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
462 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
472 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline)
474 double lastx=x, lasty=y;
475 while (outline && outline->type != SWF_PATHTYPE_MOVE)
477 x += (outline->dest.x/(float)0xffff);
478 y += (outline->dest.y/(float)0xffff);
480 if(outline->type == SWF_PATHTYPE_LINE)
487 line(tag, p0, p1, m);
489 else if(outline->type == SWF_PATHTYPE_BEZIER)
492 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
495 p1.x=o2->C.x/(float)0xffff+lastx;
496 p1.y=o2->C.y/(float)0xffff+lasty;
497 p2.x=o2->B.x/(float)0xffff+lastx;
498 p2.y=o2->B.y/(float)0xffff+lasty;
501 spline(tag,p0,p1,p2,p3,m);
505 outline = outline->link;
509 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)
514 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
517 SWF_OUTLINE *last, *tmp=outline;
518 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
524 while(tmp && tmp->type != SWF_PATHTYPE_MOVE) {
526 lx += (tmp->dest.x/(float)0xffff);
527 ly += (tmp->dest.y/(float)0xffff);
530 s = getPivot(outline, 0, line_width, 0, 0);
531 e = getPivot(last, 0, line_width, 1, 0);
533 if(line_cap == LINE_CAP_BUTT) {
534 /* make the clipping rectangle slighly bigger
535 than the line ending, so that it get's clipped
545 p2.x = x2 - s.y - s.x*ee;
546 p2.y = y2 + s.x - s.y*ee;
547 p3.x = x2 - s.y + s.x*ee;
548 p3.y = y2 + s.x + s.y*ee;
553 m2.x = lx + e.y - e.x*ee;
554 m2.y = ly - e.x - e.y*ee;
555 m3.x = lx + e.y + e.x*ee;
556 m3.y = ly - e.x + e.y*ee;
558 for(nr=0;nr<2;nr++) {
560 struct plotxy q0,q1,q2,q3,q4,q5;
563 if(line_cap == LINE_CAP_BUTT) {
566 q1.x = sizex; q1.y = 0;
567 q2.x = sizex; q2.y = sizey;
568 q3.x = 0; q3.y = sizey;
570 q0.x = sizex; q0.y = sizey;
571 q1.x = 0; q1.y = sizey;
573 q3.x = sizex; q3.y = 0;
587 line(tag, p0, p1, m);
588 line(tag, p1, p2, m);
589 line(tag, p2, p3, m);
590 line(tag, p3, p0, m);
592 if(line_cap == LINE_CAP_BUTT) {
594 endshape(output, depth+2-nr);
606 drawShortPath(output,x,y,m,outline);
608 if(line_cap == LINE_CAP_BUTT) {
614 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)
616 plotxy d1,d2,p1,p2,p3,p4;
618 d1.x = (outline->dest.x/(float)0xffff);
619 d1.y = (outline->dest.y/(float)0xffff);
620 d2 = getPivot(outline, 0, line_width, 0, 0);
622 assert(line_cap != LINE_CAP_ROUND);
623 if(line_cap == LINE_CAP_SQUARE) {
632 p2.x = x + d2.x + d1.x;
633 p2.y = y + d2.y + d1.y;
634 p3.x = x - d2.x + d1.x;
635 p3.y = y - d2.y + d1.y;
645 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)
647 SWF_OUTLINE*tmp=outline;
653 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
655 while(tmp->link && tmp->link->type!=SWF_PATHTYPE_MOVE) {
656 xx += (tmp->dest.x/(float)0xffff);
657 yy += (tmp->dest.y/(float)0xffff);
661 assert(tmp->type == SWF_PATHTYPE_LINE);
662 assert(outline->type == SWF_PATHTYPE_LINE);
666 if(outline->link == tmp) {
667 /* the two straight line segments (which are everything we
668 need to draw) are very likely to overlap. To avoid that
669 they cancel each other out at the end points, start a new
670 shape for the second one */
671 endshape(output,0);startshape(output);
675 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
677 if(outline->link != tmp)
681 tmp->type = SWF_PATHTYPE_MOVE;
682 x += (outline->dest.x/(float)0xffff);
683 y += (outline->dest.y/(float)0xffff);
684 outline = outline->link;
685 drawShortPath(output, x, y, m, outline);
693 static int t1len(SWF_OUTLINE*line)
696 while(line && line->type != SWF_PATHTYPE_MOVE) {
703 static float t1linelen(SWF_OUTLINE*line)
706 x = (line->dest.x/(float)0xffff);
707 y = (line->dest.y/(float)0xffff);
708 return sqrt(x*x+y*y);
711 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)
713 if( tag->id != ST_DEFINESHAPE &&
714 tag->id != ST_DEFINESHAPE2 &&
715 tag->id != ST_DEFINESHAPE3) {
716 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
721 double lastx=0,lasty=0;
724 SWF_OUTLINE*tmp = outline, *last = 0;
729 x += (tmp->dest.x/(float)0xffff);
730 y += (tmp->dest.y/(float)0xffff);
732 if(!tmp || tmp->type == SWF_PATHTYPE_MOVE) {
734 if(last->type == SWF_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
735 lastwasline && line_cap != LINE_CAP_ROUND)
736 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
738 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
752 if(tmp && tmp->type == SWF_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
758 tmp->link->last = tmp; // make sure list is properly linked in both directions
763 static inline int colorcompare(RGBA*a,RGBA*b)
775 static const int CHARDATAMAX = 8192;
778 int fontid; /* TODO: use a SWFFONT instead */
783 } chardata[CHARDATAMAX];
786 static SRECT getcharacterbbox(SWFFONT*font)
790 memset(&r, 0, sizeof(r));
793 if(debug) printf("\n");
794 for(t=0;t<chardatapos;t++)
796 if(chardata[t].fontid != font->id) {
797 msg("<error> Internal error: fontid %d != fontid %d", chardata[t].fontid, font->id);
800 SRECT b = font->layout->bounds[chardata[t].charid];
801 b.xmin *= chardata[t].size;
802 b.ymin *= chardata[t].size;
803 b.xmax *= chardata[t].size;
804 b.ymax *= chardata[t].size;
809 b.xmin += chardata[t].x;
810 b.ymin += chardata[t].y;
811 b.xmax += chardata[t].x;
812 b.ymax += chardata[t].y;
814 /* until we solve the INTERNAL_SCALING problem (see below)
815 make sure the bounding box is big enough */
821 if(debug) printf("(%f,%f,%f,%f) -> (%f,%f,%f,%f) [font %d/%d, char %d]\n",
822 font->layout->bounds[chardata[t].charid].xmin/20.0,
823 font->layout->bounds[chardata[t].charid].ymin/20.0,
824 font->layout->bounds[chardata[t].charid].xmax/20.0,
825 font->layout->bounds[chardata[t].charid].ymax/20.0,
834 swf_ExpandRect2(&r, &b);
836 if(debug) printf("-----> (%f,%f,%f,%f)\n",
844 static void putcharacters(TAG*tag)
849 color.r = chardata[0].color.r^255;
858 int charadvance[128];
861 int glyphbits=1; //TODO: can this be zero?
864 if(tag->id != ST_DEFINETEXT &&
865 tag->id != ST_DEFINETEXT2) {
866 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
870 msg("<warning> putcharacters called with zero characters");
873 for(pass = 0; pass < 2; pass++)
883 advancebits++; // add sign bit
884 swf_SetU8(tag, glyphbits);
885 swf_SetU8(tag, advancebits);
888 for(t=0;t<=chardatapos;t++)
890 if(lastfontid != chardata[t].fontid ||
891 lastx!=chardata[t].x ||
892 lasty!=chardata[t].y ||
893 !colorcompare(&color, &chardata[t].color) ||
895 lastsize != chardata[t].size ||
898 if(charstorepos && pass==0)
901 for(s=0;s<charstorepos;s++)
903 while(charids[s]>=(1<<glyphbits))
905 while(charadvance[s]>=(1<<advancebits))
909 if(charstorepos && pass==1)
911 tag->writeBit = 0; // Q&D
912 swf_SetBits(tag, 0, 1); // GLYPH Record
913 swf_SetBits(tag, charstorepos, 7); // number of glyphs
915 for(s=0;s<charstorepos;s++)
917 swf_SetBits(tag, charids[s], glyphbits);
918 swf_SetBits(tag, charadvance[s], advancebits);
923 if(pass == 1 && t<chardatapos)
929 if(lastx != chardata[t].x ||
930 lasty != chardata[t].y)
932 newx = chardata[t].x;
933 newy = chardata[t].y;
939 if(!colorcompare(&color, &chardata[t].color))
941 color = chardata[t].color;
944 font.id = chardata[t].fontid;
945 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
948 tag->writeBit = 0; // Q&D
949 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
952 lastfontid = chardata[t].fontid;
953 lastx = chardata[t].x;
954 lasty = chardata[t].y;
955 lastsize = chardata[t].size;
962 int nextt = t==chardatapos-1?t:t+1;
963 int rel = chardata[nextt].x-chardata[t].x;
964 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
966 lastx=chardata[nextt].x;
972 charids[charstorepos] = chardata[t].charid;
973 charadvance[charstorepos] = advance;
980 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
981 int x,int y, int size)
983 if(chardatapos == CHARDATAMAX)
985 msg("<warning> Character buffer too small. SWF will be slightly bigger");
989 chardata[chardatapos].fontid = fontid;
990 chardata[chardatapos].charid = charid;
991 chardata[chardatapos].x = x;
992 chardata[chardatapos].y = y;
993 chardata[chardatapos].color = obj->fillrgb;
994 chardata[chardatapos].size = size;
1004 /* Notice: we can only put chars in the range -1639,1638 (-32768/20,32768/20).
1005 So if we set this value to high, the char coordinates will overflow.
1006 If we set it to low, however, the char positions will be inaccurate */
1007 #define FONT_INTERNAL_SIZE 4
1009 /* process a character. */
1010 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
1013 msg("<warning> Font is NULL");
1017 int charid = getCharID(swffont, charnr, character, u);
1020 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
1021 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
1032 float det = ((m->m11*m->m22)-(m->m21*m->m12));
1033 if(fabs(det) < 0.0005) {
1034 /* x direction equals y direction- the text is invisible */
1037 det = 20*FONT_INTERNAL_SIZE / det;
1040 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
1041 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
1043 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
1044 swf_FontUseGlyph(swffont, charid);
1049 SWF_OUTLINE*outline = font->getOutline(character, charnr);
1050 char* charname = character;
1053 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
1054 FIXNULL(character),charnr,FIXNULL(font->getName()));
1073 drawpath(tag, outline, &m2, 0);
1078 static void endtext(swfoutput*obj)
1083 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1084 swf_SetU16(tag, textid);
1087 r = getcharacterbbox(obj->swffont);
1089 swf_SetRect(tag,&r);
1092 swf_GetMatrix(0, &m);
1093 swf_SetMatrix(tag,&m);
1097 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1098 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1103 /* draw a curved polygon. */
1104 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1110 /* Multiple polygons in one shape don't overlap correctly,
1111 so we better start a new shape here if the polygon is filled
1113 if(shapeid>=0 && fill && !ignoredraworder) {
1125 drawpath(output, outline,m, 0);
1128 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1138 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1141 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1145 for(t=0;t<font->numchars;t++) {
1146 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1150 /* if we didn't find the character, maybe
1151 we can find the capitalized version */
1152 for(t=0;t<font->numchars;t++) {
1153 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1160 /* try to use the unicode id */
1161 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1162 return font->ascii2glyph[u];
1166 if(charnr>=0 && charnr<font->numchars) {
1170 if(font->encoding != FONT_ENCODING_UNICODE) {
1171 /* the following only works if the font encoding
1172 is US-ASCII based. It's needed for fonts which return broken unicode
1174 if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1175 return font->ascii2glyph[charnr];
1183 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1184 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1186 fontlist_t*last=0,*iterator;
1188 msg("<error> No fontid");
1192 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1195 /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
1196 with multiple fonts */
1199 iterator = fontlist;
1201 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1202 obj->swffont = iterator->swffont;
1206 iterator = iterator->next;
1210 msg("<error> No filename given for font- internal error?");
1214 swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1);
1215 SWFFONT*swffont = swf_LoadFont(filename);
1218 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1219 swffont = swf_LoadFont(0);
1222 swf_FontSetID(swffont, ++currentswfid);
1224 if(screenloglevel >= LOGLEVEL_DEBUG) {
1225 // print font information
1226 msg("<debug> Font %s (%s)",swffont->name, filename);
1227 msg("<debug> | ID: %d", swffont->id);
1228 msg("<debug> | Version: %d", swffont->version);
1229 msg("<debug> | Name: %s", fontid);
1230 msg("<debug> | Numchars: %d", swffont->numchars);
1231 msg("<debug> | Maxascii: %d", swffont->maxascii);
1232 msg("<debug> | Style: %d", swffont->style);
1233 msg("<debug> | Encoding: %d", swffont->encoding);
1234 for(int iii=0; iii<swffont->numchars;iii++) {
1235 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,
1236 swffont->layout->bounds[iii].xmin/20.0,
1237 swffont->layout->bounds[iii].ymin/20.0,
1238 swffont->layout->bounds[iii].xmax/20.0,
1239 swffont->layout->bounds[iii].ymax/20.0
1242 for(t=0;t<swffont->maxascii;t++) {
1243 if(swffont->ascii2glyph[t] == iii)
1244 msg("<debug> | - maps to %d",t);
1249 /* set the font name to the ID we use here */
1250 if(swffont->name) free(swffont->name);
1251 swffont->name = (U8*)strdup(fontid);
1253 iterator = new fontlist_t;
1254 iterator->swffont = swffont;
1258 last->next = iterator;
1260 fontlist = iterator;
1262 obj->swffont = swffont;
1265 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1267 fontlist_t *iterator = fontlist;
1269 if(!strcmp((char*)iterator->swffont->name,fontid))
1271 iterator = iterator->next;
1276 /* set's the matrix which is to be applied to characters drawn by
1277 swfoutput_drawchar() */
1278 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1279 double m21,double m22)
1281 if(obj->fontm11 == m11 &&
1282 obj->fontm12 == m12 &&
1283 obj->fontm21 == m21 &&
1284 obj->fontm22 == m22)
1294 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1295 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1298 obj->fontmatrix = m;
1301 /* draws a character at x,y. */
1302 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1305 m.m11 = obj->fontm11;
1306 m.m12 = obj->fontm12;
1307 m.m21 = obj->fontm21;
1308 m.m22 = obj->fontm22;
1311 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1314 /* initialize the swf writer */
1315 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1319 memset(obj, 0, sizeof(struct swfoutput));
1320 filename = _filename;
1324 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1329 memset(&swf,0x00,sizeof(SWF));
1331 swf.fileVersion = flashversion;
1332 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1333 swf.movieSize.xmin = 20*x1;
1334 swf.movieSize.ymin = 20*y1;
1335 swf.movieSize.xmax = 20*x2;
1336 swf.movieSize.ymax = 20*y2;
1340 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1342 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1343 swf_SetRGB(tag,&rgb);
1345 if(1)/* add white rectangle */
1350 int shapeid = ++currentswfid;
1355 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1357 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1358 swf_SetU16(tag,shapeid);
1359 swf_SetRect(tag,&r);
1360 swf_SetShapeHeader(tag,s);
1361 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1362 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1363 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1364 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1365 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1366 swf_ShapeSetEnd(tag);
1368 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1369 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1370 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1371 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1375 tag = swf_InsertTag(tag, ST_PROTECT);
1380 void swfoutput_setprotected() //write PROTECT tag
1385 static void startshape(struct swfoutput*obj)
1393 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1395 swf_ShapeNew(&shape);
1396 linestyleid = swf_ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1397 rgb.r = obj->fillrgb.r;
1398 rgb.g = obj->fillrgb.g;
1399 rgb.b = obj->fillrgb.b;
1400 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1402 shapeid = ++currentswfid;
1403 swf_SetU16(tag,shapeid); // ID
1405 bboxrectpos = tag->len;
1410 swf_SetRect(tag,&r);
1412 memset(&bboxrect, 0, sizeof(bboxrect));
1414 swf_SetShapeStyles(tag,shape);
1415 swf_ShapeCountBits(shape,NULL,NULL);
1416 swf_SetShapeBits(tag,shape);
1418 /* TODO: do we really need this? */
1419 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1420 swflastx=swflasty=0;
1425 static void starttext(struct swfoutput*obj)
1430 textid = ++currentswfid;
1432 swflastx=swflasty=0;
1436 /* TODO: move to ../lib/rfxswf */
1437 void changeRect(TAG*tag, int pos, SRECT*newrect)
1439 /* determine length of old rect */
1443 swf_GetRect(tag, &old);
1444 swf_ResetReadBits(tag);
1445 int pos_end = tag->pos;
1447 int len = tag->len - pos_end;
1448 U8*data = (U8*)malloc(len);
1449 memcpy(data, &tag->data[pos_end], len);
1452 swf_SetRect(tag, newrect);
1453 swf_SetBlock(tag, data, len);
1455 tag->pos = tag->readBit = 0;
1458 void cancelshape(swfoutput*obj)
1460 /* delete old shape tag */
1463 swf_DeleteTag(todel);
1468 void fixAreas(swfoutput*obj)
1470 if(!shapeisempty && fill &&
1471 (bboxrect.xmin == bboxrect.xmax ||
1472 bboxrect.ymin == bboxrect.ymax) &&
1473 minlinewidth >= 0.001
1475 msg("<debug> Shape has size 0: width=%.2f height=%.2f",
1476 (bboxrect.xmax-bboxrect.xmin)/20.0,
1477 (bboxrect.ymax-bboxrect.ymin)/20.0
1482 if(r.xmin == r.xmax && r.ymin == r.ymax) {
1483 /* this thing comes down to a single dot- nothing to fix here */
1489 RGBA save_col = obj->strokergb;
1490 int save_width = linewidth;
1492 obj->strokergb = obj->fillrgb;
1493 linewidth = (int)(minlinewidth*20);
1494 if(linewidth==0) linewidth = 1;
1498 moveto(tag, r.xmin/20.0,r.ymin/20.0);
1499 lineto(tag, r.xmax/20.0,r.ymax/20.0);
1501 obj->strokergb = save_col;
1502 linewidth = save_width;
1507 static void endshape(swfoutput*obj, int clipdepth)
1516 (bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax))
1518 // delete the shape again, we didn't do anything
1523 swf_ShapeSetEnd(tag);
1525 changeRect(tag, bboxrectpos, &bboxrect);
1527 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1529 swf_ObjectPlaceClip(tag,shapeid,depth++,NULL,NULL,NULL,clipdepth);
1531 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1537 static void endpage(struct swfoutput*obj)
1544 swfoutput_endclip(obj);
1548 atag = action_Stop(atag);
1549 atag = action_End(atag);
1550 tag = swf_InsertTag(tag,ST_DOACTION);
1551 swf_ActionSet(tag,atag);
1553 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1556 void swfoutput_newpage(struct swfoutput*obj)
1560 for(depth--;depth>=startdepth;depth--) {
1561 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1562 swf_SetU16(tag,depth);
1568 /* Perform cleaning up, complete the swf, and write it out. */
1569 void swfoutput_destroy(struct swfoutput* obj)
1572 fontlist_t *tmp,*iterator = fontlist;
1574 TAG*mtag = swf.firstTag;
1575 if(iterator->swffont) {
1576 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1577 /*if(!storeallcharacters)
1578 swf_FontReduce(iterator->swffont);*/
1579 swf_FontSetDefine2(mtag, iterator->swffont);
1580 swf_FontFree(iterator->swffont);
1584 iterator = iterator->next;
1591 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1596 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1600 tag = swf_InsertTag(tag,ST_END);
1602 if(enablezlib || flashversion>=6) {
1603 if FAILED(swf_WriteSWC(fi,&swf))
1604 msg("<error> WriteSWC() failed.\n");
1606 if FAILED(swf_WriteSWF(fi,&swf))
1607 msg("<error> WriteSWF() failed.\n");
1612 msg("<notice> SWF written\n");
1615 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1617 obj->drawmode = mode;
1618 if(mode == DRAWMODE_FILL)
1620 else if(mode == DRAWMODE_EOFILL)
1622 else if(mode == DRAWMODE_STROKE)
1624 else if(mode == DRAWMODE_CLIP)
1626 else if(mode == DRAWMODE_EOCLIP)
1630 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1632 if(obj->fillrgb.r == r &&
1633 obj->fillrgb.g == g &&
1634 obj->fillrgb.b == b &&
1635 obj->fillrgb.a == a) return;
1645 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1647 if(obj->strokergb.r == r &&
1648 obj->strokergb.g == g &&
1649 obj->strokergb.b == b &&
1650 obj->strokergb.a == a) return;
1654 obj->strokergb.r = r;
1655 obj->strokergb.g = g;
1656 obj->strokergb.b = b;
1657 obj->strokergb.a = a;
1660 void swfoutput_setlinewidth(struct swfoutput*obj, double _linewidth)
1662 if(linewidth == (u16)(_linewidth*20))
1667 linewidth = (u16)(_linewidth*20);
1671 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1680 msg("<warning> Too many clip levels.");
1685 int olddrawmode = obj->drawmode;
1686 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1687 swfoutput_drawpath(obj, outline, m);
1688 swf_ShapeSetEnd(tag);
1689 swfoutput_setdrawmode(obj, olddrawmode);
1691 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1692 cliptags[clippos] = tag;
1693 clipshapes[clippos] = shapeid;
1694 clipdepths[clippos] = depth++;
1699 void swfoutput_endclip(swfoutput*obj)
1707 msg("<error> Invalid end of clipping region");
1711 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1714 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1716 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1719 if(!strncmp("http://pdf2swf:", url, 15)) {
1720 char*tmp = strdup(url);
1721 int l = strlen(tmp);
1724 swfoutput_namedlink(obj, tmp+15, points);
1735 actions = action_GetUrl(0, url, "_parent");
1737 actions = action_GetUrl(0, url, "_this");
1738 actions = action_End(actions);
1740 drawlink(obj, actions, 0, points,0);
1742 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1751 actions = action_GotoFrame(0, page);
1752 actions = action_End(actions);
1754 drawlink(obj, actions, 0, points,0);
1757 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1758 of the viewer objects, like subtitles, index elements etc.
1760 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1762 ActionTAG *actions1,*actions2;
1763 char*tmp = strdup(name);
1771 if(!strncmp(tmp, "call:", 5))
1773 char*x = strchr(&tmp[5], ':');
1775 actions1 = action_PushInt(0, 0); //number of parameters (0)
1776 actions1 = action_PushString(actions1, &tmp[5]); //function name
1777 actions1 = action_CallFunction(actions1);
1780 actions1 = action_PushString(0, x+1); //parameter
1781 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1782 actions1 = action_PushString(actions1, &tmp[5]); //function name
1783 actions1 = action_CallFunction(actions1);
1785 actions2 = action_End(0);
1790 actions1 = action_PushString(0, "/:subtitle");
1791 actions1 = action_PushString(actions1, name);
1792 actions1 = action_SetVariable(actions1);
1793 actions1 = action_End(actions1);
1795 actions2 = action_PushString(0, "/:subtitle");
1796 actions2 = action_PushString(actions2, "");
1797 actions2 = action_SetVariable(actions2);
1798 actions2 = action_End(actions2);
1801 drawlink(obj, actions1, actions2, points,mouseover);
1803 swf_ActionFree(actions1);
1804 swf_ActionFree(actions2);
1808 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1814 struct plotxy p1,p2,p3,p4;
1818 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1822 int buttonid = ++currentswfid;
1825 if(points[t].x>xmax) xmax=points[t].x;
1826 if(points[t].y>ymax) ymax=points[t].y;
1827 if(points[t].x<xmin) xmin=points[t].x;
1828 if(points[t].y<ymin) ymin=points[t].y;
1831 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1832 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1834 /* the following code subtracts the upper left edge from all coordinates,
1835 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1836 Necessary for preprocessing with swfcombine. */
1837 posx = xmin; posy = ymin;
1838 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1839 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1840 xmin -= posx; ymin -= posy;
1841 xmax -= posx; ymax -= posy;
1844 myshapeid = ++currentswfid;
1845 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1846 swf_ShapeNew(&shape);
1847 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1848 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1849 swf_SetU16(tag, myshapeid);
1850 r.xmin = (int)(xmin*20);
1851 r.ymin = (int)(ymin*20);
1852 r.xmax = (int)(xmax*20);
1853 r.ymax = (int)(ymax*20);
1854 swf_SetRect(tag,&r);
1855 swf_SetShapeStyles(tag,shape);
1856 swf_ShapeCountBits(shape,NULL,NULL);
1857 swf_SetShapeBits(tag,shape);
1858 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1859 swflastx = swflasty = 0;
1865 swf_ShapeSetEnd(tag);
1868 myshapeid2 = ++currentswfid;
1869 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1870 swf_ShapeNew(&shape);
1871 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1873 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1874 swf_SetU16(tag, myshapeid2);
1875 r.xmin = (int)(xmin*20);
1876 r.ymin = (int)(ymin*20);
1877 r.xmax = (int)(xmax*20);
1878 r.ymax = (int)(ymax*20);
1879 swf_SetRect(tag,&r);
1880 swf_SetShapeStyles(tag,shape);
1881 swf_ShapeCountBits(shape,NULL,NULL);
1882 swf_SetShapeBits(tag,shape);
1883 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1884 swflastx = swflasty = 0;
1890 swf_ShapeSetEnd(tag);
1894 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1895 swf_SetU16(tag,buttonid); //id
1896 swf_ButtonSetFlags(tag, 0); //menu=no
1897 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1898 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1899 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1900 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1902 swf_ActionSet(tag,actions1);
1907 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1908 swf_SetU16(tag,buttonid); //id
1909 swf_ButtonSetFlags(tag, 0); //menu=no
1910 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1911 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1912 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1913 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1914 swf_SetU8(tag,0); // end of button records
1915 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1916 swf_ActionSet(tag,actions1);
1918 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1919 swf_ActionSet(tag,actions2);
1921 swf_ButtonPostProcess(tag, 2);
1924 swf_ButtonPostProcess(tag, 1);
1928 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1930 if(posx!=0 || posy!=0) {
1932 swf_GetMatrix(0,&m);
1933 m.tx = (int)(posx*20);
1934 m.ty = (int)(posy*20);
1935 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1938 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1942 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1943 double x1,double y1,
1944 double x2,double y2,
1945 double x3,double y3,
1946 double x4,double y4)
1952 struct plotxy p1,p2,p3,p4;
1954 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1955 if(x2>xmax) xmax=x2;
1956 if(y2>ymax) ymax=y2;
1957 if(x2<xmin) xmin=x2;
1958 if(y2<ymin) ymin=y2;
1959 if(x3>xmax) xmax=x3;
1960 if(y3>ymax) ymax=y3;
1961 if(x3<xmin) xmin=x3;
1962 if(y3<ymin) ymin=y3;
1963 if(x4>xmax) xmax=x4;
1964 if(y4>ymax) ymax=y4;
1965 if(x4<xmin) xmin=x4;
1966 if(y4<ymin) ymin=y4;
1972 {p1.x = (int)(p1.x*20)/20.0;
1973 p1.y = (int)(p1.y*20)/20.0;
1974 p2.x = (int)(p2.x*20)/20.0;
1975 p2.y = (int)(p2.y*20)/20.0;
1976 p3.x = (int)(p3.x*20)/20.0;
1977 p3.y = (int)(p3.y*20)/20.0;
1978 p4.x = (int)(p4.x*20)/20.0;
1979 p4.y = (int)(p4.y*20)/20.0;}
1982 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1983 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1984 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1985 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1987 m.tx = (int)(p1.x*20);
1988 m.ty = (int)(p1.y*20);
1991 myshapeid = ++currentswfid;
1992 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1993 swf_ShapeNew(&shape);
1994 //lsid = ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1995 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1996 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1997 swf_SetU16(tag, myshapeid);
1998 r.xmin = (int)(xmin*20);
1999 r.ymin = (int)(ymin*20);
2000 r.xmax = (int)(xmax*20);
2001 r.ymax = (int)(ymax*20);
2002 swf_SetRect(tag,&r);
2003 swf_SetShapeStyles(tag,shape);
2004 swf_ShapeCountBits(shape,NULL,NULL);
2005 swf_SetShapeBits(tag,shape);
2006 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
2007 swflastx = swflasty = 0;
2014 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
2015 ShapeSetLine (tag, shape, (int)(x1*20);
2016 ShapeSetLine (tag, shape, x*20,0);
2017 ShapeSetLine (tag, shape, 0,-y*20);
2018 ShapeSetLine (tag, shape, -x*20,0);*/
2019 swf_ShapeSetEnd(tag);
2022 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
2023 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
2026 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
2027 double x1,double y1,
2028 double x2,double y2,
2029 double x3,double y3,
2030 double x4,double y4)
2038 int bitid = ++currentswfid;
2040 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2041 swf_SetU16(tag, bitid);
2042 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
2048 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2052 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2053 double x1,double y1,
2054 double x2,double y2,
2055 double x3,double y3,
2056 double x4,double y4)
2066 int bitid = ++currentswfid;
2068 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2069 swf_SetU16(tag, bitid);
2070 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2071 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2075 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2076 double x1,double y1,
2077 double x2,double y2,
2078 double x3,double y3,
2079 double x4,double y4)
2087 int bitid = ++currentswfid;
2089 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2090 swf_SetU16(tag, bitid);
2091 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2097 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2101 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2102 double x1,double y1,
2103 double x2,double y2,
2104 double x3,double y3,
2105 double x4,double y4, int n)
2116 /* SWF expects scanlines to be 4 byte aligned */
2119 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2121 for(y=0;y<sizey;y++)
2123 for(x=0;x<sizex;x++)
2124 *ptr++ = mem[y*sizex+x];
2125 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2130 int bitid = ++currentswfid;
2132 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2133 swf_SetU16(tag, bitid);
2134 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2142 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2146 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2147 double x1,double y1,
2148 double x2,double y2,
2149 double x3,double y3,
2150 double x4,double y4)
2158 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2161 void swfoutput_setparameter(char*name, char*value)
2163 if(!strcmp(name, "drawonlyshapes")) {
2164 drawonlyshapes = atoi(value);
2165 } else if(!strcmp(name, "ignoredraworder")) {
2166 ignoredraworder = atoi(value);
2167 } else if(!strcmp(name, "filloverlap")) {
2168 filloverlap = atoi(value);
2169 } else if(!strcmp(name, "linksopennewwindow")) {
2170 opennewwindow = atoi(value);
2171 } else if(!strcmp(name, "opennewwindow")) {
2172 opennewwindow = atoi(value);
2173 } else if(!strcmp(name, "storeallcharacters")) {
2174 storeallcharacters = atoi(value);
2175 } else if(!strcmp(name, "enablezlib")) {
2176 enablezlib = atoi(value);
2177 } else if(!strcmp(name, "insertstop")) {
2178 insertstoptag = atoi(value);
2179 } else if(!strcmp(name, "flashversion")) {
2180 flashversion = atoi(value);
2181 } else if(!strcmp(name, "minlinewidth")) {
2182 minlinewidth = atof(value);
2183 } else if(!strcmp(name, "jpegquality")) {
2184 int val = atoi(value);
2186 if(val>100) val=100;
2188 } else if(!strcmp(name, "splinequality")) {
2189 int v = atoi(value);
2190 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2193 } else if(!strcmp(name, "fontquality")) {
2194 int v = atoi(value);
2195 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2197 fontsplinemaxerror = v;
2199 fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);