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"
39 #define standardEncodingSize 335
40 extern char *standardEncodingNames[standardEncodingSize];
43 int ignoredraworder=0;
46 int storeallcharacters=0;
51 int fontsplinemaxerror=1;
52 static int flag_protected = 0;
54 typedef unsigned char u8;
55 typedef unsigned short int u16;
56 typedef unsigned long int u32;
59 static char* filename = 0;
62 static int currentswfid = 0;
64 static int startdepth = 1;
67 static int shapeid = -1;
68 static int textid = -1;
70 static int drawmode = -1;
71 static char storefont = 0;
72 static int fillstyleid;
73 static int linestyleid;
74 static int swflastx=0;
75 static int swflasty=0;
76 static int lastwasfill = 0;
88 char fillstylechanged = 0;
90 static void startshape(struct swfoutput* obj);
91 static void starttext(struct swfoutput* obj);
92 static void endshape();
93 static void endtext();
95 // matrix multiplication. changes p0
96 static void transform (plotxy*p0,struct swfmatrix*m)
99 x = m->m11*p0->x+m->m12*p0->y;
100 y = m->m21*p0->x+m->m22*p0->y;
105 // write a move-to command into the swf
106 static int moveto(TAG*tag, plotxy p0)
108 int rx = (int)(p0.x*20);
109 int ry = (int)(p0.y*20);
110 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
111 swf_ShapeSetMove (tag, shape, rx,ry);
112 fillstylechanged = 0;
120 // write a line-to command into the swf
121 static void lineto(TAG*tag, plotxy p0)
123 int rx = ((int)(p0.x*20)-swflastx);
124 int ry = ((int)(p0.y*20)-swflasty);
125 /* we can't skip this for rx=0,ry=0, those
127 swf_ShapeSetLine (tag, shape, rx,ry);
132 // write a spline-to command into the swf
133 static void splineto(TAG*tag, plotxy control,plotxy end)
135 int cx = ((int)(control.x*20)-swflastx);
136 int cy = ((int)(control.y*20)-swflasty);
139 int ex = ((int)(end.x*20)-swflastx);
140 int ey = ((int)(end.y*20)-swflasty);
143 if(cx || cy || ex || ey)
144 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
147 /* write a line, given two points and the transformation
149 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
157 /* write a cubic (!) spline. This involves calling the approximate()
158 function out of spline.cc to convert it to a quadratic spline. */
159 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
162 struct qspline q[128];
176 /* fonts use a different approximation than shapes */
177 num = cspline_approximate(&c, q, fontsplinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
178 //num = cspline_approximate(&c, q, 10.0, APPROXIMATE_INFLECTION);
180 num = cspline_approximate(&c, q, splinemaxerror/20.0, APPROXIMATE_RECURSIVE_BINARY);
184 moveto(tag,q[t].start);
185 splineto(tag,q[t].control, q[t].end);
195 static void stopFill()
199 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
200 fillstylechanged = 1;
204 static void startFill()
208 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
209 fillstylechanged = 1;
214 /* draw a T1 outline. These are generated by pdf2swf and by t1lib
215 (representing characters). */
216 void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log)
218 if(tag->id != ST_DEFINEFONT &&
219 tag->id != ST_DEFINESHAPE &&
220 tag->id != ST_DEFINESHAPE2 &&
221 tag->id != ST_DEFINESHAPE3)
223 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
227 double lastx=0,lasty=0;
228 double firstx=0,firsty=0;
233 x += (outline->dest.x/(float)0xffff);
234 y += (outline->dest.y/(float)0xffff);
235 if(outline->type == T1_PATHTYPE_MOVE)
237 if(((int)(lastx*20) != (int)(firstx*20) ||
238 (int)(lasty*20) != (int)(firsty*20)) &&
247 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
248 line(tag, p0, p1, m);
254 else if(outline->type == T1_PATHTYPE_LINE)
262 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
265 else if(outline->type == T1_PATHTYPE_BEZIER)
271 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
274 p1.x=o2->C.x/(float)0xffff+lastx;
275 p1.y=o2->C.y/(float)0xffff+lasty;
276 p2.x=o2->B.x/(float)0xffff+lastx;
277 p2.y=o2->B.y/(float)0xffff+lasty;
280 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
281 spline(tag,p0,p1,p2,p3,m);
284 msg("<error> drawpath: unknown outline type:%d\n", outline->type);
288 outline = outline->link;
290 if(((int)(lastx*20) != (int)(firstx*20) ||
291 (int)(lasty*20) != (int)(firsty*20)) &&
300 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
301 line(tag, p0, p1, m);
305 plotxy getPivot(T1_OUTLINE*outline, int dir, double line_width, int end, int trytwo)
307 T1_PATHPOINT next, next2;
308 double xv=0,yv=0, xv2=0, yv2=0;
313 if(outline->type == T1_PATHTYPE_LINE) {
314 next = outline->dest;
316 next = ((T1_BEZIERSEGMENT*)outline)->B;
317 if(next.x==0 && next.y==0) {
318 next = ((T1_BEZIERSEGMENT*)outline)->C;
320 if(next.x==0 && next.y==0) {
321 next = ((T1_BEZIERSEGMENT*)outline)->dest;
325 if(trytwo && outline->last && outline->last->type != T1_PATHTYPE_MOVE) {
326 if(outline->type == T1_PATHTYPE_LINE) {
327 next2 = outline->last->dest;
329 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)(outline->last))->C;
330 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)(outline->last))->B;
331 next2.x = outline->last->dest.x - c.x;
332 next2.y = outline->last->dest.y - c.y;
333 if(next2.x==0 && next2.y==0) {
334 next2.x = outline->last->dest.x - b.x;
335 next2.y = outline->last->dest.y - b.y;
337 if(next2.x==0 && next2.y==0) {
338 next2.x = outline->last->dest.x;
339 next2.y = outline->last->dest.y;
345 if(outline->type == T1_PATHTYPE_LINE) {
346 next = outline->dest;
348 T1_PATHPOINT c = ((T1_BEZIERSEGMENT*)outline)->C;
349 T1_PATHPOINT b = ((T1_BEZIERSEGMENT*)outline)->B;
350 next.x = outline->dest.x - c.x;
351 next.y = outline->dest.y - c.y;
352 if(next.x==0 && next.y==0) {
353 next.x = outline->dest.x - b.x;
354 next.y = outline->dest.y - b.y;
356 if(next.x==0 && next.y==0) {
357 next.x = outline->dest.x;
358 next.y = outline->dest.y;
362 if(trytwo && outline->link && outline->link->type != T1_PATHTYPE_MOVE) {
363 if(outline->type == T1_PATHTYPE_LINE) {
364 next2 = outline->link->dest;
366 next2 = ((T1_BEZIERSEGMENT*)(outline->link))->B;
367 if(next2.x==0 && next2.y==0) {
368 next2 = ((T1_BEZIERSEGMENT*)outline->link)->C;
370 if(next2.x==0 && next2.y==0) {
371 next2 = ((T1_BEZIERSEGMENT*)outline->link)->dest;
379 xv = next.y/(float)0xffff;
380 yv = -next.x/(float)0xffff;
382 xv = -next.y/(float)0xffff;
383 yv = next.x/(float)0xffff;
386 double r = (line_width/2)/sqrt(xv*xv+yv*yv);
392 xv2 = next2.y/(float)0xffff;
393 yv2 = -next2.x/(float)0xffff;
395 xv2 = -next2.y/(float)0xffff;
396 yv2 = next2.x/(float)0xffff;
399 double r2 = (line_width/2)/sqrt(xv2*xv2+yv2*yv2);
404 double r3 = (line_width/2)/sqrt(xv*xv+yv*yv);
414 void drawShortPath(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline)
416 double lastx=x, lasty=y;
417 while (outline && outline->type != T1_PATHTYPE_MOVE)
419 x += (outline->dest.x/(float)0xffff);
420 y += (outline->dest.y/(float)0xffff);
422 if(outline->type == T1_PATHTYPE_LINE)
429 line(tag, p0, p1, m);
431 else if(outline->type == T1_PATHTYPE_BEZIER)
434 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
437 p1.x=o2->C.x/(float)0xffff+lastx;
438 p1.y=o2->C.y/(float)0xffff+lasty;
439 p2.x=o2->B.x/(float)0xffff+lastx;
440 p2.y=o2->B.y/(float)0xffff+lasty;
443 spline(tag,p0,p1,p2,p3,m);
447 outline = outline->link;
451 void drawShortPathWithEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
456 if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
459 T1_OUTLINE *last, *tmp=outline;
460 plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
466 while(tmp && tmp->type != T1_PATHTYPE_MOVE) {
468 lx += (tmp->dest.x/(float)0xffff);
469 ly += (tmp->dest.y/(float)0xffff);
472 s = getPivot(outline, 0, line_width, 0, 0);
473 e = getPivot(last, 0, line_width, 1, 0);
475 if(line_cap == LINE_CAP_BUTT) {
476 /* make the clipping rectangle slighly bigger
477 than the line ending, so that it get's clipped
487 p2.x = x2 - s.y - s.x*ee;
488 p2.y = y2 + s.x - s.y*ee;
489 p3.x = x2 - s.y + s.x*ee;
490 p3.y = y2 + s.x + s.y*ee;
495 m2.x = lx + e.y - e.x*ee;
496 m2.y = ly - e.x - e.y*ee;
497 m3.x = lx + e.y + e.x*ee;
498 m3.y = ly - e.x + e.y*ee;
500 for(nr=0;nr<2;nr++) {
502 struct plotxy q0,q1,q2,q3,q4,q5;
504 if(line_cap == LINE_CAP_BUTT) {
507 q1.x = sizex; q1.y = 0;
508 q2.x = sizex; q2.y = sizey;
509 q3.x = 0; q3.y = sizey;
511 q0.x = sizex; q0.y = sizey;
512 q1.x = 0; q1.y = sizey;
514 q3.x = sizex; q3.y = 0;
528 line(tag, p0, p1, m);
529 line(tag, p1, p2, m);
530 line(tag, p2, p3, m);
531 line(tag, p3, p0, m);
533 if(line_cap == LINE_CAP_BUTT) {
535 swf_ShapeSetEnd(tag);
536 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
537 swf_ObjectPlaceClip(tag,shapeid,depth,NULL,NULL,NULL,depth+2-nr);
551 drawShortPath(output,x,y,m,outline);
553 if(line_cap == LINE_CAP_BUTT) {
559 void drawT1toRect(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
561 plotxy d1,d2,p1,p2,p3,p4;
563 d1.x = (outline->dest.x/(float)0xffff);
564 d1.y = (outline->dest.y/(float)0xffff);
565 d2 = getPivot(outline, 0, line_width, 0, 0);
567 assert(line_cap != LINE_CAP_ROUND);
568 if(line_cap == LINE_CAP_SQUARE) {
577 p2.x = x + d2.x + d1.x;
578 p2.y = y + d2.y + d1.y;
579 p3.x = x - d2.x + d1.x;
580 p3.y = y - d2.y + d1.y;
590 void drawShortPathWithStraightEnds(struct swfoutput*output, double x, double y, struct swfmatrix* m, T1_OUTLINE*outline, int num, int line_cap, int line_join, double line_width)
592 T1_OUTLINE*tmp=outline;
598 drawT1toRect(output, x, y, m,outline, num, line_cap, line_join, line_width);
600 while(tmp->link && tmp->link->type!=T1_PATHTYPE_MOVE) {
601 xx += (tmp->dest.x/(float)0xffff);
602 yy += (tmp->dest.y/(float)0xffff);
606 assert(tmp->type == T1_PATHTYPE_LINE);
607 assert(outline->type == T1_PATHTYPE_LINE);
611 if(outline->link == tmp) {
612 /* the two straight line segments (which are everything we
613 need to draw) are very likely to overlap. To avoid that
614 they cancel each other out at the end points, start a new
615 shape for the second one */
616 endshape();startshape(output);
620 drawT1toRect(output, xx, yy, m, tmp, num, line_cap, line_join, line_width);
622 if(outline->link != tmp)
626 tmp->type = T1_PATHTYPE_MOVE;
627 x += (outline->dest.x/(float)0xffff);
628 y += (outline->dest.y/(float)0xffff);
629 outline = outline->link;
630 drawShortPath(output, x, y, m, outline);
638 static int t1len(T1_OUTLINE*line)
641 while(line && line->type != T1_PATHTYPE_MOVE) {
648 static float t1linelen(T1_OUTLINE*line)
651 x = (line->dest.x/(float)0xffff);
652 y = (line->dest.y/(float)0xffff);
653 return sqrt(x*x+y*y);
656 void drawpath2poly(struct swfoutput *output, T1_OUTLINE*outline, struct swfmatrix*m, int log, int line_join, int line_cap, double line_width, double miter_limit)
658 if(tag->id != ST_DEFINEFONT &&
659 tag->id != ST_DEFINESHAPE &&
660 tag->id != ST_DEFINESHAPE2 &&
661 tag->id != ST_DEFINESHAPE3) {
662 msg("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
667 double lastx=0,lasty=0;
670 T1_OUTLINE*tmp = outline, *last = 0;
675 x += (tmp->dest.x/(float)0xffff);
676 y += (tmp->dest.y/(float)0xffff);
678 if(!tmp || tmp->type == T1_PATHTYPE_MOVE) {
680 if(last->type == T1_PATHTYPE_LINE && t1linelen(last)>line_width*2 &&
681 lastwasline && line_cap != LINE_CAP_ROUND)
682 drawShortPathWithStraightEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
684 drawShortPathWithEnds(output, lastx, lasty, m, last, valid, line_cap, line_join, line_width);
698 if(tmp && tmp->type == T1_PATHTYPE_LINE && t1linelen(tmp)>line_width*2)
704 tmp->link->last = tmp; // make sure list is properly linked in both directions
709 static inline int colorcompare(RGBA*a,RGBA*b)
721 static const int CHARDATAMAX = 1024;
729 } chardata[CHARDATAMAX];
732 static void putcharacters(TAG*tag)
737 color.r = chardata[0].color.r^255;
746 int charadvance[128];
749 int glyphbits=1; //TODO: can this be zero?
752 if(tag->id != ST_DEFINETEXT &&
753 tag->id != ST_DEFINETEXT2) {
754 msg("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
758 msg("<warning> putcharacters called with zero characters");
761 for(pass = 0; pass < 2; pass++)
771 advancebits++; // add sign bit
772 swf_SetU8(tag, glyphbits);
773 swf_SetU8(tag, advancebits);
776 for(t=0;t<=chardatapos;t++)
778 if(lastfontid != chardata[t].fontid ||
779 lastx!=chardata[t].x ||
780 lasty!=chardata[t].y ||
781 !colorcompare(&color, &chardata[t].color) ||
783 lastsize != chardata[t].size ||
786 if(charstorepos && pass==0)
789 for(s=0;s<charstorepos;s++)
791 while(charids[s]>=(1<<glyphbits))
793 while(charadvance[s]>=(1<<advancebits))
797 if(charstorepos && pass==1)
799 tag->writeBit = 0; // Q&D
800 swf_SetBits(tag, 0, 1); // GLYPH Record
801 swf_SetBits(tag, charstorepos, 7); // number of glyphs
803 for(s=0;s<charstorepos;s++)
805 swf_SetBits(tag, charids[s], glyphbits);
806 swf_SetBits(tag, charadvance[s], advancebits);
811 if(pass == 1 && t<chardatapos)
817 if(lastx != chardata[t].x ||
818 lasty != chardata[t].y)
820 newx = chardata[t].x;
821 newy = chardata[t].y;
827 if(!colorcompare(&color, &chardata[t].color))
829 color = chardata[t].color;
832 font.id = chardata[t].fontid;
833 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
836 tag->writeBit = 0; // Q&D
837 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
840 lastfontid = chardata[t].fontid;
841 lastx = chardata[t].x;
842 lasty = chardata[t].y;
843 lastsize = chardata[t].size;
850 int nextt = t==chardatapos-1?t:t+1;
851 int rel = chardata[nextt].x-chardata[t].x;
852 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
854 lastx=chardata[nextt].x;
860 charids[charstorepos] = chardata[t].charid;
861 charadvance[charstorepos] = advance;
868 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
869 int x,int y, int size)
871 if(chardatapos == CHARDATAMAX)
876 chardata[chardatapos].fontid = fontid;
877 chardata[chardatapos].charid = charid;
878 chardata[chardatapos].x = x;
879 chardata[chardatapos].y = y;
880 chardata[chardatapos].color = obj->fillrgb;
881 chardata[chardatapos].size = size;
886 /* process a character. */
887 static void drawchar(struct swfoutput*obj, SWFFont*font, SWFFONT *swffont, char*character, int charnr, swfmatrix*m, Unicode u)
890 if(m->m12!=0 || m->m21!=0)
896 msg("<warning> Font is NULL");
899 //if(usefonts && ! drawonlyshapes)
902 int charid = font->getSWFCharID(character, charnr);
903 printf("charID %d, character %s\n", charid, character);
906 charid = getCharID(swffont, charnr, character, u);
910 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
911 FIXNULL(character),charnr, FIXNULL(font->getName()));
919 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
920 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
924 T1_OUTLINE*outline = font->getOutline(character, charnr);
925 char* charname = character;
928 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
929 FIXNULL(character),charnr,FIXNULL(font->getName()));
948 drawpath(tag, outline, &m2, 0);
953 /* draw a curved polygon. */
954 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
960 /* Multiple polygons in one shape don't overlap correctly,
961 so we better start a new shape here if the polygon is filled
963 if(shapeid>=0 && fill && !ignoredraworder) {
975 drawpath(tag, outline,m, 0);
978 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
988 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
991 /* SWFFont: copy all t1 font outlines to a local
993 SWFFont::SWFFont(char*name, int id, char*filename)
995 if(!T1_GetFontName(id))
998 this->name = strdup(T1_GetFontFileName(id));
999 this->fontid = strdup(name);
1002 char**charnamebase= T1_GetAllCharNames(id);
1003 char**a= charnamebase;
1004 int t, outlinepos=0;
1017 this->standardtablesize = 0;
1019 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
1021 this->standardtablesize = 256;
1022 if(this->charnum < this->standardtablesize)
1023 this->standardtablesize = this->charnum;
1024 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1026 for(t = 0; t < this->standardtablesize; t++) {
1027 char*name = T1_GetCharName(id,t);
1030 if(!name || !strstr(name, "notdef")) {
1031 if(t<standardEncodingSize) {
1032 name = standardEncodingNames[t];
1035 name = ""; //TODO: store something like <%d>
1038 standardtable[t] = strdup(name);
1039 msg("<debug> Char %d is named %s\n", t, name);
1042 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1043 charname = (char**)malloc(charnum*sizeof(char*));
1044 width = (int*)malloc(charnum*sizeof(int));
1045 memset(width, 0, charnum*sizeof(int));
1046 memset(charname, 0, charnum*sizeof(char*));
1047 used = (char*)malloc(charnum*sizeof(char));
1048 char2swfcharid = (U16*)malloc(charnum*2);
1049 swfcharid2char = (U16*)malloc(charnum*2);
1052 memset(used,0,charnum*sizeof(char));
1054 this->swfid = ++currentswfid;
1059 map[t] = strdup(*a);
1067 int ret = T1_ReencodeFont(id, map);
1071 int ret = T1_ReencodeFont(id, map);
1073 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1074 /* Deleting the font invalidates the charname array,
1075 so we have to ask for it again now.
1076 We continue at the position we were, hoping the font
1077 didn't shrink in the meantime or something.
1079 a = T1_GetAllCharNames(id) + (a - charnamebase);
1085 char* name = T1_GetCharName(id, s);
1086 if(!name) name = "";
1087 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1088 this->width[outlinepos] = T1_GetCharWidth(id, s);
1089 this->charname[outlinepos] = strdup(name);
1100 /* free all tables, write out definefont tags */
1106 if(storeallcharacters)
1109 for(t=0;t<this->charnum;t++)
1111 if(this->charname[t])
1112 getSWFCharID(this->charname[t], -1);
1116 ptr = (int*)malloc(swfcharpos*sizeof(int));
1118 for(t=0;t<charnum;t++)
1119 if(used[t]) usednum++;
1121 if(usednum && !drawonlyshapes)
1123 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1124 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1125 swf_SetU16(ftag, this->swfid);
1126 int initpos = swf_GetTagLen(ftag);
1133 for(t=0;t<swfcharpos;t++)
1135 ptr[t] = swf_GetTagLen(ftag);
1136 swf_SetU16(ftag, 0x1234);
1138 for(t=0;t<swfcharpos;t++)
1140 *(U16*)&ftag->data[ptr[t]] =
1141 SWAP16(swf_GetTagLen(ftag)-initpos);
1145 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1149 swf_ShapeSetStyle(ftag,&s,0,1,0);
1150 fillstylechanged = 1;
1151 int lastfill = fill;
1154 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1157 swf_ShapeSetEnd(ftag);
1159 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1160 swf_SetU16(ftag, this->swfid);
1162 swf_SetU8(ftag, strlen(this->fontid));
1163 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1167 swf_SetU8(ftag, 0); //flags
1168 for(t=0;t<swfcharpos;t++)
1171 char * name = this->charname[this->swfcharid2char[t]];
1172 for(s=0;s<256;s++) {
1173 if(standardEncodingNames[s] &&
1174 !strcmp(name,standardEncodingNames[s]))
1177 swf_SetU8(ftag, (U8)s);
1184 for(t=0;t<charnum;t++)
1186 for(t=0;t<standardtablesize;t++)
1187 if(standardtable[t]) {
1188 free(standardtable[t]);
1190 free(standardtable);
1194 free(swfcharid2char);
1195 free(char2swfcharid);
1198 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1201 for(t=0;t<this->charnum;t++) {
1202 if(!strcmp(this->charname[t],name)) {
1207 /* if we didn't find the character, maybe
1208 we can find the capitalized version */
1209 for(t=0;t<this->charnum;t++) {
1210 if(!strcasecmp(this->charname[t],name))
1214 /* if we didn't find it by name, use the names of the first 256 characters
1215 of the font to try a new name based on charnr */
1216 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1217 T1_OUTLINE*ret = getOutline(this->standardtable[charnr], -1);
1224 int SWFFont::getSWFCharID(char*name, int charnr)
1227 for(t=0;t<this->charnum;t++) {
1228 if(!strcmp(this->charname[t],name)) {
1231 swfcharid2char[swfcharpos] = t;
1232 char2swfcharid[t] = swfcharpos++;
1235 return char2swfcharid[t];
1239 /* if we didn't find the character, maybe
1240 we can find the capitalized version */
1241 for(t=0;t<this->charnum;t++) {
1242 if(!strcasecmp(this->charname[t],name)) {
1245 swfcharid2char[swfcharpos] = t;
1246 char2swfcharid[t] = swfcharpos++;
1249 return char2swfcharid[t];
1253 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1254 of the font to try a new name based on charnr */
1255 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1256 int ret = getSWFCharID(this->standardtable[charnr], -1);
1262 int getCharID(SWFFONT *font, int charnr, char *charname, Unicode u)
1265 for(t=0;t<font->numchars;t++) {
1266 if(!strcmp(font->glyphnames[t],charname)) {
1271 /* if we didn't find the character, maybe
1272 we can find the capitalized version */
1273 for(t=0;t<font->numchars;t++) {
1274 if(!strcasecmp(font->glyphnames[t],charname)) {
1279 /* try to use the unicode id */
1280 for(t=0;t<font->numchars;t++) {
1281 if(font->ascii2glyph[t] == u) {
1289 int SWFFont::getWidth(char*name)
1292 for(t=0;t<this->charnum;t++) {
1293 if(!strcmp(this->charname[t],name)) {
1294 return this->width[t];
1300 char*SWFFont::getName()
1312 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1313 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1315 static int currentswfid = 0;
1319 fontlist_t*last=0,*iterator;
1320 if(obj->swffont && (obj->swffont->id == atoi(fontid)))
1323 iterator = fontlist;
1325 if(iterator->swffont->id == atoi(fontid))
1328 iterator = iterator->next;
1332 obj->swffont = iterator->swffont;
1337 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1340 SWFFONT *swffont = swf_LoadFont(filename);
1341 swf_FontSetID(swffont, atoi(fontid));
1342 iterator = new fontlist_t;
1343 iterator->swffont = swffont;
1347 last->next = iterator;
1349 fontlist = iterator;
1350 obj->swffont = swffont;
1353 fontlist_t*last=0,*iterator;
1354 if(obj->font && !strcmp(obj->font->fontid,fontid))
1357 iterator = fontlist;
1359 if(!strcmp(iterator->font->fontid,fontid))
1362 iterator = iterator->next;
1366 obj->font = iterator->font;
1367 obj->swffont = iterator->swffont;
1372 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1375 SWFFont*font = new SWFFont(fontid, t1id, filename);
1377 //load swffont and print font information
1378 SWFFONT *swffont = swf_LoadFont(filename);
1379 swf_FontSetID(swffont, ++currentswfid);
1380 // print font information
1382 printf("\n----------------------SWF Font Information:\n");
1383 printf("ID:%d\n", swffont->id);
1384 printf("Version:%d\n", swffont->version);
1385 printf("Name:%s\n", swffont->name);
1386 printf("Numchars:%d\n", swffont->numchars);
1387 printf("Maxascii:%d\n", swffont->maxascii);
1388 printf("Style:%d\n", swffont->style);
1389 printf("Encoding:%d\n", swffont->encoding);
1390 for(int iii=0; iii<swffont->numchars;iii++)
1392 printf("Glyphname, glyph2ascii, ascii2glyph %d:%s, %d, %d\n", iii, swffont->glyphnames[iii], swffont->glyph2ascii[iii], swffont->ascii2glyph[iii]);
1394 printf("\n----------------------SWF Font Information End.\n");
1396 iterator = new fontlist_t;
1397 iterator->font = font;
1398 iterator->swffont = swffont;
1402 last->next = iterator;
1404 fontlist = iterator;
1406 obj->swffont = swffont;
1410 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1414 fontlist_t *iterator = fontlist;
1416 if(iterator->swffont->id == atoi(fontid))
1418 iterator = iterator->next;
1423 fontlist_t *iterator = fontlist;
1425 if(!strcmp(iterator->font->fontid,fontid))
1427 iterator = iterator->next;
1433 /* set's the matrix which is to be applied to characters drawn by
1434 swfoutput_drawchar() */
1435 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1436 double m21,double m22)
1438 if(obj->fontm11 == m11 &&
1439 obj->fontm12 == m12 &&
1440 obj->fontm21 == m21 &&
1441 obj->fontm22 == m22)
1451 /* draws a character at x,y. */
1452 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr, Unicode u)
1455 m.m11 = obj->fontm11;
1456 m.m12 = obj->fontm12;
1457 m.m21 = obj->fontm21;
1458 m.m22 = obj->fontm22;
1461 drawchar(obj, obj->font, obj->swffont, character, charnr, &m, u);
1464 /* initialize the swf writer */
1465 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1470 memset(obj, 0, sizeof(struct swfoutput));
1471 filename = _filename;
1475 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1479 memset(&swf,0x00,sizeof(SWF));
1481 swf.fileVersion = flashversion;
1482 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1483 swf.movieSize.xmin = 20*x1;
1484 swf.movieSize.ymin = 20*y1;
1485 swf.movieSize.xmax = 20*x2;
1486 swf.movieSize.ymax = 20*y2;
1490 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1492 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1493 swf_SetRGB(tag,&rgb);
1495 if(1)/* add white rectangle */
1500 int shapeid = ++currentswfid;
1505 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1507 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1508 swf_SetU16(tag,shapeid);
1509 swf_SetRect(tag,&r);
1510 swf_SetShapeHeader(tag,s);
1511 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1512 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1513 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1514 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1515 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1516 swf_ShapeSetEnd(tag);
1518 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1519 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1520 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1521 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1525 tag = swf_InsertTag(tag, ST_PROTECT);
1530 void swfoutput_setprotected() //write PROTECT tag
1535 static void startshape(struct swfoutput*obj)
1543 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1545 swf_ShapeNew(&shape);
1546 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1547 rgb.r = obj->fillrgb.r;
1548 rgb.g = obj->fillrgb.g;
1549 rgb.b = obj->fillrgb.b;
1550 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1552 shapeid = ++currentswfid;
1553 swf_SetU16(tag,shapeid); // ID
1560 swf_SetRect(tag,&r);
1562 swf_SetShapeStyles(tag,shape);
1563 swf_ShapeCountBits(shape,NULL,NULL);
1564 swf_SetShapeBits(tag,shape);
1566 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1567 swflastx=swflasty=0;
1571 static void starttext(struct swfoutput*obj)
1577 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1578 textid = ++currentswfid;
1579 swf_SetU16(tag, textid);
1586 swf_SetRect(tag,&r);
1595 swf_SetMatrix(tag,&m);
1596 swflastx=swflasty=0;
1599 static void endshape()
1603 swf_ShapeSetEnd(tag);
1604 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1605 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1609 static void endtext()
1615 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1616 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1620 static void endpage(struct swfoutput*obj)
1627 swfoutput_endclip(obj);
1631 atag = action_Stop(atag);
1632 atag = action_End(atag);
1633 tag = swf_InsertTag(tag,ST_DOACTION);
1634 swf_ActionSet(tag,atag);
1636 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1639 void swfoutput_newpage(struct swfoutput*obj)
1643 for(depth--;depth>=startdepth;depth--) {
1644 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1645 swf_SetU16(tag,depth);
1651 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1652 up, complete the swf, and write it out. */
1653 void swfoutput_destroy(struct swfoutput* obj)
1656 fontlist_t *tmp,*iterator = fontlist;
1658 delete iterator->font;
1661 iterator = iterator->next;
1669 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1674 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1678 tag = swf_InsertTag(tag,ST_END);
1681 if FAILED(swf_WriteSWC(fi,&swf))
1682 msg("<error> WriteSWC() failed.\n");
1684 if FAILED(swf_WriteSWF(fi,&swf))
1685 msg("<error> WriteSWF() failed.\n");
1690 msg("<notice> SWF written\n");
1693 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1696 if(mode == DRAWMODE_FILL)
1698 else if(mode == DRAWMODE_EOFILL)
1700 else if(mode == DRAWMODE_STROKE)
1702 else if(mode == DRAWMODE_CLIP)
1704 else if(mode == DRAWMODE_EOCLIP)
1708 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1710 if(obj->fillrgb.r == r &&
1711 obj->fillrgb.g == g &&
1712 obj->fillrgb.b == b &&
1713 obj->fillrgb.a == a) return;
1723 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1725 if(obj->strokergb.r == r &&
1726 obj->strokergb.g == g &&
1727 obj->strokergb.b == b &&
1728 obj->strokergb.a == a) return;
1732 obj->strokergb.r = r;
1733 obj->strokergb.g = g;
1734 obj->strokergb.b = b;
1735 obj->strokergb.a = a;
1738 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1740 if(obj->linewidth == (u16)(linewidth*20))
1745 obj->linewidth = (u16)(linewidth*20);
1749 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1758 msg("<warning> Too many clip levels.");
1763 int olddrawmode = drawmode;
1764 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1765 swfoutput_drawpath(obj, outline, m);
1766 swf_ShapeSetEnd(tag);
1767 swfoutput_setdrawmode(obj, olddrawmode);
1769 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1770 cliptags[clippos] = tag;
1771 clipshapes[clippos] = shapeid;
1772 clipdepths[clippos] = depth++;
1777 void swfoutput_endclip(swfoutput*obj)
1785 msg("<error> Invalid end of clipping region");
1789 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1792 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1794 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1797 if(!strncmp("http://pdf2swf:", url, 15)) {
1798 char*tmp = strdup(url);
1799 int l = strlen(tmp);
1802 swfoutput_namedlink(obj, tmp+15, points);
1813 actions = action_GetUrl(0, url, "_parent");
1815 actions = action_GetUrl(0, url, "_this");
1816 actions = action_End(actions);
1818 drawlink(obj, actions, 0, points,0);
1820 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1829 actions = action_GotoFrame(0, page);
1830 actions = action_End(actions);
1832 drawlink(obj, actions, 0, points,0);
1835 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1836 of the viewer objects, like subtitles, index elements etc.
1838 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1840 ActionTAG *actions1,*actions2;
1841 char*tmp = strdup(name);
1849 if(!strncmp(tmp, "call:", 5))
1851 char*x = strchr(&tmp[5], ':');
1853 actions1 = action_PushInt(0, 0); //number of parameters (0)
1854 actions1 = action_PushString(actions1, &tmp[5]); //function name
1855 actions1 = action_CallFunction(actions1);
1858 actions1 = action_PushString(0, x+1); //parameter
1859 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1860 actions1 = action_PushString(actions1, &tmp[5]); //function name
1861 actions1 = action_CallFunction(actions1);
1863 actions2 = action_End(0);
1868 actions1 = action_PushString(0, "/:subtitle");
1869 actions1 = action_PushString(actions1, name);
1870 actions1 = action_SetVariable(actions1);
1871 actions1 = action_End(actions1);
1873 actions2 = action_PushString(0, "/:subtitle");
1874 actions2 = action_PushString(actions2, "");
1875 actions2 = action_SetVariable(actions2);
1876 actions2 = action_End(actions2);
1879 drawlink(obj, actions1, actions2, points,mouseover);
1881 swf_ActionFree(actions1);
1882 swf_ActionFree(actions2);
1886 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1892 struct plotxy p1,p2,p3,p4;
1896 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1900 int buttonid = ++currentswfid;
1903 if(points[t].x>xmax) xmax=points[t].x;
1904 if(points[t].y>ymax) ymax=points[t].y;
1905 if(points[t].x<xmin) xmin=points[t].x;
1906 if(points[t].y<ymin) ymin=points[t].y;
1909 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1910 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1912 /* the following code subtracts the upper left edge from all coordinates,
1913 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1914 Necessary for preprocessing with swfcombine. */
1915 posx = xmin; posy = ymin;
1916 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1917 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1918 xmin -= posx; ymin -= posy;
1919 xmax -= posx; ymax -= posy;
1922 myshapeid = ++currentswfid;
1923 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1924 swf_ShapeNew(&shape);
1925 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1926 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1927 swf_SetU16(tag, myshapeid);
1928 r.xmin = (int)(xmin*20);
1929 r.ymin = (int)(ymin*20);
1930 r.xmax = (int)(xmax*20);
1931 r.ymax = (int)(ymax*20);
1932 swf_SetRect(tag,&r);
1933 swf_SetShapeStyles(tag,shape);
1934 swf_ShapeCountBits(shape,NULL,NULL);
1935 swf_SetShapeBits(tag,shape);
1936 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1937 swflastx = swflasty = 0;
1943 swf_ShapeSetEnd(tag);
1946 myshapeid2 = ++currentswfid;
1947 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1948 swf_ShapeNew(&shape);
1949 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1951 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1952 swf_SetU16(tag, myshapeid2);
1953 r.xmin = (int)(xmin*20);
1954 r.ymin = (int)(ymin*20);
1955 r.xmax = (int)(xmax*20);
1956 r.ymax = (int)(ymax*20);
1957 swf_SetRect(tag,&r);
1958 swf_SetShapeStyles(tag,shape);
1959 swf_ShapeCountBits(shape,NULL,NULL);
1960 swf_SetShapeBits(tag,shape);
1961 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1962 swflastx = swflasty = 0;
1968 swf_ShapeSetEnd(tag);
1972 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1973 swf_SetU16(tag,buttonid); //id
1974 swf_ButtonSetFlags(tag, 0); //menu=no
1975 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1976 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1977 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1978 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1980 swf_ActionSet(tag,actions1);
1985 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1986 swf_SetU16(tag,buttonid); //id
1987 swf_ButtonSetFlags(tag, 0); //menu=no
1988 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1989 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1990 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1991 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1992 swf_SetU8(tag,0); // end of button records
1993 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1994 swf_ActionSet(tag,actions1);
1996 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1997 swf_ActionSet(tag,actions2);
1999 swf_ButtonPostProcess(tag, 2);
2002 swf_ButtonPostProcess(tag, 1);
2006 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
2008 if(posx!=0 || posy!=0) {
2010 swf_GetMatrix(0,&m);
2011 m.tx = (int)(posx*20);
2012 m.ty = (int)(posy*20);
2013 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
2016 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
2020 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
2021 double x1,double y1,
2022 double x2,double y2,
2023 double x3,double y3,
2024 double x4,double y4)
2030 struct plotxy p1,p2,p3,p4;
2032 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
2033 if(x2>xmax) xmax=x2;
2034 if(y2>ymax) ymax=y2;
2035 if(x2<xmin) xmin=x2;
2036 if(y2<ymin) ymin=y2;
2037 if(x3>xmax) xmax=x3;
2038 if(y3>ymax) ymax=y3;
2039 if(x3<xmin) xmin=x3;
2040 if(y3<ymin) ymin=y3;
2041 if(x4>xmax) xmax=x4;
2042 if(y4>ymax) ymax=y4;
2043 if(x4<xmin) xmin=x4;
2044 if(y4<ymin) ymin=y4;
2050 {p1.x = (int)(p1.x*20)/20.0;
2051 p1.y = (int)(p1.y*20)/20.0;
2052 p2.x = (int)(p2.x*20)/20.0;
2053 p2.y = (int)(p2.y*20)/20.0;
2054 p3.x = (int)(p3.x*20)/20.0;
2055 p3.y = (int)(p3.y*20)/20.0;
2056 p4.x = (int)(p4.x*20)/20.0;
2057 p4.y = (int)(p4.y*20)/20.0;}
2060 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
2061 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
2062 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
2063 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
2065 m.tx = (int)(p1.x*20);
2066 m.ty = (int)(p1.y*20);
2069 myshapeid = ++currentswfid;
2070 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
2071 swf_ShapeNew(&shape);
2072 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
2073 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
2074 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
2075 swf_SetU16(tag, myshapeid);
2076 r.xmin = (int)(xmin*20);
2077 r.ymin = (int)(ymin*20);
2078 r.xmax = (int)(xmax*20);
2079 r.ymax = (int)(ymax*20);
2080 swf_SetRect(tag,&r);
2081 swf_SetShapeStyles(tag,shape);
2082 swf_ShapeCountBits(shape,NULL,NULL);
2083 swf_SetShapeBits(tag,shape);
2084 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
2085 swflastx = swflasty = 0;
2092 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
2093 ShapeSetLine (tag, shape, (int)(x1*20);
2094 ShapeSetLine (tag, shape, x*20,0);
2095 ShapeSetLine (tag, shape, 0,-y*20);
2096 ShapeSetLine (tag, shape, -x*20,0);*/
2097 swf_ShapeSetEnd(tag);
2100 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
2101 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
2104 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
2105 double x1,double y1,
2106 double x2,double y2,
2107 double x3,double y3,
2108 double x4,double y4)
2116 int bitid = ++currentswfid;
2118 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2119 swf_SetU16(tag, bitid);
2120 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
2126 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2130 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2131 double x1,double y1,
2132 double x2,double y2,
2133 double x3,double y3,
2134 double x4,double y4)
2144 int bitid = ++currentswfid;
2146 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2147 swf_SetU16(tag, bitid);
2148 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2149 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2153 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2154 double x1,double y1,
2155 double x2,double y2,
2156 double x3,double y3,
2157 double x4,double y4)
2165 int bitid = ++currentswfid;
2167 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2168 swf_SetU16(tag, bitid);
2169 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2175 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2179 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2180 double x1,double y1,
2181 double x2,double y2,
2182 double x3,double y3,
2183 double x4,double y4, int n)
2194 /* SWF expects scanlines to be 4 byte aligned */
2197 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2199 for(y=0;y<sizey;y++)
2201 for(x=0;x<sizex;x++)
2202 *ptr++ = mem[y*sizex+x];
2203 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2208 int bitid = ++currentswfid;
2210 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2211 swf_SetU16(tag, bitid);
2212 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2220 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2224 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2225 double x1,double y1,
2226 double x2,double y2,
2227 double x3,double y3,
2228 double x4,double y4)
2236 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);