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.1;
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(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, float x, float 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(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(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 /* todo: why don't higher values (64, 1024) work here? */
1005 #define FONT_INTERNAL_SIZE 1
1007 /* process a character. */
1008 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
1011 msg("<warning> Font is NULL");
1015 int charid = getCharID(swffont, charnr, character, u);
1018 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
1019 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
1030 float det = ((m->m11*m->m22)-(m->m21*m->m12));
1031 if(fabs(det) < 0.0005) {
1032 /* x direction equals y direction- the text is invisible */
1035 det = 20*FONT_INTERNAL_SIZE / det;
1038 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
1039 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
1041 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
1042 swf_FontUseGlyph(swffont, charid);
1047 SWF_OUTLINE*outline = font->getOutline(character, charnr);
1048 char* charname = character;
1051 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
1052 FIXNULL(character),charnr,FIXNULL(font->getName()));
1071 drawpath(tag, outline, &m2, 0);
1076 static void endtext(swfoutput*obj)
1081 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1082 swf_SetU16(tag, textid);
1085 r = getcharacterbbox(obj->swffont);
1087 swf_SetRect(tag,&r);
1090 swf_GetMatrix(0, &m);
1091 swf_SetMatrix(tag,&m);
1095 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1096 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1101 /* draw a curved polygon. */
1102 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1108 /* Multiple polygons in one shape don't overlap correctly,
1109 so we better start a new shape here if the polygon is filled
1111 if(shapeid>=0 && fill && !ignoredraworder) {
1123 drawpath(output, outline,m, 0);
1126 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1136 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1139 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1143 for(t=0;t<font->numchars;t++) {
1144 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1148 /* if we didn't find the character, maybe
1149 we can find the capitalized version */
1150 for(t=0;t<font->numchars;t++) {
1151 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1158 /* try to use the unicode id */
1159 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1160 return font->ascii2glyph[u];
1164 if(charnr>=0 && charnr<font->numchars) {
1168 if(font->encoding != FONT_ENCODING_UNICODE) {
1169 /* the following only works if the font encoding
1170 is US-ASCII based. It's needed for fonts which return broken unicode
1172 if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1173 return font->ascii2glyph[charnr];
1181 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1182 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1184 fontlist_t*last=0,*iterator;
1186 msg("<error> No fontid");
1190 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1193 /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
1194 with multiple fonts */
1197 iterator = fontlist;
1199 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1200 obj->swffont = iterator->swffont;
1204 iterator = iterator->next;
1208 msg("<error> No filename given for font- internal error?");
1212 swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1);
1213 SWFFONT*swffont = swf_LoadFont(filename);
1216 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1217 swffont = swf_LoadFont(0);
1220 swf_FontSetID(swffont, ++currentswfid);
1222 if(screenloglevel >= LOGLEVEL_DEBUG) {
1223 // print font information
1224 msg("<debug> Font %s (%s)",swffont->name, filename);
1225 msg("<debug> | ID: %d", swffont->id);
1226 msg("<debug> | Version: %d", swffont->version);
1227 msg("<debug> | Name: %s", fontid);
1228 msg("<debug> | Numchars: %d", swffont->numchars);
1229 msg("<debug> | Maxascii: %d", swffont->maxascii);
1230 msg("<debug> | Style: %d", swffont->style);
1231 msg("<debug> | Encoding: %d", swffont->encoding);
1232 for(int iii=0; iii<swffont->numchars;iii++) {
1233 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,
1234 swffont->layout->bounds[iii].xmin/20.0,
1235 swffont->layout->bounds[iii].ymin/20.0,
1236 swffont->layout->bounds[iii].xmax/20.0,
1237 swffont->layout->bounds[iii].ymax/20.0
1240 for(t=0;t<swffont->maxascii;t++) {
1241 if(swffont->ascii2glyph[t] == iii)
1242 msg("<debug> | - maps to %d",t);
1247 /* set the font name to the ID we use here */
1248 if(swffont->name) free(swffont->name);
1249 swffont->name = (U8*)strdup(fontid);
1251 iterator = new fontlist_t;
1252 iterator->swffont = swffont;
1256 last->next = iterator;
1258 fontlist = iterator;
1260 obj->swffont = swffont;
1263 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1265 fontlist_t *iterator = fontlist;
1267 if(!strcmp((char*)iterator->swffont->name,fontid))
1269 iterator = iterator->next;
1274 /* set's the matrix which is to be applied to characters drawn by
1275 swfoutput_drawchar() */
1276 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1277 double m21,double m22)
1279 if(obj->fontm11 == m11 &&
1280 obj->fontm12 == m12 &&
1281 obj->fontm21 == m21 &&
1282 obj->fontm22 == m22)
1292 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1293 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1296 obj->fontmatrix = m;
1299 /* draws a character at x,y. */
1300 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1303 m.m11 = obj->fontm11;
1304 m.m12 = obj->fontm12;
1305 m.m21 = obj->fontm21;
1306 m.m22 = obj->fontm22;
1309 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1312 /* initialize the swf writer */
1313 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1317 memset(obj, 0, sizeof(struct swfoutput));
1318 filename = _filename;
1322 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1327 memset(&swf,0x00,sizeof(SWF));
1329 swf.fileVersion = flashversion;
1330 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1331 swf.movieSize.xmin = 20*x1;
1332 swf.movieSize.ymin = 20*y1;
1333 swf.movieSize.xmax = 20*x2;
1334 swf.movieSize.ymax = 20*y2;
1338 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1340 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1341 swf_SetRGB(tag,&rgb);
1343 if(1)/* add white rectangle */
1348 int shapeid = ++currentswfid;
1353 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1355 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1356 swf_SetU16(tag,shapeid);
1357 swf_SetRect(tag,&r);
1358 swf_SetShapeHeader(tag,s);
1359 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1360 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1361 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1362 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1363 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1364 swf_ShapeSetEnd(tag);
1366 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1367 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1368 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1369 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1373 tag = swf_InsertTag(tag, ST_PROTECT);
1378 void swfoutput_setprotected() //write PROTECT tag
1383 static void startshape(struct swfoutput*obj)
1391 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1393 swf_ShapeNew(&shape);
1394 linestyleid = swf_ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1395 rgb.r = obj->fillrgb.r;
1396 rgb.g = obj->fillrgb.g;
1397 rgb.b = obj->fillrgb.b;
1398 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1400 shapeid = ++currentswfid;
1401 swf_SetU16(tag,shapeid); // ID
1403 /* TODO: patch back */
1404 bboxrectpos = tag->len;
1409 swf_SetRect(tag,&r);
1411 memset(&bboxrect, 0, sizeof(bboxrect));
1413 swf_SetShapeStyles(tag,shape);
1414 swf_ShapeCountBits(shape,NULL,NULL);
1415 swf_SetShapeBits(tag,shape);
1417 /* TODO: do we really need this? */
1418 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1419 swflastx=swflasty=0;
1424 static void starttext(struct swfoutput*obj)
1429 textid = ++currentswfid;
1431 swflastx=swflasty=0;
1435 /* TODO: move to ../lib/rfxswf */
1436 void changeRect(TAG*tag, int pos, SRECT*newrect)
1438 /* determine length of old rect */
1442 swf_GetRect(tag, &old);
1443 swf_ResetReadBits(tag);
1444 int pos_end = tag->pos;
1446 int len = tag->len - pos_end;
1447 U8*data = (U8*)malloc(len);
1448 memcpy(data, &tag->data[pos_end], len);
1451 swf_SetRect(tag, newrect);
1452 swf_SetBlock(tag, data, len);
1454 tag->pos = tag->readBit = 0;
1459 if(!shapeisempty && fill &&
1460 (bboxrect.xmin == bboxrect.xmax ||
1461 bboxrect.ymin == bboxrect.ymax) &&
1462 minlinewidth >= 0.001
1464 msg("<debug> Shape has size 0");
1466 if(bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax) {
1467 /* this thing comes down to a single dot- nothing to fix here */
1472 if(bboxrect.xmin == bboxrect.xmax) {
1477 /* warning: doing this inside endshape() is dangerous */
1478 moveto(tag, bboxrect.xmin/20.0 , bboxrect.ymin/20.0);
1479 lineto(tag, bboxrect.xmax/20.0 + x, bboxrect.ymin/20.0);
1480 lineto(tag, bboxrect.xmax/20.0 + x, bboxrect.ymax/20.0 + y);
1481 lineto(tag, bboxrect.xmin/20.0 , bboxrect.ymax/20.0 + y);
1482 lineto(tag, bboxrect.xmin/20.0 , bboxrect.ymin/20.0);
1487 static void endshape(int clipdepth)
1496 (bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax))
1498 // delete the tag again, we didn't do anything
1501 swf_DeleteTag(todel);
1507 swf_ShapeSetEnd(tag);
1509 changeRect(tag, bboxrectpos, &bboxrect);
1511 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1513 swf_ObjectPlaceClip(tag,shapeid,depth++,NULL,NULL,NULL,clipdepth);
1515 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1521 static void endpage(struct swfoutput*obj)
1528 swfoutput_endclip(obj);
1532 atag = action_Stop(atag);
1533 atag = action_End(atag);
1534 tag = swf_InsertTag(tag,ST_DOACTION);
1535 swf_ActionSet(tag,atag);
1537 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1540 void swfoutput_newpage(struct swfoutput*obj)
1544 for(depth--;depth>=startdepth;depth--) {
1545 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1546 swf_SetU16(tag,depth);
1552 /* Perform cleaning up, complete the swf, and write it out. */
1553 void swfoutput_destroy(struct swfoutput* obj)
1556 fontlist_t *tmp,*iterator = fontlist;
1558 TAG*mtag = swf.firstTag;
1559 if(iterator->swffont) {
1560 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1561 /*if(!storeallcharacters)
1562 swf_FontReduce(iterator->swffont);*/
1563 swf_FontSetDefine2(mtag, iterator->swffont);
1564 swf_FontFree(iterator->swffont);
1568 iterator = iterator->next;
1575 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1580 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1584 tag = swf_InsertTag(tag,ST_END);
1586 if(enablezlib || flashversion>=6) {
1587 if FAILED(swf_WriteSWC(fi,&swf))
1588 msg("<error> WriteSWC() failed.\n");
1590 if FAILED(swf_WriteSWF(fi,&swf))
1591 msg("<error> WriteSWF() failed.\n");
1596 msg("<notice> SWF written\n");
1599 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1601 obj->drawmode = mode;
1602 if(mode == DRAWMODE_FILL)
1604 else if(mode == DRAWMODE_EOFILL)
1606 else if(mode == DRAWMODE_STROKE)
1608 else if(mode == DRAWMODE_CLIP)
1610 else if(mode == DRAWMODE_EOCLIP)
1614 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1616 if(obj->fillrgb.r == r &&
1617 obj->fillrgb.g == g &&
1618 obj->fillrgb.b == b &&
1619 obj->fillrgb.a == a) return;
1629 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1631 if(obj->strokergb.r == r &&
1632 obj->strokergb.g == g &&
1633 obj->strokergb.b == b &&
1634 obj->strokergb.a == a) return;
1638 obj->strokergb.r = r;
1639 obj->strokergb.g = g;
1640 obj->strokergb.b = b;
1641 obj->strokergb.a = a;
1644 void swfoutput_setlinewidth(struct swfoutput*obj, double _linewidth)
1646 if(linewidth == (u16)(_linewidth*20))
1651 linewidth = (u16)(_linewidth*20);
1655 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1664 msg("<warning> Too many clip levels.");
1669 int olddrawmode = obj->drawmode;
1670 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1671 swfoutput_drawpath(obj, outline, m);
1672 swf_ShapeSetEnd(tag);
1673 swfoutput_setdrawmode(obj, olddrawmode);
1675 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1676 cliptags[clippos] = tag;
1677 clipshapes[clippos] = shapeid;
1678 clipdepths[clippos] = depth++;
1683 void swfoutput_endclip(swfoutput*obj)
1691 msg("<error> Invalid end of clipping region");
1695 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1698 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1700 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1703 if(!strncmp("http://pdf2swf:", url, 15)) {
1704 char*tmp = strdup(url);
1705 int l = strlen(tmp);
1708 swfoutput_namedlink(obj, tmp+15, points);
1719 actions = action_GetUrl(0, url, "_parent");
1721 actions = action_GetUrl(0, url, "_this");
1722 actions = action_End(actions);
1724 drawlink(obj, actions, 0, points,0);
1726 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1735 actions = action_GotoFrame(0, page);
1736 actions = action_End(actions);
1738 drawlink(obj, actions, 0, points,0);
1741 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1742 of the viewer objects, like subtitles, index elements etc.
1744 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1746 ActionTAG *actions1,*actions2;
1747 char*tmp = strdup(name);
1755 if(!strncmp(tmp, "call:", 5))
1757 char*x = strchr(&tmp[5], ':');
1759 actions1 = action_PushInt(0, 0); //number of parameters (0)
1760 actions1 = action_PushString(actions1, &tmp[5]); //function name
1761 actions1 = action_CallFunction(actions1);
1764 actions1 = action_PushString(0, x+1); //parameter
1765 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1766 actions1 = action_PushString(actions1, &tmp[5]); //function name
1767 actions1 = action_CallFunction(actions1);
1769 actions2 = action_End(0);
1774 actions1 = action_PushString(0, "/:subtitle");
1775 actions1 = action_PushString(actions1, name);
1776 actions1 = action_SetVariable(actions1);
1777 actions1 = action_End(actions1);
1779 actions2 = action_PushString(0, "/:subtitle");
1780 actions2 = action_PushString(actions2, "");
1781 actions2 = action_SetVariable(actions2);
1782 actions2 = action_End(actions2);
1785 drawlink(obj, actions1, actions2, points,mouseover);
1787 swf_ActionFree(actions1);
1788 swf_ActionFree(actions2);
1792 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1798 struct plotxy p1,p2,p3,p4;
1802 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1806 int buttonid = ++currentswfid;
1809 if(points[t].x>xmax) xmax=points[t].x;
1810 if(points[t].y>ymax) ymax=points[t].y;
1811 if(points[t].x<xmin) xmin=points[t].x;
1812 if(points[t].y<ymin) ymin=points[t].y;
1815 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1816 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1818 /* the following code subtracts the upper left edge from all coordinates,
1819 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1820 Necessary for preprocessing with swfcombine. */
1821 posx = xmin; posy = ymin;
1822 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1823 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1824 xmin -= posx; ymin -= posy;
1825 xmax -= posx; ymax -= posy;
1828 myshapeid = ++currentswfid;
1829 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1830 swf_ShapeNew(&shape);
1831 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1832 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1833 swf_SetU16(tag, myshapeid);
1834 r.xmin = (int)(xmin*20);
1835 r.ymin = (int)(ymin*20);
1836 r.xmax = (int)(xmax*20);
1837 r.ymax = (int)(ymax*20);
1838 swf_SetRect(tag,&r);
1839 swf_SetShapeStyles(tag,shape);
1840 swf_ShapeCountBits(shape,NULL,NULL);
1841 swf_SetShapeBits(tag,shape);
1842 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1843 swflastx = swflasty = 0;
1849 swf_ShapeSetEnd(tag);
1852 myshapeid2 = ++currentswfid;
1853 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1854 swf_ShapeNew(&shape);
1855 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1857 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1858 swf_SetU16(tag, myshapeid2);
1859 r.xmin = (int)(xmin*20);
1860 r.ymin = (int)(ymin*20);
1861 r.xmax = (int)(xmax*20);
1862 r.ymax = (int)(ymax*20);
1863 swf_SetRect(tag,&r);
1864 swf_SetShapeStyles(tag,shape);
1865 swf_ShapeCountBits(shape,NULL,NULL);
1866 swf_SetShapeBits(tag,shape);
1867 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1868 swflastx = swflasty = 0;
1874 swf_ShapeSetEnd(tag);
1878 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1879 swf_SetU16(tag,buttonid); //id
1880 swf_ButtonSetFlags(tag, 0); //menu=no
1881 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1882 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1883 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1884 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1886 swf_ActionSet(tag,actions1);
1891 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1892 swf_SetU16(tag,buttonid); //id
1893 swf_ButtonSetFlags(tag, 0); //menu=no
1894 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1895 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1896 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1897 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1898 swf_SetU8(tag,0); // end of button records
1899 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1900 swf_ActionSet(tag,actions1);
1902 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1903 swf_ActionSet(tag,actions2);
1905 swf_ButtonPostProcess(tag, 2);
1908 swf_ButtonPostProcess(tag, 1);
1912 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1914 if(posx!=0 || posy!=0) {
1916 swf_GetMatrix(0,&m);
1917 m.tx = (int)(posx*20);
1918 m.ty = (int)(posy*20);
1919 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1922 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1926 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1927 double x1,double y1,
1928 double x2,double y2,
1929 double x3,double y3,
1930 double x4,double y4)
1936 struct plotxy p1,p2,p3,p4;
1938 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1939 if(x2>xmax) xmax=x2;
1940 if(y2>ymax) ymax=y2;
1941 if(x2<xmin) xmin=x2;
1942 if(y2<ymin) ymin=y2;
1943 if(x3>xmax) xmax=x3;
1944 if(y3>ymax) ymax=y3;
1945 if(x3<xmin) xmin=x3;
1946 if(y3<ymin) ymin=y3;
1947 if(x4>xmax) xmax=x4;
1948 if(y4>ymax) ymax=y4;
1949 if(x4<xmin) xmin=x4;
1950 if(y4<ymin) ymin=y4;
1956 {p1.x = (int)(p1.x*20)/20.0;
1957 p1.y = (int)(p1.y*20)/20.0;
1958 p2.x = (int)(p2.x*20)/20.0;
1959 p2.y = (int)(p2.y*20)/20.0;
1960 p3.x = (int)(p3.x*20)/20.0;
1961 p3.y = (int)(p3.y*20)/20.0;
1962 p4.x = (int)(p4.x*20)/20.0;
1963 p4.y = (int)(p4.y*20)/20.0;}
1966 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1967 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1968 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1969 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1971 m.tx = (int)(p1.x*20);
1972 m.ty = (int)(p1.y*20);
1975 myshapeid = ++currentswfid;
1976 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1977 swf_ShapeNew(&shape);
1978 //lsid = ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1979 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1980 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1981 swf_SetU16(tag, myshapeid);
1982 r.xmin = (int)(xmin*20);
1983 r.ymin = (int)(ymin*20);
1984 r.xmax = (int)(xmax*20);
1985 r.ymax = (int)(ymax*20);
1986 swf_SetRect(tag,&r);
1987 swf_SetShapeStyles(tag,shape);
1988 swf_ShapeCountBits(shape,NULL,NULL);
1989 swf_SetShapeBits(tag,shape);
1990 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1991 swflastx = swflasty = 0;
1998 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1999 ShapeSetLine (tag, shape, (int)(x1*20);
2000 ShapeSetLine (tag, shape, x*20,0);
2001 ShapeSetLine (tag, shape, 0,-y*20);
2002 ShapeSetLine (tag, shape, -x*20,0);*/
2003 swf_ShapeSetEnd(tag);
2006 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
2007 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
2010 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
2011 double x1,double y1,
2012 double x2,double y2,
2013 double x3,double y3,
2014 double x4,double y4)
2022 int bitid = ++currentswfid;
2024 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2025 swf_SetU16(tag, bitid);
2026 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
2032 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2036 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2037 double x1,double y1,
2038 double x2,double y2,
2039 double x3,double y3,
2040 double x4,double y4)
2050 int bitid = ++currentswfid;
2052 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2053 swf_SetU16(tag, bitid);
2054 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2055 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2059 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2060 double x1,double y1,
2061 double x2,double y2,
2062 double x3,double y3,
2063 double x4,double y4)
2071 int bitid = ++currentswfid;
2073 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2074 swf_SetU16(tag, bitid);
2075 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2081 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2085 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2086 double x1,double y1,
2087 double x2,double y2,
2088 double x3,double y3,
2089 double x4,double y4, int n)
2100 /* SWF expects scanlines to be 4 byte aligned */
2103 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2105 for(y=0;y<sizey;y++)
2107 for(x=0;x<sizex;x++)
2108 *ptr++ = mem[y*sizex+x];
2109 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2114 int bitid = ++currentswfid;
2116 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2117 swf_SetU16(tag, bitid);
2118 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2126 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2130 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2131 double x1,double y1,
2132 double x2,double y2,
2133 double x3,double y3,
2134 double x4,double y4)
2142 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2145 void swfoutput_setparameter(char*name, char*value)
2147 if(!strcmp(name, "drawonlyshapes")) {
2148 drawonlyshapes = atoi(value);
2149 } else if(!strcmp(name, "ignoredraworder")) {
2150 ignoredraworder = atoi(value);
2151 } else if(!strcmp(name, "filloverlap")) {
2152 filloverlap = atoi(value);
2153 } else if(!strcmp(name, "linksopennewwindow")) {
2154 opennewwindow = atoi(value);
2155 } else if(!strcmp(name, "opennewwindow")) {
2156 opennewwindow = atoi(value);
2157 } else if(!strcmp(name, "storeallcharacters")) {
2158 storeallcharacters = atoi(value);
2159 } else if(!strcmp(name, "enablezlib")) {
2160 enablezlib = atoi(value);
2161 } else if(!strcmp(name, "insertstop")) {
2162 insertstoptag = atoi(value);
2163 } else if(!strcmp(name, "flashversion")) {
2164 flashversion = atoi(value);
2165 } else if(!strcmp(name, "minlinewidth")) {
2166 minlinewidth = atof(value);
2167 } else if(!strcmp(name, "jpegquality")) {
2168 int val = atoi(value);
2170 if(val>100) val=100;
2172 } else if(!strcmp(name, "splinequality")) {
2173 int v = atoi(value);
2174 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2177 } else if(!strcmp(name, "fontquality")) {
2178 int v = atoi(value);
2179 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2181 fontsplinemaxerror = v;
2183 fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);