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;
124 static void addPointToBBox(int px, int py)
130 swf_ExpandRect(&bboxrect, p);
132 swf_ExpandRect3(&bboxrect, p, linewidth*3/2);
136 // write a line-to command into the swf
137 static void lineto(TAG*tag, plotxy p0)
139 int px = (int)(p0.x*20);
140 int py = (int)(p0.y*20);
141 int rx = (px-swflastx);
142 int ry = (py-swflasty);
143 /* we can't skip this for rx=0,ry=0, those
145 swf_ShapeSetLine (tag, shape, rx,ry);
147 addPointToBBox(swflastx,swflasty);
148 addPointToBBox(px,py);
155 // write a spline-to command into the swf
156 static void splineto(TAG*tag, plotxy control,plotxy end)
158 int lastlastx = swflastx;
159 int lastlasty = swflasty;
161 int cx = ((int)(control.x*20)-swflastx);
162 int cy = ((int)(control.y*20)-swflasty);
165 int ex = ((int)(end.x*20)-swflastx);
166 int ey = ((int)(end.y*20)-swflasty);
170 if(cx || cy || ex || ey) {
171 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
172 addPointToBBox(lastlastx ,lastlasty );
173 addPointToBBox(lastlastx+cx,lastlasty+cy);
174 addPointToBBox(lastlastx+cx+ex,lastlasty+cy+ey);
179 /* write a line, given two points and the transformation
181 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
189 /* write a cubic (!) spline. This involves calling the approximate()
190 function out of spline.cc to convert it to a quadratic spline. */
191 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
194 struct qspline q[128];
208 /* fonts use a different approximation than shapes */
209 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
210 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
212 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
216 moveto(tag,q[t].start);
217 splineto(tag,q[t].control, q[t].end);
227 static void stopFill()
231 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
232 fillstylechanged = 1;
236 static void startFill()
240 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
241 fillstylechanged = 1;
246 /* draw an outline. These are generated by pdf2swf and by t1lib
247 (representing characters). */
248 void drawpath(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int log)
250 if( tag->id != ST_DEFINESHAPE &&
251 tag->id != ST_DEFINESHAPE2 &&
252 tag->id != ST_DEFINESHAPE3)
254 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
258 double lastx=0,lasty=0;
259 double firstx=0,firsty=0;
264 x += (outline->dest.x/(float)0xffff);
265 y += (outline->dest.y/(float)0xffff);
266 if(outline->type == SWF_PATHTYPE_MOVE)
268 //if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
269 if(filloverlap && !init && fill && output->drawmode != DRAWMODE_EOFILL) {
270 /* drawmode=FILL (not EOFILL) means that
271 seperate shapes do not cancel each other out.
272 On SWF side, we need to start a new shape for each
273 closed polygon, because SWF only knows EOFILL.
280 if(((int)(lastx*20) != (int)(firstx*20) ||
281 (int)(lasty*20) != (int)(firsty*20)) &&
290 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
291 line(tag, p0, p1, m);
297 else if(outline->type == SWF_PATHTYPE_LINE)
305 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
308 else if(outline->type == SWF_PATHTYPE_BEZIER)
314 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
317 p1.x=o2->C.x/(float)0xffff+lastx;
318 p1.y=o2->C.y/(float)0xffff+lasty;
319 p2.x=o2->B.x/(float)0xffff+lastx;
320 p2.y=o2->B.y/(float)0xffff+lasty;
323 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
324 spline(tag,p0,p1,p2,p3,m);
327 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
331 outline = outline->link;
333 if(((int)(lastx*20) != (int)(firstx*20) ||
334 (int)(lasty*20) != (int)(firsty*20)) &&
343 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
344 line(tag, p0, p1, m);
348 plotxy getPivot(SWF_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
350 SWF_PATHPOINT next, next2;
351 double xv=0,yv=0, xv2=0, yv2=0;
356 if(outline->type == SWF_PATHTYPE_LINE) {
357 next = outline->dest;
359 next = ((SWF_BEZIERSEGMENT*)outline)->B;
360 if(next.x==0 && next.y==0) {
361 next = ((SWF_BEZIERSEGMENT*)outline)->C;
363 if(next.x==0 && next.y==0) {
364 next = ((SWF_BEZIERSEGMENT*)outline)->dest;
368 if(trytwo && outline->last && outline->last->type != SWF_PATHTYPE_MOVE) {
369 if(outline->type == SWF_PATHTYPE_LINE) {
370 next2 = outline->last->dest;
372 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)(outline->last))->C;
373 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)(outline->last))->B;
374 next2.x = outline->last->dest.x - c.x;
375 next2.y = outline->last->dest.y - c.y;
376 if(next2.x==0 && next2.y==0) {
377 next2.x = outline->last->dest.x - b.x;
378 next2.y = outline->last->dest.y - b.y;
380 if(next2.x==0 && next2.y==0) {
381 next2.x = outline->last->dest.x;
382 next2.y = outline->last->dest.y;
388 if(outline->type == SWF_PATHTYPE_LINE) {
389 next = outline->dest;
391 SWF_PATHPOINT c = ((SWF_BEZIERSEGMENT*)outline)->C;
392 SWF_PATHPOINT b = ((SWF_BEZIERSEGMENT*)outline)->B;
393 next.x = outline->dest.x - c.x;
394 next.y = outline->dest.y - c.y;
395 if(next.x==0 && next.y==0) {
396 next.x = outline->dest.x - b.x;
397 next.y = outline->dest.y - b.y;
399 if(next.x==0 && next.y==0) {
400 next.x = outline->dest.x;
401 next.y = outline->dest.y;
405 if(trytwo && outline->link && outline->link->type != SWF_PATHTYPE_MOVE) {
406 if(outline->type == SWF_PATHTYPE_LINE) {
407 next2 = outline->link->dest;
409 next2 = ((SWF_BEZIERSEGMENT*)(outline->link))->B;
410 if(next2.x==0 && next2.y==0) {
411 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->C;
413 if(next2.x==0 && next2.y==0) {
414 next2 = ((SWF_BEZIERSEGMENT*)outline->link)->dest;
422 xv = next.y/(float)0xffff;
423 yv = -next.x/(float)0xffff;
425 xv = -next.y/(float)0xffff;
426 yv = next.x/(float)0xffff;
429 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
435 xv2 = next2.y/(float)0xffff;
436 yv2 = -next2.x/(float)0xffff;
438 xv2 = -next2.y/(float)0xffff;
439 yv2 = next2.x/(float)0xffff;
442 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
447 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
457 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, SWF_OUTLINE*outline)
459 double lastx=x, lasty=y;
460 while (outline && outline->type != SWF_PATHTYPE_MOVE)
462 x += (outline->dest.x/(float)0xffff);
463 y += (outline->dest.y/(float)0xffff);
465 if(outline->type == SWF_PATHTYPE_LINE)
472 line(tag, p0, p1, m);
474 else if(outline->type == SWF_PATHTYPE_BEZIER)
477 SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
480 p1.x=o2->C.x/(float)0xffff+lastx;
481 p1.y=o2->C.y/(float)0xffff+lasty;
482 p2.x=o2->B.x/(float)0xffff+lastx;
483 p2.y=o2->B.y/(float)0xffff+lasty;
486 spline(tag,p0,p1,p2,p3,m);
490 outline = outline->link;
494 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)
499 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
502 SWF_OUTLINE *last, *tmp=outline;
503 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
509 while(tmp && tmp->type != SWF_PATHTYPE_MOVE) {
511 lx += (tmp->dest.x/(float)0xffff);
512 ly += (tmp->dest.y/(float)0xffff);
515 s = getPivot(outline, 0, line_width, 0, 0);
516 e = getPivot(last, 0, line_width, 1, 0);
518 if(line_cap == LINE_CAP_BUTT) {
519 /* make the clipping rectangle slighly bigger
520 than the line ending, so that it get's clipped
530 p2.x = x2 - s.y - s.x*ee;
531 p2.y = y2 + s.x - s.y*ee;
532 p3.x = x2 - s.y + s.x*ee;
533 p3.y = y2 + s.x + s.y*ee;
538 m2.x = lx + e.y - e.x*ee;
539 m2.y = ly - e.x - e.y*ee;
540 m3.x = lx + e.y + e.x*ee;
541 m3.y = ly - e.x + e.y*ee;
543 for(nr=0;nr<2;nr++) {
545 struct plotxy q0,q1,q2,q3,q4,q5;
548 if(line_cap == LINE_CAP_BUTT) {
551 q1.x = sizex; q1.y = 0;
552 q2.x = sizex; q2.y = sizey;
553 q3.x = 0; q3.y = sizey;
555 q0.x = sizex; q0.y = sizey;
556 q1.x = 0; q1.y = sizey;
558 q3.x = sizex; q3.y = 0;
572 line(tag, p0, p1, m);
573 line(tag, p1, p2, m);
574 line(tag, p2, p3, m);
575 line(tag, p3, p0, m);
577 if(line_cap == LINE_CAP_BUTT) {
579 endshape(depth+2-nr);
591 drawShortPath(output,x,y,m,outline);
593 if(line_cap == LINE_CAP_BUTT) {
599 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)
601 plotxy d1,d2,p1,p2,p3,p4;
603 d1.x = (outline->dest.x/(float)0xffff);
604 d1.y = (outline->dest.y/(float)0xffff);
605 d2 = getPivot(outline, 0, line_width, 0, 0);
607 assert(line_cap != LINE_CAP_ROUND);
608 if(line_cap == LINE_CAP_SQUARE) {
617 p2.x = x + d2.x + d1.x;
618 p2.y = y + d2.y + d1.y;
619 p3.x = x - d2.x + d1.x;
620 p3.y = y - d2.y + d1.y;
630 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)
632 SWF_OUTLINE*tmp=outline;
638 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
640 while(tmp->link && tmp->link->type!=SWF_PATHTYPE_MOVE) {
641 xx += (tmp->dest.x/(float)0xffff);
642 yy += (tmp->dest.y/(float)0xffff);
646 assert(tmp->type == SWF_PATHTYPE_LINE);
647 assert(outline->type == SWF_PATHTYPE_LINE);
651 if(outline->link == tmp) {
652 /* the two straight line segments (which are everything we
653 need to draw) are very likely to overlap. To avoid that
654 they cancel each other out at the end points, start a new
655 shape for the second one */
656 endshape(0);startshape(output);
660 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
662 if(outline->link != tmp)
666 tmp->type = SWF_PATHTYPE_MOVE;
667 x += (outline->dest.x/(float)0xffff);
668 y += (outline->dest.y/(float)0xffff);
669 outline = outline->link;
670 drawShortPath(output, x, y, m, outline);
678 static int t1len(SWF_OUTLINE*line)
681 while(line && line->type != SWF_PATHTYPE_MOVE) {
688 static float t1linelen(SWF_OUTLINE*line)
691 x = (line->dest.x/(float)0xffff);
692 y = (line->dest.y/(float)0xffff);
693 return sqrt(x*x+y*y);
696 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)
698 if( tag->id != ST_DEFINESHAPE &&
699 tag->id != ST_DEFINESHAPE2 &&
700 tag->id != ST_DEFINESHAPE3) {
701 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
706 double lastx=0,lasty=0;
709 SWF_OUTLINE*tmp = outline, *last = 0;
714 x += (tmp->dest.x/(float)0xffff);
715 y += (tmp->dest.y/(float)0xffff);
717 if(!tmp || tmp->type == SWF_PATHTYPE_MOVE) {
719 if(last->type == SWF_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
720 lastwasline && line_cap != LINE_CAP_ROUND)
721 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
723 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
737 if(tmp && tmp->type == SWF_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
743 tmp->link->last = tmp; // make sure list is properly linked in both directions
748 static inline int colorcompare(RGBA*a,RGBA*b)
760 static const int CHARDATAMAX = 8192;
768 } chardata[CHARDATAMAX];
771 static SRECT getcharacterbbox(SWFFONT*font)
775 memset(&r, 0, sizeof(r));
778 if(debug) printf("\n");
779 for(t=0;t<chardatapos;t++)
781 if(chardata[t].fontid != font->id) {
782 msg("<error> Internal error: fontid %d != fontid %d", chardata[t].fontid, font->id);
785 SRECT b = font->layout->bounds[chardata[t].charid];
786 b.xmin *= chardata[t].size;
787 b.ymin *= chardata[t].size;
788 b.xmax *= chardata[t].size;
789 b.ymax *= chardata[t].size;
794 b.xmin += chardata[t].x;
795 b.ymin += chardata[t].y;
796 b.xmax += chardata[t].x;
797 b.ymax += chardata[t].y;
799 /* until we solve the INTERNAL_SCALING problem (see below)
800 make sure the bounding box is big enough */
806 if(debug) printf("(%f,%f,%f,%f) -> (%f,%f,%f,%f) [font %d/%d, char %d]\n",
807 font->layout->bounds[chardata[t].charid].xmin/20.0,
808 font->layout->bounds[chardata[t].charid].ymin/20.0,
809 font->layout->bounds[chardata[t].charid].xmax/20.0,
810 font->layout->bounds[chardata[t].charid].ymax/20.0,
819 swf_ExpandRect2(&r, &b);
821 if(debug) printf("-----> (%f,%f,%f,%f)\n",
829 static void putcharacters(TAG*tag)
834 color.r = chardata[0].color.r^255;
843 int charadvance[128];
846 int glyphbits=1; //TODO: can this be zero?
849 if(tag->id != ST_DEFINETEXT &&
850 tag->id != ST_DEFINETEXT2) {
851 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
855 msg("<warning> putcharacters called with zero characters");
858 for(pass = 0; pass < 2; pass++)
868 advancebits++; // add sign bit
869 swf_SetU8(tag, glyphbits);
870 swf_SetU8(tag, advancebits);
873 for(t=0;t<=chardatapos;t++)
875 if(lastfontid != chardata[t].fontid ||
876 lastx!=chardata[t].x ||
877 lasty!=chardata[t].y ||
878 !colorcompare(&color, &chardata[t].color) ||
880 lastsize != chardata[t].size ||
883 if(charstorepos && pass==0)
886 for(s=0;s<charstorepos;s++)
888 while(charids[s]>=(1<<glyphbits))
890 while(charadvance[s]>=(1<<advancebits))
894 if(charstorepos && pass==1)
896 tag->writeBit = 0; // Q&D
897 swf_SetBits(tag, 0, 1); // GLYPH Record
898 swf_SetBits(tag, charstorepos, 7); // number of glyphs
900 for(s=0;s<charstorepos;s++)
902 swf_SetBits(tag, charids[s], glyphbits);
903 swf_SetBits(tag, charadvance[s], advancebits);
908 if(pass == 1 && t<chardatapos)
914 if(lastx != chardata[t].x ||
915 lasty != chardata[t].y)
917 newx = chardata[t].x;
918 newy = chardata[t].y;
924 if(!colorcompare(&color, &chardata[t].color))
926 color = chardata[t].color;
929 font.id = chardata[t].fontid;
930 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
933 tag->writeBit = 0; // Q&D
934 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
937 lastfontid = chardata[t].fontid;
938 lastx = chardata[t].x;
939 lasty = chardata[t].y;
940 lastsize = chardata[t].size;
947 int nextt = t==chardatapos-1?t:t+1;
948 int rel = chardata[nextt].x-chardata[t].x;
949 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
951 lastx=chardata[nextt].x;
957 charids[charstorepos] = chardata[t].charid;
958 charadvance[charstorepos] = advance;
965 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
966 int x,int y, int size)
968 if(chardatapos == CHARDATAMAX)
970 msg("<warning> Character buffer too small. SWF will be slightly bigger");
974 chardata[chardatapos].fontid = fontid;
975 chardata[chardatapos].charid = charid;
976 chardata[chardatapos].x = x;
977 chardata[chardatapos].y = y;
978 chardata[chardatapos].color = obj->fillrgb;
979 chardata[chardatapos].size = size;
989 /* todo: why don't higher values (64, 1024) work here? */
990 #define FONT_INTERNAL_SIZE 1
992 /* process a character. */
993 static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
996 msg("<warning> Font is NULL");
1000 int charid = getCharID(swffont, charnr, character, u);
1003 msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
1004 FIXNULL(character),charnr, u, FIXNULL((char*)swffont->name), swffont->numchars);
1015 float det = ((m->m11*m->m22)-(m->m21*m->m12));
1016 if(fabs(det) < 0.0005) {
1017 /* x direction equals y direction- the text is invisible */
1020 det = 20*FONT_INTERNAL_SIZE / det;
1023 p.x = (SCOORD)(( x * m->m22 - y * m->m12)*det);
1024 p.y = (SCOORD)((- x * m->m21 + y * m->m11)*det);
1026 putcharacter(obj, swffont->id, charid,p.x,p.y,FONT_INTERNAL_SIZE);
1027 swf_FontUseGlyph(swffont, charid);
1032 SWF_OUTLINE*outline = font->getOutline(character, charnr);
1033 char* charname = character;
1036 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
1037 FIXNULL(character),charnr,FIXNULL(font->getName()));
1056 drawpath(tag, outline, &m2, 0);
1061 static void endtext(swfoutput*obj)
1066 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1067 swf_SetU16(tag, textid);
1070 r = getcharacterbbox(obj->swffont);
1072 swf_SetRect(tag,&r);
1075 swf_GetMatrix(0, &m);
1076 swf_SetMatrix(tag,&m);
1080 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1081 swf_ObjectPlace(tag,textid,/*depth*/depth++,&obj->fontmatrix,NULL,NULL);
1086 /* draw a curved polygon. */
1087 void swfoutput_drawpath(swfoutput*output, SWF_OUTLINE*outline,
1093 /* Multiple polygons in one shape don't overlap correctly,
1094 so we better start a new shape here if the polygon is filled
1096 if(shapeid>=0 && fill && !ignoredraworder) {
1108 drawpath(output, outline,m, 0);
1111 void swfoutput_drawpath2poly(struct swfoutput*output, SWF_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
1121 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
1124 int getCharID(SWFFONT *font, int charnr, char *charname, int u)
1128 for(t=0;t<font->numchars;t++) {
1129 if(font->glyphnames[t] && !strcmp(font->glyphnames[t],charname)) {
1133 /* if we didn't find the character, maybe
1134 we can find the capitalized version */
1135 for(t=0;t<font->numchars;t++) {
1136 if(font->glyphnames[t] && !strcasecmp(font->glyphnames[t],charname)) {
1143 /* try to use the unicode id */
1144 if(u>=0 && u<font->maxascii && font->ascii2glyph[u]>=0) {
1145 return font->ascii2glyph[u];
1149 if(charnr>=0 && charnr<font->numchars) {
1153 /* the following is technically wrong, and only works if the font encoding
1154 is US-ASCII based. It's needed for fonts which return broken unicode
1156 /* if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
1157 return font->ascii2glyph[charnr];
1164 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1165 void swfoutput_setfont(struct swfoutput*obj, char*fontid, char*filename)
1167 fontlist_t*last=0,*iterator;
1169 msg("<error> No fontid");
1173 if(obj->swffont && obj->swffont->name && !strcmp((char*)obj->swffont->name,fontid))
1176 /* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
1177 with multiple fonts */
1180 iterator = fontlist;
1182 if(!strcmp((char*)iterator->swffont->name,fontid)) {
1183 obj->swffont = iterator->swffont;
1187 iterator = iterator->next;
1191 msg("<error> No filename given for font- internal error?");
1195 swf_SetLoadFontParameters(64,/*skip unused*/0,/*full unicode*/1);
1196 SWFFONT*swffont = swf_LoadFont(filename);
1199 msg("<warning> Couldn't load font %s (%s)", fontid, filename);
1200 swffont = swf_LoadFont(0);
1203 swf_FontSetID(swffont, ++currentswfid);
1205 if(screenloglevel >= LOGLEVEL_DEBUG) {
1206 // print font information
1207 msg("<debug> Font %s (%s)",swffont->name, filename);
1208 msg("<debug> | ID: %d", swffont->id);
1209 msg("<debug> | Version: %d", swffont->version);
1210 msg("<debug> | Name: %s", fontid);
1211 msg("<debug> | Numchars: %d", swffont->numchars);
1212 msg("<debug> | Maxascii: %d", swffont->maxascii);
1213 msg("<debug> | Style: %d", swffont->style);
1214 msg("<debug> | Encoding: %d", swffont->encoding);
1215 for(int iii=0; iii<swffont->numchars;iii++) {
1216 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,
1217 swffont->layout->bounds[iii].xmin/20.0,
1218 swffont->layout->bounds[iii].ymin/20.0,
1219 swffont->layout->bounds[iii].xmax/20.0,
1220 swffont->layout->bounds[iii].ymax/20.0
1225 /* set the font name to the ID we use here */
1226 if(swffont->name) free(swffont->name);
1227 swffont->name = (U8*)strdup(fontid);
1229 iterator = new fontlist_t;
1230 iterator->swffont = swffont;
1234 last->next = iterator;
1236 fontlist = iterator;
1238 obj->swffont = swffont;
1241 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1243 fontlist_t *iterator = fontlist;
1245 if(!strcmp((char*)iterator->swffont->name,fontid))
1247 iterator = iterator->next;
1252 /* set's the matrix which is to be applied to characters drawn by
1253 swfoutput_drawchar() */
1254 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1255 double m21,double m22)
1257 if(obj->fontm11 == m11 &&
1258 obj->fontm12 == m12 &&
1259 obj->fontm21 == m21 &&
1260 obj->fontm22 == m22)
1270 m.sx = (U32)(((obj->fontm11)*65536)/FONT_INTERNAL_SIZE); m.r1 = (U32)(((obj->fontm12)*65536)/FONT_INTERNAL_SIZE);
1271 m.r0 = (U32)(((obj->fontm21)*65536)/FONT_INTERNAL_SIZE); m.sy = (U32)(((obj->fontm22)*65536)/FONT_INTERNAL_SIZE);
1274 obj->fontmatrix = m;
1277 /* draws a character at x,y. */
1278 int swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, int u)
1281 m.m11 = obj->fontm11;
1282 m.m12 = obj->fontm12;
1283 m.m21 = obj->fontm21;
1284 m.m22 = obj->fontm22;
1287 return drawchar(obj, obj->swffont, character, charnr, u, &m);
1290 /* initialize the swf writer */
1291 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1295 memset(obj, 0, sizeof(struct swfoutput));
1296 filename = _filename;
1300 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1305 memset(&swf,0x00,sizeof(SWF));
1307 swf.fileVersion = flashversion;
1308 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1309 swf.movieSize.xmin = 20*x1;
1310 swf.movieSize.ymin = 20*y1;
1311 swf.movieSize.xmax = 20*x2;
1312 swf.movieSize.ymax = 20*y2;
1316 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1318 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1319 swf_SetRGB(tag,&rgb);
1321 if(1)/* add white rectangle */
1326 int shapeid = ++currentswfid;
1331 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1333 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1334 swf_SetU16(tag,shapeid);
1335 swf_SetRect(tag,&r);
1336 swf_SetShapeHeader(tag,s);
1337 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1338 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1339 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1340 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1341 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1342 swf_ShapeSetEnd(tag);
1344 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1345 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1346 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1347 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1351 tag = swf_InsertTag(tag, ST_PROTECT);
1356 void swfoutput_setprotected() //write PROTECT tag
1361 static void startshape(struct swfoutput*obj)
1369 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1371 swf_ShapeNew(&shape);
1372 linestyleid = swf_ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1373 rgb.r = obj->fillrgb.r;
1374 rgb.g = obj->fillrgb.g;
1375 rgb.b = obj->fillrgb.b;
1376 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1378 shapeid = ++currentswfid;
1379 swf_SetU16(tag,shapeid); // ID
1381 /* TODO: patch back */
1382 bboxrectpos = tag->len;
1387 swf_SetRect(tag,&r);
1389 memset(&bboxrect, 0, sizeof(bboxrect));
1391 swf_SetShapeStyles(tag,shape);
1392 swf_ShapeCountBits(shape,NULL,NULL);
1393 swf_SetShapeBits(tag,shape);
1395 /* TODO: do we really need this? */
1396 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1397 swflastx=swflasty=0;
1402 static void starttext(struct swfoutput*obj)
1407 textid = ++currentswfid;
1409 swflastx=swflasty=0;
1413 /* TODO: move to ../lib/rfxswf */
1414 void changeRect(TAG*tag, int pos, SRECT*newrect)
1416 /* determine length of old rect */
1420 swf_GetRect(tag, &old);
1421 swf_ResetReadBits(tag);
1422 int pos_end = tag->pos;
1424 int len = tag->len - pos_end;
1425 U8*data = (U8*)malloc(len);
1426 memcpy(data, &tag->data[pos_end], len);
1429 swf_SetRect(tag, newrect);
1430 swf_SetBlock(tag, data, len);
1432 tag->pos = tag->readBit = 0;
1435 static void endshape(int clipdepth)
1439 swf_ShapeSetEnd(tag);
1442 // delete the tag again, we didn't do anything
1445 swf_DeleteTag(todel);
1451 changeRect(tag, bboxrectpos, &bboxrect);
1453 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1455 swf_ObjectPlaceClip(tag,shapeid,depth++,NULL,NULL,NULL,clipdepth);
1457 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1463 static void endpage(struct swfoutput*obj)
1470 swfoutput_endclip(obj);
1474 atag = action_Stop(atag);
1475 atag = action_End(atag);
1476 tag = swf_InsertTag(tag,ST_DOACTION);
1477 swf_ActionSet(tag,atag);
1479 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1482 void swfoutput_newpage(struct swfoutput*obj)
1486 for(depth--;depth>=startdepth;depth--) {
1487 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1488 swf_SetU16(tag,depth);
1494 /* Perform cleaning up, complete the swf, and write it out. */
1495 void swfoutput_destroy(struct swfoutput* obj)
1498 fontlist_t *tmp,*iterator = fontlist;
1500 TAG*mtag = swf.firstTag;
1501 if(iterator->swffont) {
1502 mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
1503 /*if(!storeallcharacters)
1504 swf_FontReduce(iterator->swffont);*/
1505 swf_FontSetDefine2(mtag, iterator->swffont);
1506 swf_FontFree(iterator->swffont);
1510 iterator = iterator->next;
1517 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1522 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1526 tag = swf_InsertTag(tag,ST_END);
1528 if(enablezlib || flashversion>=6) {
1529 if FAILED(swf_WriteSWC(fi,&swf))
1530 msg("<error> WriteSWC() failed.\n");
1532 if FAILED(swf_WriteSWF(fi,&swf))
1533 msg("<error> WriteSWF() failed.\n");
1538 msg("<notice> SWF written\n");
1541 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1543 obj->drawmode = mode;
1544 if(mode == DRAWMODE_FILL)
1546 else if(mode == DRAWMODE_EOFILL)
1548 else if(mode == DRAWMODE_STROKE)
1550 else if(mode == DRAWMODE_CLIP)
1552 else if(mode == DRAWMODE_EOCLIP)
1556 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1558 if(obj->fillrgb.r == r &&
1559 obj->fillrgb.g == g &&
1560 obj->fillrgb.b == b &&
1561 obj->fillrgb.a == a) return;
1571 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1573 if(obj->strokergb.r == r &&
1574 obj->strokergb.g == g &&
1575 obj->strokergb.b == b &&
1576 obj->strokergb.a == a) return;
1580 obj->strokergb.r = r;
1581 obj->strokergb.g = g;
1582 obj->strokergb.b = b;
1583 obj->strokergb.a = a;
1586 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1588 if(linewidth == (u16)(linewidth*20))
1593 linewidth = (u16)(linewidth*20);
1597 void swfoutput_startclip(swfoutput*obj, SWF_OUTLINE*outline, struct swfmatrix*m)
1606 msg("<warning> Too many clip levels.");
1611 int olddrawmode = obj->drawmode;
1612 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1613 swfoutput_drawpath(obj, outline, m);
1614 swf_ShapeSetEnd(tag);
1615 swfoutput_setdrawmode(obj, olddrawmode);
1617 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1618 cliptags[clippos] = tag;
1619 clipshapes[clippos] = shapeid;
1620 clipdepths[clippos] = depth++;
1625 void swfoutput_endclip(swfoutput*obj)
1633 msg("<error> Invalid end of clipping region");
1637 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1640 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1642 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1645 if(!strncmp("http://pdf2swf:", url, 15)) {
1646 char*tmp = strdup(url);
1647 int l = strlen(tmp);
1650 swfoutput_namedlink(obj, tmp+15, points);
1661 actions = action_GetUrl(0, url, "_parent");
1663 actions = action_GetUrl(0, url, "_this");
1664 actions = action_End(actions);
1666 drawlink(obj, actions, 0, points,0);
1668 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1677 actions = action_GotoFrame(0, page);
1678 actions = action_End(actions);
1680 drawlink(obj, actions, 0, points,0);
1683 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1684 of the viewer objects, like subtitles, index elements etc.
1686 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1688 ActionTAG *actions1,*actions2;
1689 char*tmp = strdup(name);
1697 if(!strncmp(tmp, "call:", 5))
1699 char*x = strchr(&tmp[5], ':');
1701 actions1 = action_PushInt(0, 0); //number of parameters (0)
1702 actions1 = action_PushString(actions1, &tmp[5]); //function name
1703 actions1 = action_CallFunction(actions1);
1706 actions1 = action_PushString(0, x+1); //parameter
1707 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1708 actions1 = action_PushString(actions1, &tmp[5]); //function name
1709 actions1 = action_CallFunction(actions1);
1711 actions2 = action_End(0);
1716 actions1 = action_PushString(0, "/:subtitle");
1717 actions1 = action_PushString(actions1, name);
1718 actions1 = action_SetVariable(actions1);
1719 actions1 = action_End(actions1);
1721 actions2 = action_PushString(0, "/:subtitle");
1722 actions2 = action_PushString(actions2, "");
1723 actions2 = action_SetVariable(actions2);
1724 actions2 = action_End(actions2);
1727 drawlink(obj, actions1, actions2, points,mouseover);
1729 swf_ActionFree(actions1);
1730 swf_ActionFree(actions2);
1734 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1740 struct plotxy p1,p2,p3,p4;
1744 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1748 int buttonid = ++currentswfid;
1751 if(points[t].x>xmax) xmax=points[t].x;
1752 if(points[t].y>ymax) ymax=points[t].y;
1753 if(points[t].x<xmin) xmin=points[t].x;
1754 if(points[t].y<ymin) ymin=points[t].y;
1757 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1758 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1760 /* the following code subtracts the upper left edge from all coordinates,
1761 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1762 Necessary for preprocessing with swfcombine. */
1763 posx = xmin; posy = ymin;
1764 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1765 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1766 xmin -= posx; ymin -= posy;
1767 xmax -= posx; ymax -= posy;
1770 myshapeid = ++currentswfid;
1771 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1772 swf_ShapeNew(&shape);
1773 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1774 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1775 swf_SetU16(tag, myshapeid);
1776 r.xmin = (int)(xmin*20);
1777 r.ymin = (int)(ymin*20);
1778 r.xmax = (int)(xmax*20);
1779 r.ymax = (int)(ymax*20);
1780 swf_SetRect(tag,&r);
1781 swf_SetShapeStyles(tag,shape);
1782 swf_ShapeCountBits(shape,NULL,NULL);
1783 swf_SetShapeBits(tag,shape);
1784 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1785 swflastx = swflasty = 0;
1791 swf_ShapeSetEnd(tag);
1794 myshapeid2 = ++currentswfid;
1795 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1796 swf_ShapeNew(&shape);
1797 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1799 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1800 swf_SetU16(tag, myshapeid2);
1801 r.xmin = (int)(xmin*20);
1802 r.ymin = (int)(ymin*20);
1803 r.xmax = (int)(xmax*20);
1804 r.ymax = (int)(ymax*20);
1805 swf_SetRect(tag,&r);
1806 swf_SetShapeStyles(tag,shape);
1807 swf_ShapeCountBits(shape,NULL,NULL);
1808 swf_SetShapeBits(tag,shape);
1809 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1810 swflastx = swflasty = 0;
1816 swf_ShapeSetEnd(tag);
1820 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1821 swf_SetU16(tag,buttonid); //id
1822 swf_ButtonSetFlags(tag, 0); //menu=no
1823 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1824 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1825 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1826 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1828 swf_ActionSet(tag,actions1);
1833 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1834 swf_SetU16(tag,buttonid); //id
1835 swf_ButtonSetFlags(tag, 0); //menu=no
1836 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1837 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1838 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1839 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1840 swf_SetU8(tag,0); // end of button records
1841 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1842 swf_ActionSet(tag,actions1);
1844 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1845 swf_ActionSet(tag,actions2);
1847 swf_ButtonPostProcess(tag, 2);
1850 swf_ButtonPostProcess(tag, 1);
1854 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1856 if(posx!=0 || posy!=0) {
1858 swf_GetMatrix(0,&m);
1859 m.tx = (int)(posx*20);
1860 m.ty = (int)(posy*20);
1861 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1864 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1868 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1869 double x1,double y1,
1870 double x2,double y2,
1871 double x3,double y3,
1872 double x4,double y4)
1878 struct plotxy p1,p2,p3,p4;
1880 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1881 if(x2>xmax) xmax=x2;
1882 if(y2>ymax) ymax=y2;
1883 if(x2<xmin) xmin=x2;
1884 if(y2<ymin) ymin=y2;
1885 if(x3>xmax) xmax=x3;
1886 if(y3>ymax) ymax=y3;
1887 if(x3<xmin) xmin=x3;
1888 if(y3<ymin) ymin=y3;
1889 if(x4>xmax) xmax=x4;
1890 if(y4>ymax) ymax=y4;
1891 if(x4<xmin) xmin=x4;
1892 if(y4<ymin) ymin=y4;
1898 {p1.x = (int)(p1.x*20)/20.0;
1899 p1.y = (int)(p1.y*20)/20.0;
1900 p2.x = (int)(p2.x*20)/20.0;
1901 p2.y = (int)(p2.y*20)/20.0;
1902 p3.x = (int)(p3.x*20)/20.0;
1903 p3.y = (int)(p3.y*20)/20.0;
1904 p4.x = (int)(p4.x*20)/20.0;
1905 p4.y = (int)(p4.y*20)/20.0;}
1908 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1909 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1910 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1911 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1913 m.tx = (int)(p1.x*20);
1914 m.ty = (int)(p1.y*20);
1917 myshapeid = ++currentswfid;
1918 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1919 swf_ShapeNew(&shape);
1920 //lsid = ShapeAddLineStyle(shape,linewidth,&obj->strokergb);
1921 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1922 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1923 swf_SetU16(tag, myshapeid);
1924 r.xmin = (int)(xmin*20);
1925 r.ymin = (int)(ymin*20);
1926 r.xmax = (int)(xmax*20);
1927 r.ymax = (int)(ymax*20);
1928 swf_SetRect(tag,&r);
1929 swf_SetShapeStyles(tag,shape);
1930 swf_ShapeCountBits(shape,NULL,NULL);
1931 swf_SetShapeBits(tag,shape);
1932 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1933 swflastx = swflasty = 0;
1940 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1941 ShapeSetLine (tag, shape, (int)(x1*20);
1942 ShapeSetLine (tag, shape, x*20,0);
1943 ShapeSetLine (tag, shape, 0,-y*20);
1944 ShapeSetLine (tag, shape, -x*20,0);*/
1945 swf_ShapeSetEnd(tag);
1948 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1949 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1952 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1953 double x1,double y1,
1954 double x2,double y2,
1955 double x3,double y3,
1956 double x4,double y4)
1964 int bitid = ++currentswfid;
1966 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1967 swf_SetU16(tag, bitid);
1968 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1974 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1978 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1979 double x1,double y1,
1980 double x2,double y2,
1981 double x3,double y3,
1982 double x4,double y4)
1992 int bitid = ++currentswfid;
1994 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1995 swf_SetU16(tag, bitid);
1996 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1997 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2001 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2002 double x1,double y1,
2003 double x2,double y2,
2004 double x3,double y3,
2005 double x4,double y4)
2013 int bitid = ++currentswfid;
2015 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2016 swf_SetU16(tag, bitid);
2017 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2023 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2027 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2028 double x1,double y1,
2029 double x2,double y2,
2030 double x3,double y3,
2031 double x4,double y4, int n)
2042 /* SWF expects scanlines to be 4 byte aligned */
2045 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2047 for(y=0;y<sizey;y++)
2049 for(x=0;x<sizex;x++)
2050 *ptr++ = mem[y*sizex+x];
2051 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2056 int bitid = ++currentswfid;
2058 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2059 swf_SetU16(tag, bitid);
2060 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2068 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2072 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2073 double x1,double y1,
2074 double x2,double y2,
2075 double x3,double y3,
2076 double x4,double y4)
2084 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2087 void swfoutput_setparameter(char*name, char*value)
2089 if(!strcmp(name, "drawonlyshapes")) {
2090 drawonlyshapes = atoi(value);
2091 } else if(!strcmp(name, "ignoredraworder")) {
2092 ignoredraworder = atoi(value);
2093 } else if(!strcmp(name, "filloverlap")) {
2094 filloverlap = atoi(value);
2095 } else if(!strcmp(name, "linksopennewwindow")) {
2096 opennewwindow = atoi(value);
2097 } else if(!strcmp(name, "opennewwindow")) {
2098 opennewwindow = atoi(value);
2099 } else if(!strcmp(name, "storeallcharacters")) {
2100 storeallcharacters = atoi(value);
2101 } else if(!strcmp(name, "enablezlib")) {
2102 enablezlib = atoi(value);
2103 } else if(!strcmp(name, "insertstop")) {
2104 insertstoptag = atoi(value);
2105 } else if(!strcmp(name, "flashversion")) {
2106 flashversion = atoi(value);
2107 } else if(!strcmp(name, "jpegquality")) {
2108 int val = atoi(value);
2110 if(val>100) val=100;
2112 } else if(!strcmp(name, "splinequality")) {
2113 int v = atoi(value);
2114 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2117 } else if(!strcmp(name, "fontquality")) {
2118 int v = atoi(value);
2119 v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
2121 fontsplinemaxerror = v;
2123 fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);