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, char*character, int charnr, swfmatrix*m)
890 if(m->m12!=0 || m->m21!=0)
896 msg("<warning> Font is NULL");
899 if(usefonts && ! drawonlyshapes)
901 int charid = font->getSWFCharID(character, charnr);
903 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
904 FIXNULL(character),charnr, FIXNULL(font->getName()));
911 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
912 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
916 T1_OUTLINE*outline = font->getOutline(character, charnr);
917 char* charname = character;
920 msg("<warning> Didn't find character '%s' (%d) in current charset (%s)",
921 FIXNULL(character),charnr,FIXNULL(font->getName()));
940 drawpath(tag, outline, &m2, 0);
945 /* draw a curved polygon. */
946 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
952 /* Multiple polygons in one shape don't overlap correctly,
953 so we better start a new shape here if the polygon is filled
955 if(shapeid>=0 && fill && !ignoredraworder) {
967 drawpath(tag, outline,m, 0);
970 void swfoutput_drawpath2poly(struct swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m, int line_join, int line_cap, double line_width, double miter_limit)
980 drawpath2poly(output, outline, m, 0, line_join, line_cap, line_width, miter_limit);
983 /* SWFFont: copy all t1 font outlines to a local
985 SWFFont::SWFFont(char*name, int id, char*filename)
987 if(!T1_GetFontName(id))
990 this->name = strdup(T1_GetFontFileName(id));
991 this->fontid = strdup(name);
994 char**charnamebase= T1_GetAllCharNames(id);
995 char**a= charnamebase;
1009 this->standardtablesize = 0;
1011 msg("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
1013 this->standardtablesize = 256;
1014 if(this->charnum < this->standardtablesize)
1015 this->standardtablesize = this->charnum;
1016 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
1018 for(t = 0; t < this->standardtablesize; t++) {
1019 char*name = T1_GetCharName(id,t);
1022 if(!name || !strstr(name, "notdef")) {
1023 if(t<standardEncodingSize) {
1024 name = standardEncodingNames[t];
1027 name = ""; //TODO: store something like <%d>
1030 standardtable[t] = strdup(name);
1031 msg("<debug> Char %d is named %s\n", t, name);
1034 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
1035 charname = (char**)malloc(charnum*sizeof(char*));
1036 width = (int*)malloc(charnum*sizeof(int));
1037 memset(width, 0, charnum*sizeof(int));
1038 memset(charname, 0, charnum*sizeof(char*));
1039 used = (char*)malloc(charnum*sizeof(char));
1040 char2swfcharid = (U16*)malloc(charnum*2);
1041 swfcharid2char = (U16*)malloc(charnum*2);
1044 memset(used,0,charnum*sizeof(char));
1046 this->swfid = ++currentswfid;
1051 map[t] = strdup(*a);
1059 int ret = T1_ReencodeFont(id, map);
1063 int ret = T1_ReencodeFont(id, map);
1065 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
1066 /* Deleting the font invalidates the charname array,
1067 so we have to ask for it again now.
1068 We continue at the position we were, hoping the font
1069 didn't shrink in the meantime or something.
1071 a = T1_GetAllCharNames(id) + (a - charnamebase);
1077 char* name = T1_GetCharName(id, s);
1078 if(!name) name = "";
1079 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
1080 this->width[outlinepos] = T1_GetCharWidth(id, s);
1081 this->charname[outlinepos] = strdup(name);
1092 /* free all tables, write out definefont tags */
1098 if(storeallcharacters)
1101 for(t=0;t<this->charnum;t++)
1103 if(this->charname[t])
1104 getSWFCharID(this->charname[t], -1);
1108 ptr = (int*)malloc(swfcharpos*sizeof(int));
1110 for(t=0;t<charnum;t++)
1111 if(used[t]) usednum++;
1113 if(usednum && !drawonlyshapes)
1115 msg("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
1116 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
1117 swf_SetU16(ftag, this->swfid);
1118 int initpos = swf_GetTagLen(ftag);
1125 for(t=0;t<swfcharpos;t++)
1127 ptr[t] = swf_GetTagLen(ftag);
1128 swf_SetU16(ftag, 0x1234);
1130 for(t=0;t<swfcharpos;t++)
1132 *(U16*)&ftag->data[ptr[t]] =
1133 SWAP16(swf_GetTagLen(ftag)-initpos);
1137 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
1141 swf_ShapeSetStyle(ftag,&s,0,1,0);
1142 fillstylechanged = 1;
1143 int lastfill = fill;
1146 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
1149 swf_ShapeSetEnd(ftag);
1151 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
1152 swf_SetU16(ftag, this->swfid);
1154 swf_SetU8(ftag, strlen(this->fontid));
1155 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
1159 swf_SetU8(ftag, 0); //flags
1160 for(t=0;t<swfcharpos;t++)
1163 char * name = this->charname[this->swfcharid2char[t]];
1164 for(s=0;s<256;s++) {
1165 if(standardEncodingNames[s] &&
1166 !strcmp(name,standardEncodingNames[s]))
1169 swf_SetU8(ftag, (U8)s);
1176 for(t=0;t<charnum;t++)
1178 for(t=0;t<standardtablesize;t++)
1179 if(standardtable[t]) {
1180 free(standardtable[t]);
1182 free(standardtable);
1186 free(swfcharid2char);
1187 free(char2swfcharid);
1190 T1_OUTLINE*SWFFont::getOutline(char*name, int charnr)
1193 for(t=0;t<this->charnum;t++) {
1194 if(!strcmp(this->charname[t],name)) {
1199 /* if we didn't find the character, maybe
1200 we can find the capitalized version */
1201 for(t=0;t<this->charnum;t++) {
1202 if(!strcasecmp(this->charname[t],name))
1206 /* if we didn't find it by name, use the names of the first 256 characters
1207 of the font to try a new name based on charnr */
1208 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1209 T1_OUTLINE*ret = getOutline(this->standardtable[charnr], -1);
1216 int SWFFont::getSWFCharID(char*name, int charnr)
1219 for(t=0;t<this->charnum;t++) {
1220 if(!strcmp(this->charname[t],name)) {
1223 swfcharid2char[swfcharpos] = t;
1224 char2swfcharid[t] = swfcharpos++;
1227 return char2swfcharid[t];
1231 /* if we didn't find the character, maybe
1232 we can find the capitalized version */
1233 for(t=0;t<this->charnum;t++) {
1234 if(!strcasecmp(this->charname[t],name)) {
1237 swfcharid2char[swfcharpos] = t;
1238 char2swfcharid[t] = swfcharpos++;
1241 return char2swfcharid[t];
1245 /* if we didn't find it by name, use the names of the first 256 (or so) characters
1246 of the font to try a new name based on charnr */
1247 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
1248 int ret = getSWFCharID(this->standardtable[charnr], -1);
1254 int SWFFont::getWidth(char*name)
1257 for(t=0;t<this->charnum;t++) {
1258 if(!strcmp(this->charname[t],name)) {
1259 return this->width[t];
1265 char*SWFFont::getName()
1276 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
1277 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
1279 fontlist_t*last=0,*iterator;
1280 if(obj->font && !strcmp(obj->font->fontid,fontid))
1283 iterator = fontlist;
1285 if(!strcmp(iterator->font->fontid,fontid))
1288 iterator = iterator->next;
1292 obj->font = iterator->font;
1297 msg("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
1300 SWFFont*font = new SWFFont(fontid, t1id, filename);
1301 iterator = new fontlist_t;
1302 iterator->font = font;
1306 last->next = iterator;
1308 fontlist = iterator;
1312 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
1314 fontlist_t *iterator = fontlist;
1316 if(!strcmp(iterator->font->fontid,fontid))
1318 iterator = iterator->next;
1323 /* set's the matrix which is to be applied to characters drawn by
1324 swfoutput_drawchar() */
1325 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
1326 double m21,double m22)
1328 if(obj->fontm11 == m11 &&
1329 obj->fontm12 == m12 &&
1330 obj->fontm21 == m21 &&
1331 obj->fontm22 == m22)
1341 /* draws a character at x,y. */
1342 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
1345 m.m11 = obj->fontm11;
1346 m.m12 = obj->fontm12;
1347 m.m21 = obj->fontm21;
1348 m.m22 = obj->fontm22;
1351 drawchar(obj, obj->font, character, charnr, &m);
1354 /* initialize the swf writer */
1355 void swfoutput_init(struct swfoutput* obj, char*_filename, int x1, int y1, int x2, int y2)
1360 memset(obj, 0, sizeof(struct swfoutput));
1361 filename = _filename;
1365 msg("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
1369 memset(&swf,0x00,sizeof(SWF));
1371 swf.fileVersion = flashversion;
1372 swf.frameRate = 0x0040; // 1 frame per 4 seconds
1373 swf.movieSize.xmin = 20*x1;
1374 swf.movieSize.ymin = 20*y1;
1375 swf.movieSize.xmax = 20*x2;
1376 swf.movieSize.ymax = 20*y2;
1380 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
1382 rgb.a = rgb.r = rgb.g = rgb.b = 0xff;
1383 swf_SetRGB(tag,&rgb);
1385 if(1)/* add white rectangle */
1390 int shapeid = ++currentswfid;
1395 tag = swf_InsertTag(tag, ST_DEFINESHAPE);
1397 fs1 = swf_ShapeAddSolidFillStyle(s, &rgb);
1398 swf_SetU16(tag,shapeid);
1399 swf_SetRect(tag,&r);
1400 swf_SetShapeHeader(tag,s);
1401 swf_ShapeSetAll(tag,s,x1*20,y1*20,ls1,fs1,0);
1402 swf_ShapeSetLine(tag,s,20*(x2-x1),0);
1403 swf_ShapeSetLine(tag,s,0,20*(y2-y1));
1404 swf_ShapeSetLine(tag,s,20*(x1-x2),0);
1405 swf_ShapeSetLine(tag,s,0,20*(y1-y2));
1406 swf_ShapeSetEnd(tag);
1408 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1409 swf_ObjectPlace(tag,shapeid,depth++,0,0,0);
1410 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1411 swf_ObjectPlaceClip(tag,shapeid,depth++,0,0,0,65535);
1415 tag = swf_InsertTag(tag, ST_PROTECT);
1420 void swfoutput_setprotected() //write PROTECT tag
1425 static void startshape(struct swfoutput*obj)
1433 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1435 swf_ShapeNew(&shape);
1436 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1437 rgb.r = obj->fillrgb.r;
1438 rgb.g = obj->fillrgb.g;
1439 rgb.b = obj->fillrgb.b;
1440 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1442 shapeid = ++currentswfid;
1443 swf_SetU16(tag,shapeid); // ID
1450 swf_SetRect(tag,&r);
1452 swf_SetShapeStyles(tag,shape);
1453 swf_ShapeCountBits(shape,NULL,NULL);
1454 swf_SetShapeBits(tag,shape);
1456 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
1457 swflastx=swflasty=0;
1461 static void starttext(struct swfoutput*obj)
1467 tag = swf_InsertTag(tag,ST_DEFINETEXT);
1468 textid = ++currentswfid;
1469 swf_SetU16(tag, textid);
1476 swf_SetRect(tag,&r);
1485 swf_SetMatrix(tag,&m);
1486 swflastx=swflasty=0;
1489 static void endshape()
1493 swf_ShapeSetEnd(tag);
1494 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1495 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
1499 static void endtext()
1505 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1506 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
1510 static void endpage(struct swfoutput*obj)
1517 swfoutput_endclip(obj);
1521 atag = action_Stop(atag);
1522 atag = action_End(atag);
1523 tag = swf_InsertTag(tag,ST_DOACTION);
1524 swf_ActionSet(tag,atag);
1526 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1529 void swfoutput_newpage(struct swfoutput*obj)
1533 for(depth--;depth>=startdepth;depth--) {
1534 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1535 swf_SetU16(tag,depth);
1541 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1542 up, complete the swf, and write it out. */
1543 void swfoutput_destroy(struct swfoutput* obj)
1546 fontlist_t *tmp,*iterator = fontlist;
1548 delete iterator->font;
1551 iterator = iterator->next;
1559 fi = open(filename, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY, 0777);
1564 msg("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1568 tag = swf_InsertTag(tag,ST_END);
1571 if FAILED(swf_WriteSWC(fi,&swf))
1572 msg("<error> WriteSWC() failed.\n");
1574 if FAILED(swf_WriteSWF(fi,&swf))
1575 msg("<error> WriteSWF() failed.\n");
1580 msg("<notice> SWF written\n");
1583 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1586 if(mode == DRAWMODE_FILL)
1588 else if(mode == DRAWMODE_EOFILL)
1590 else if(mode == DRAWMODE_STROKE)
1592 else if(mode == DRAWMODE_CLIP)
1594 else if(mode == DRAWMODE_EOCLIP)
1598 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1600 if(obj->fillrgb.r == r &&
1601 obj->fillrgb.g == g &&
1602 obj->fillrgb.b == b &&
1603 obj->fillrgb.a == a) return;
1613 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1615 if(obj->strokergb.r == r &&
1616 obj->strokergb.g == g &&
1617 obj->strokergb.b == b &&
1618 obj->strokergb.a == a) return;
1622 obj->strokergb.r = r;
1623 obj->strokergb.g = g;
1624 obj->strokergb.b = b;
1625 obj->strokergb.a = a;
1628 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1630 if(obj->linewidth == (u16)(linewidth*20))
1635 obj->linewidth = (u16)(linewidth*20);
1639 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1648 msg("<warning> Too many clip levels.");
1653 int olddrawmode = drawmode;
1654 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1655 swfoutput_drawpath(obj, outline, m);
1656 swf_ShapeSetEnd(tag);
1657 swfoutput_setdrawmode(obj, olddrawmode);
1659 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1660 cliptags[clippos] = tag;
1661 clipshapes[clippos] = shapeid;
1662 clipdepths[clippos] = depth++;
1667 void swfoutput_endclip(swfoutput*obj)
1675 msg("<error> Invalid end of clipping region");
1679 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1682 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1684 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1687 if(!strncmp("http://pdf2swf:", url, 15)) {
1688 char*tmp = strdup(url);
1689 int l = strlen(tmp);
1692 swfoutput_namedlink(obj, tmp+15, points);
1703 actions = action_GetUrl(0, url, "_parent");
1705 actions = action_GetUrl(0, url, "_this");
1706 actions = action_End(actions);
1708 drawlink(obj, actions, 0, points,0);
1710 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1719 actions = action_GotoFrame(0, page);
1720 actions = action_End(actions);
1722 drawlink(obj, actions, 0, points,0);
1725 /* Named Links (a.k.a. Acrobatmenu) are used to implement various gadgets
1726 of the viewer objects, like subtitles, index elements etc.
1728 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1730 ActionTAG *actions1,*actions2;
1731 char*tmp = strdup(name);
1739 if(!strncmp(tmp, "call:", 5))
1741 char*x = strchr(&tmp[5], ':');
1743 actions1 = action_PushInt(0, 0); //number of parameters (0)
1744 actions1 = action_PushString(actions1, &tmp[5]); //function name
1745 actions1 = action_CallFunction(actions1);
1748 actions1 = action_PushString(0, x+1); //parameter
1749 actions1 = action_PushInt(actions1, 1); //number of parameters (1)
1750 actions1 = action_PushString(actions1, &tmp[5]); //function name
1751 actions1 = action_CallFunction(actions1);
1753 actions2 = action_End(0);
1758 actions1 = action_PushString(0, "/:subtitle");
1759 actions1 = action_PushString(actions1, name);
1760 actions1 = action_SetVariable(actions1);
1761 actions1 = action_End(actions1);
1763 actions2 = action_PushString(0, "/:subtitle");
1764 actions2 = action_PushString(actions2, "");
1765 actions2 = action_SetVariable(actions2);
1766 actions2 = action_End(actions2);
1769 drawlink(obj, actions1, actions2, points,mouseover);
1771 swf_ActionFree(actions1);
1772 swf_ActionFree(actions2);
1776 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1782 struct plotxy p1,p2,p3,p4;
1786 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1790 int buttonid = ++currentswfid;
1793 if(points[t].x>xmax) xmax=points[t].x;
1794 if(points[t].y>ymax) ymax=points[t].y;
1795 if(points[t].x<xmin) xmin=points[t].x;
1796 if(points[t].y<ymin) ymin=points[t].y;
1799 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1800 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1802 /* the following code subtracts the upper left edge from all coordinates,
1803 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1804 Necessary for preprocessing with swfcombine. */
1805 posx = xmin; posy = ymin;
1806 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1807 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1808 xmin -= posx; ymin -= posy;
1809 xmax -= posx; ymax -= posy;
1812 myshapeid = ++currentswfid;
1813 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1814 swf_ShapeNew(&shape);
1815 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1816 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1817 swf_SetU16(tag, myshapeid);
1818 r.xmin = (int)(xmin*20);
1819 r.ymin = (int)(ymin*20);
1820 r.xmax = (int)(xmax*20);
1821 r.ymax = (int)(ymax*20);
1822 swf_SetRect(tag,&r);
1823 swf_SetShapeStyles(tag,shape);
1824 swf_ShapeCountBits(shape,NULL,NULL);
1825 swf_SetShapeBits(tag,shape);
1826 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1827 swflastx = swflasty = 0;
1833 swf_ShapeSetEnd(tag);
1836 myshapeid2 = ++currentswfid;
1837 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1838 swf_ShapeNew(&shape);
1839 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1841 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1842 swf_SetU16(tag, myshapeid2);
1843 r.xmin = (int)(xmin*20);
1844 r.ymin = (int)(ymin*20);
1845 r.xmax = (int)(xmax*20);
1846 r.ymax = (int)(ymax*20);
1847 swf_SetRect(tag,&r);
1848 swf_SetShapeStyles(tag,shape);
1849 swf_ShapeCountBits(shape,NULL,NULL);
1850 swf_SetShapeBits(tag,shape);
1851 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1852 swflastx = swflasty = 0;
1858 swf_ShapeSetEnd(tag);
1862 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1863 swf_SetU16(tag,buttonid); //id
1864 swf_ButtonSetFlags(tag, 0); //menu=no
1865 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1866 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1867 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1868 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1870 swf_ActionSet(tag,actions1);
1875 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1876 swf_SetU16(tag,buttonid); //id
1877 swf_ButtonSetFlags(tag, 0); //menu=no
1878 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1879 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1880 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1881 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1882 swf_SetU8(tag,0); // end of button records
1883 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1884 swf_ActionSet(tag,actions1);
1886 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1887 swf_ActionSet(tag,actions2);
1889 swf_ButtonPostProcess(tag, 2);
1892 swf_ButtonPostProcess(tag, 1);
1896 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1898 if(posx!=0 || posy!=0) {
1900 swf_GetMatrix(0,&m);
1901 m.tx = (int)(posx*20);
1902 m.ty = (int)(posy*20);
1903 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1906 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1910 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1911 double x1,double y1,
1912 double x2,double y2,
1913 double x3,double y3,
1914 double x4,double y4)
1920 struct plotxy p1,p2,p3,p4;
1922 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1923 if(x2>xmax) xmax=x2;
1924 if(y2>ymax) ymax=y2;
1925 if(x2<xmin) xmin=x2;
1926 if(y2<ymin) ymin=y2;
1927 if(x3>xmax) xmax=x3;
1928 if(y3>ymax) ymax=y3;
1929 if(x3<xmin) xmin=x3;
1930 if(y3<ymin) ymin=y3;
1931 if(x4>xmax) xmax=x4;
1932 if(y4>ymax) ymax=y4;
1933 if(x4<xmin) xmin=x4;
1934 if(y4<ymin) ymin=y4;
1940 {p1.x = (int)(p1.x*20)/20.0;
1941 p1.y = (int)(p1.y*20)/20.0;
1942 p2.x = (int)(p2.x*20)/20.0;
1943 p2.y = (int)(p2.y*20)/20.0;
1944 p3.x = (int)(p3.x*20)/20.0;
1945 p3.y = (int)(p3.y*20)/20.0;
1946 p4.x = (int)(p4.x*20)/20.0;
1947 p4.y = (int)(p4.y*20)/20.0;}
1950 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1951 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1952 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1953 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1955 m.tx = (int)(p1.x*20);
1956 m.ty = (int)(p1.y*20);
1959 myshapeid = ++currentswfid;
1960 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1961 swf_ShapeNew(&shape);
1962 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1963 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1964 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1965 swf_SetU16(tag, myshapeid);
1966 r.xmin = (int)(xmin*20);
1967 r.ymin = (int)(ymin*20);
1968 r.xmax = (int)(xmax*20);
1969 r.ymax = (int)(ymax*20);
1970 swf_SetRect(tag,&r);
1971 swf_SetShapeStyles(tag,shape);
1972 swf_ShapeCountBits(shape,NULL,NULL);
1973 swf_SetShapeBits(tag,shape);
1974 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1975 swflastx = swflasty = 0;
1982 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1983 ShapeSetLine (tag, shape, (int)(x1*20);
1984 ShapeSetLine (tag, shape, x*20,0);
1985 ShapeSetLine (tag, shape, 0,-y*20);
1986 ShapeSetLine (tag, shape, -x*20,0);*/
1987 swf_ShapeSetEnd(tag);
1990 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1991 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1994 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1995 double x1,double y1,
1996 double x2,double y2,
1997 double x3,double y3,
1998 double x4,double y4)
2006 int bitid = ++currentswfid;
2008 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2009 swf_SetU16(tag, bitid);
2010 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
2016 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2020 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2021 double x1,double y1,
2022 double x2,double y2,
2023 double x3,double y3,
2024 double x4,double y4)
2034 int bitid = ++currentswfid;
2036 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
2037 swf_SetU16(tag, bitid);
2038 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
2039 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2043 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
2044 double x1,double y1,
2045 double x2,double y2,
2046 double x3,double y3,
2047 double x4,double y4)
2055 int bitid = ++currentswfid;
2057 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
2058 swf_SetU16(tag, bitid);
2059 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
2065 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2069 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
2070 double x1,double y1,
2071 double x2,double y2,
2072 double x3,double y3,
2073 double x4,double y4, int n)
2084 /* SWF expects scanlines to be 4 byte aligned */
2087 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
2089 for(y=0;y<sizey;y++)
2091 for(x=0;x<sizex;x++)
2092 *ptr++ = mem[y*sizex+x];
2093 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
2098 int bitid = ++currentswfid;
2100 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
2101 swf_SetU16(tag, bitid);
2102 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
2110 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
2114 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
2115 double x1,double y1,
2116 double x2,double y2,
2117 double x3,double y3,
2118 double x4,double y4)
2126 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);