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 "swfoutput.h"
27 #include "../lib/log.h"
28 #include "../lib/rfxswf.h"
30 #define standardEncodingSize 335
31 extern char *standardEncodingNames[standardEncodingSize];
34 int ignoredraworder=0;
37 int storeallcharacters=0;
40 static int flag_protected = 0;
42 typedef unsigned char u8;
43 typedef unsigned short int u16;
44 typedef unsigned long int u32;
47 static char* filename = 0;
50 static int currentswfid = 0;
52 static int startdepth = 1;
55 static int shapeid = -1;
56 static int textid = -1;
58 static int drawmode = -1;
59 static char storefont = 0;
60 static int fillstyleid;
61 static int linestyleid;
62 static int swflastx=0;
63 static int swflasty=0;
64 static int lastwasfill = 0;
76 char fillstylechanged = 0;
78 static void startshape(struct swfoutput* obj);
79 static void starttext(struct swfoutput* obj);
80 static void endshape();
81 static void endtext();
83 // matrix multiplication. changes p0
84 static void transform (plotxy*p0,struct swfmatrix*m)
87 x = m->m11*p0->x+m->m12*p0->y;
88 y = m->m21*p0->x+m->m22*p0->y;
93 // write a move-to command into the swf
94 static void moveto(TAG*tag, plotxy p0)
96 int rx = (int)(p0.x*20);
97 int ry = (int)(p0.y*20);
98 if(rx!=swflastx || ry!=swflasty || fillstylechanged) {
99 swf_ShapeSetMove (tag, shape, rx,ry);
100 fillstylechanged = 0;
106 // write a line-to command into the swf
107 static void lineto(TAG*tag, plotxy p0)
109 int rx = ((int)(p0.x*20)-swflastx);
110 int ry = ((int)(p0.y*20)-swflasty);
111 /* we can't skip this for rx=0,ry=0, those
113 swf_ShapeSetLine (tag, shape, rx,ry);
118 // write a spline-to command into the swf
119 static void splineto(TAG*tag, plotxy control,plotxy end)
121 int cx = ((int)(control.x*20)-swflastx);
122 int cy = ((int)(control.y*20)-swflasty);
125 int ex = ((int)(end.x*20)-swflastx);
126 int ey = ((int)(end.y*20)-swflasty);
129 if(cx || cy || ex || ey)
130 swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey);
133 /* write a line, given two points and the transformation
135 static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m)
143 /* write a cubic (!) spline. This involves calling the approximate()
144 function out of spline.cc to convert it to a quadratic spline. */
145 static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
148 struct qspline q[16];
156 num = approximate(p0,p1,p2,p3,q);
158 moveto(tag,q[t].start);
159 splineto(tag,q[t].control, q[t].end);
169 /* draw a T1 outline. These are generated by pdf2swf and by t1lib.
170 (representing characters) */
171 void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log)
173 if(tag->id != ST_DEFINEFONT &&
174 tag->id != ST_DEFINESHAPE &&
175 tag->id != ST_DEFINESHAPE2 &&
176 tag->id != ST_DEFINESHAPE3)
178 logf("<error> internal error: drawpath needs a shape tag, not %d\n",tag->id);
182 double lastx=0,lasty=0;
183 double firstx=0,firsty=0;
188 x += (outline->dest.x/(float)0xffff);
189 y += (outline->dest.y/(float)0xffff);
190 if(outline->type == T1_PATHTYPE_MOVE)
192 if(((int)(lastx*20) != (int)(firstx*20) ||
193 (int)(lasty*20) != (int)(firsty*20)) &&
202 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
203 line(tag, p0, p1, m);
209 else if(outline->type == T1_PATHTYPE_LINE)
217 if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
220 else if(outline->type == T1_PATHTYPE_BEZIER)
226 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
229 p1.x=o2->C.x/(float)0xffff+lastx;
230 p1.y=o2->C.y/(float)0xffff+lasty;
231 p2.x=o2->B.x/(float)0xffff+lastx;
232 p2.y=o2->B.y/(float)0xffff+lasty;
235 if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y);
236 spline(tag,p0,p1,p2,p3,m);
239 logf("<error> drawpath: unknown outline type:%d\n", outline->type);
243 outline = outline->link;
245 if(((int)(lastx*20) != (int)(firstx*20) ||
246 (int)(lasty*20) != (int)(firsty*20)) &&
255 if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y);
256 line(tag, p0, p1, m);
260 static inline int colorcompare(RGBA*a,RGBA*b)
272 static const int CHARDATAMAX = 1024;
280 } chardata[CHARDATAMAX];
283 static void putcharacters(TAG*tag)
288 color.r = chardata[0].color.r^255;
297 int charadvance[128];
300 int glyphbits=1; //TODO: can this be zero?
303 if(tag->id != ST_DEFINETEXT &&
304 tag->id != ST_DEFINETEXT2) {
305 logf("<error> internal error: putcharacters needs an text tag, not %d\n",tag->id);
309 logf("<warning> putcharacters called with zero characters");
312 for(pass = 0; pass < 2; pass++)
322 advancebits++; // add sign bit
323 swf_SetU8(tag, glyphbits);
324 swf_SetU8(tag, advancebits);
327 for(t=0;t<=chardatapos;t++)
329 if(lastfontid != chardata[t].fontid ||
330 lastx!=chardata[t].x ||
331 lasty!=chardata[t].y ||
332 !colorcompare(&color, &chardata[t].color) ||
334 lastsize != chardata[t].size ||
337 if(charstorepos && pass==0)
340 for(s=0;s<charstorepos;s++)
342 while(charids[s]>=(1<<glyphbits))
344 while(charadvance[s]>=(1<<advancebits))
348 if(charstorepos && pass==1)
350 tag->writeBit = 0; // Q&D
351 swf_SetBits(tag, 0, 1); // GLYPH Record
352 swf_SetBits(tag, charstorepos, 7); // number of glyphs
354 for(s=0;s<charstorepos;s++)
356 swf_SetBits(tag, charids[s], glyphbits);
357 swf_SetBits(tag, charadvance[s], advancebits);
362 if(pass == 1 && t<chardatapos)
368 if(lastx != chardata[t].x ||
369 lasty != chardata[t].y)
374 if(!colorcompare(&color, &chardata[t].color))
376 color = chardata[t].color;
379 font.id = chardata[t].fontid;
380 if(lastfontid != chardata[t].fontid || lastsize != chardata[t].size)
383 tag->writeBit = 0; // Q&D
384 swf_TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy);
387 lastfontid = chardata[t].fontid;
388 lastx = chardata[t].x;
389 lasty = chardata[t].y;
390 lastsize = chardata[t].size;
397 int nextt = t==chardatapos-1?t:t+1;
398 int rel = chardata[nextt].x-chardata[t].x;
399 if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) {
401 lastx=chardata[nextt].x;
407 charids[charstorepos] = chardata[t].charid;
408 charadvance[charstorepos] = advance;
415 static void putcharacter(struct swfoutput*obj, int fontid, int charid,
416 int x,int y, int size)
418 if(chardatapos == CHARDATAMAX)
423 chardata[chardatapos].fontid = fontid;
424 chardata[chardatapos].charid = charid;
425 chardata[chardatapos].x = x;
426 chardata[chardatapos].y = y;
427 chardata[chardatapos].color = obj->fillrgb;
428 chardata[chardatapos].size = size;
433 /* process a character. */
434 static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m)
437 if(m->m12!=0 || m->m21!=0)
442 if(usefonts && ! drawonlyshapes)
444 int charid = font->getSWFCharID(character, charnr);
449 putcharacter(obj, font->swfid, charid,(int)(m->m13*20),(int)(m->m23*20),
450 (int)(m->m11*20/2+0.5)); //where does the /2 come from?
454 T1_OUTLINE*outline = font->getOutline(character);
455 char* charname = character;
458 logf("<warning> Didn't find %s in current charset (%s)",
459 FIXNULL(character),FIXNULL(font->getName()));
475 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
476 fillstylechanged = 1;
482 drawpath(tag, outline, &m2, 0);
487 /* draw a curved polygon. */
488 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline,
494 /* Multiple polygons in one shape don't overlap correctly,
495 so we better start a new shape here if the polygon is filled
497 if(shapeid>=0 && fill && !ignoredraworder) {
504 if(lastwasfill && !fill)
506 swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
507 fillstylechanged = 1;
510 if(!lastwasfill && fill)
512 swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
513 fillstylechanged = 1;
517 drawpath(tag, outline,m, 0);
520 /* SWFFont: copy all t1 font outlines to a local
522 SWFFont::SWFFont(char*name, int id, char*filename)
524 if(!T1_GetFontName(id))
527 this->name = strdup(T1_GetFontFileName(id));
528 this->fontid = strdup(name);
531 char**a= T1_GetAllCharNames(id);
542 logf("<verbose> Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum);
544 this->standardtablesize = 256;
545 if(this->charnum < this->standardtablesize)
546 this->standardtablesize = this->charnum;
547 this->standardtable = (char**)malloc(standardtablesize*sizeof(char*));
549 for(t = 0; t < this->standardtablesize; t++) {
550 char*name = T1_GetCharName(id,t);
553 standardtable[t] = strdup(name);
556 outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*));
557 charname = (char**)malloc(charnum*sizeof(char*));
558 width = (int*)malloc(charnum*sizeof(int));
559 memset(width, 0, charnum*sizeof(int));
560 memset(charname, 0, charnum*sizeof(char*));
561 used = (char*)malloc(charnum*sizeof(char));
562 char2swfcharid = (U16*)malloc(charnum*2);
563 swfcharid2char = (U16*)malloc(charnum*2);
566 memset(used,0,charnum*sizeof(char));
568 this->swfid = ++currentswfid;
581 int ret = T1_ReencodeFont(id, map);
585 int ret = T1_ReencodeFont(id, map);
587 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
593 char* name = T1_GetCharName(id, s);
595 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
596 this->width[outlinepos] = T1_GetCharWidth(id, s);
597 this->charname[outlinepos] = strdup(name);
605 /* free all tables, write out definefont tags */
611 if(storeallcharacters)
614 for(t=0;t<this->charnum;t++)
616 if(this->charname[t])
617 getSWFCharID(this->charname[t], -1);
621 ptr = (int*)malloc(swfcharpos*sizeof(int));
623 for(t=0;t<charnum;t++)
624 if(used[t]) usednum++;
626 if(usednum && !drawonlyshapes)
628 logf("<verbose> Font %s has %d used characters",FIXNULL(fontid), usednum);
629 TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT);
630 swf_SetU16(ftag, this->swfid);
631 int initpos = swf_GetTagLen(ftag);
638 for(t=0;t<swfcharpos;t++)
640 ptr[t] = swf_GetTagLen(ftag);
641 swf_SetU16(ftag, 0x1234);
643 for(t=0;t<swfcharpos;t++)
645 *(U16*)&ftag->data[ptr[t]] =
646 SWAP16(swf_GetTagLen(ftag)-initpos);
650 swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits
654 swf_ShapeSetStyle(ftag,&s,0,1,0);
655 fillstylechanged = 1;
659 drawpath(ftag, outline[swfcharid2char[t]],&m, 0);
662 swf_ShapeSetEnd(ftag);
664 ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO);
665 swf_SetU16(ftag, this->swfid);
667 swf_SetU8(ftag, strlen(this->fontid));
668 swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid));
672 swf_SetU8(ftag, 0); //flags
673 for(t=0;t<swfcharpos;t++)
676 char * name = this->charname[this->swfcharid2char[t]];
678 if(standardEncodingNames[s] &&
679 !strcmp(name,standardEncodingNames[s]))
682 swf_SetU8(ftag, (U8)s);
688 for(t=0;t<charnum;t++)
690 for(t=0;t<standardtablesize;t++)
691 if(standardtable[t]) {
692 free(standardtable[t]);
698 free(swfcharid2char);
699 free(char2swfcharid);
702 T1_OUTLINE*SWFFont::getOutline(char*name)
705 for(t=0;t<this->charnum;t++) {
706 if(!strcmp(this->charname[t],name)) {
709 swfcharid2char[swfcharpos] = t;
710 char2swfcharid[t] = swfcharpos;
720 int SWFFont::getWidth(char*name)
723 for(t=0;t<this->charnum;t++) {
724 if(!strcmp(this->charname[t],name)) {
725 return this->width[t];
731 int SWFFont::getSWFCharID(char*name, int charnr)
734 for(t=0;t<this->charnum;t++) {
735 if(!strcmp(this->charname[t],name)) {
738 swfcharid2char[swfcharpos] = t;
739 char2swfcharid[t] = swfcharpos++;
742 return char2swfcharid[t];
745 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
746 return getSWFCharID(this->standardtable[charnr], -1);
748 logf("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
752 char*SWFFont::getName()
763 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
764 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
766 fontlist_t*last=0,*iterator;
767 if(obj->font && !strcmp(obj->font->fontid,fontid))
772 if(!strcmp(iterator->font->fontid,fontid))
775 iterator = iterator->next;
779 obj->font = iterator->font;
784 logf("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
787 SWFFont*font = new SWFFont(fontid, t1id, filename);
788 iterator = new fontlist_t;
789 iterator->font = font;
793 last->next = iterator;
799 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
801 fontlist_t *iterator = fontlist;
803 if(!strcmp(iterator->font->fontid,fontid))
805 iterator = iterator->next;
810 /* set's the matrix which is to be applied to characters drawn by
811 swfoutput_drawchar() */
812 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
813 double m21,double m22)
815 if(obj->fontm11 == m11 &&
816 obj->fontm12 == m12 &&
817 obj->fontm21 == m21 &&
828 /* draws a character at x,y. */
829 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
832 m.m11 = obj->fontm11;
833 m.m12 = obj->fontm12;
834 m.m21 = obj->fontm21;
835 m.m22 = obj->fontm22;
838 drawchar(obj, obj->font, character, charnr, &m);
841 /* initialize the swf writer */
842 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
847 memset(obj, 0, sizeof(struct swfoutput));
848 filename = _filename;
852 logf("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
856 memset(&swf,0x00,sizeof(SWF));
859 swf.frameRate = 0x0040; // 1 frame per 4 seconds
860 swf.movieSize.xmax = 20*sizex;
861 swf.movieSize.ymax = 20*sizey;
863 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
868 swf_SetRGB(tag,&rgb);
869 if(flag_protected) // good practice! /r
870 tag = swf_InsertTag(tag, ST_PROTECT);
875 void swfoutput_setprotected() //write PROTECT tag
880 static void startshape(struct swfoutput*obj)
888 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
890 swf_ShapeNew(&shape);
891 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
892 rgb.r = obj->fillrgb.r;
893 rgb.g = obj->fillrgb.g;
894 rgb.b = obj->fillrgb.b;
895 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
897 shapeid = ++currentswfid;
898 swf_SetU16(tag,shapeid); // ID
907 swf_SetShapeStyles(tag,shape);
908 swf_ShapeCountBits(shape,NULL,NULL);
909 swf_SetShapeBits(tag,shape);
911 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
916 static void starttext(struct swfoutput*obj)
922 tag = swf_InsertTag(tag,ST_DEFINETEXT);
923 textid = ++currentswfid;
924 swf_SetU16(tag, textid);
940 swf_SetMatrix(tag,&m);
944 static void endshape()
948 swf_ShapeSetEnd(tag);
949 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
950 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
954 static void endtext()
960 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
961 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
965 static void endpage(struct swfoutput*obj)
972 swfoutput_endclip(obj);
976 atag = action_Stop(atag);
977 atag = action_End(atag);
978 tag = swf_InsertTag(tag,ST_DOACTION);
979 swf_ActionSet(tag,atag);
981 tag = swf_InsertTag(tag,ST_SHOWFRAME);
984 void swfoutput_newpage(struct swfoutput*obj)
988 for(depth--;depth>=startdepth;depth--) {
989 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
990 swf_SetU16(tag,depth);
997 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
998 up, complete the swf, and write it out. */
999 void swfoutput_destroy(struct swfoutput* obj)
1002 fontlist_t *tmp,*iterator = fontlist;
1004 delete iterator->font;
1007 iterator = iterator->next;
1015 fi = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0777);
1020 logf("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1024 tag = swf_InsertTag(tag,ST_END);
1027 if FAILED(swf_WriteSWC(fi,&swf))
1028 logf("<error> WriteSWC() failed.\n");
1030 if FAILED(swf_WriteSWF(fi,&swf))
1031 logf("<error> WriteSWF() failed.\n");
1036 logf("<notice> SWF written\n");
1039 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1042 if(mode == DRAWMODE_FILL)
1044 else if(mode == DRAWMODE_EOFILL)
1046 else if(mode == DRAWMODE_STROKE)
1048 else if(mode == DRAWMODE_CLIP)
1050 else if(mode == DRAWMODE_EOCLIP)
1054 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1056 if(obj->fillrgb.r == r &&
1057 obj->fillrgb.g == g &&
1058 obj->fillrgb.b == b &&
1059 obj->fillrgb.a == a) return;
1069 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1071 if(obj->strokergb.r == r &&
1072 obj->strokergb.g == g &&
1073 obj->strokergb.b == b &&
1074 obj->strokergb.a == a) return;
1078 obj->strokergb.r = r;
1079 obj->strokergb.g = g;
1080 obj->strokergb.b = b;
1081 obj->strokergb.a = a;
1084 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1086 if(obj->linewidth == (u16)(linewidth*20))
1091 obj->linewidth = (u16)(linewidth*20);
1095 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1104 logf("<warning> Too many clip levels.");
1109 int olddrawmode = drawmode;
1110 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1111 swfoutput_drawpath(obj, outline, m);
1112 swf_ShapeSetEnd(tag);
1113 swfoutput_setdrawmode(obj, olddrawmode);
1115 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1116 cliptags[clippos] = tag;
1117 clipshapes[clippos] = shapeid;
1118 clipdepths[clippos] = depth++;
1123 void swfoutput_endclip(swfoutput*obj)
1131 logf("<error> Invalid end of clipping region");
1135 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1138 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1140 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1150 actions = action_GetUrl(0, url, "_parent");
1152 actions = action_GetUrl(0, url, "_this");
1153 actions = action_End(actions);
1155 drawlink(obj, actions, 0, points,0);
1157 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1166 actions = action_GotoFrame(0, page);
1167 actions = action_End(actions);
1169 drawlink(obj, actions, 0, points,0);
1171 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1173 ActionTAG *actions1,*actions2;
1180 actions1 = action_PushString(0, "/:subtitle");
1181 actions1 = action_PushString(actions1, name);
1182 actions1 = action_SetVariable(actions1);
1183 actions1 = action_End(actions1);
1185 actions2 = action_PushString(0, "/:subtitle");
1186 actions2 = action_PushString(actions2, "");
1187 actions2 = action_SetVariable(actions2);
1188 actions2 = action_End(actions2);
1190 drawlink(obj, actions1, actions2, points,1);
1192 swf_ActionFree(actions1);
1193 swf_ActionFree(actions2);
1196 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1202 struct plotxy p1,p2,p3,p4;
1206 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1210 int buttonid = ++currentswfid;
1213 if(points[t].x>xmax) xmax=points[t].x;
1214 if(points[t].y>ymax) ymax=points[t].y;
1215 if(points[t].x<xmin) xmin=points[t].x;
1216 if(points[t].y<ymin) ymin=points[t].y;
1219 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1220 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1222 /* the following code subtracts the upper left edge from all coordinates,
1223 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1224 Necessary for preprocessing with swfcombine. */
1225 posx = xmin; posy = ymin;
1226 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1227 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1228 xmin -= posx; ymin -= posy;
1229 xmax -= posx; ymax -= posy;
1232 myshapeid = ++currentswfid;
1233 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1234 swf_ShapeNew(&shape);
1235 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1236 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1237 swf_SetU16(tag, myshapeid);
1238 r.xmin = (int)(xmin*20);
1239 r.ymin = (int)(ymin*20);
1240 r.xmax = (int)(xmax*20);
1241 r.ymax = (int)(ymax*20);
1242 swf_SetRect(tag,&r);
1243 swf_SetShapeStyles(tag,shape);
1244 swf_ShapeCountBits(shape,NULL,NULL);
1245 swf_SetShapeBits(tag,shape);
1246 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1247 swflastx = swflasty = 0;
1253 swf_ShapeSetEnd(tag);
1256 myshapeid2 = ++currentswfid;
1257 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1258 swf_ShapeNew(&shape);
1259 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1261 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1262 swf_SetU16(tag, myshapeid2);
1263 r.xmin = (int)(xmin*20);
1264 r.ymin = (int)(ymin*20);
1265 r.xmax = (int)(xmax*20);
1266 r.ymax = (int)(ymax*20);
1267 swf_SetRect(tag,&r);
1268 swf_SetShapeStyles(tag,shape);
1269 swf_ShapeCountBits(shape,NULL,NULL);
1270 swf_SetShapeBits(tag,shape);
1271 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1272 swflastx = swflasty = 0;
1278 swf_ShapeSetEnd(tag);
1282 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1283 swf_SetU16(tag,buttonid); //id
1284 swf_ButtonSetFlags(tag, 0); //menu=no
1285 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1286 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1287 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1288 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1290 swf_ActionSet(tag,actions1);
1295 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1296 swf_SetU16(tag,buttonid); //id
1297 swf_ButtonSetFlags(tag, 0); //menu=no
1298 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1299 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1300 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1301 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1302 swf_SetU8(tag,0); // end of button records
1303 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1304 swf_ActionSet(tag,actions1);
1306 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1307 swf_ActionSet(tag,actions2);
1309 swf_ButtonPostProcess(tag, 2);
1312 swf_ButtonPostProcess(tag, 1);
1316 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1318 if(posx!=0 || posy!=0) {
1320 swf_GetMatrix(0,&m);
1321 m.tx = (int)(posx*20);
1322 m.ty = (int)(posy*20);
1323 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1326 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1330 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1331 double x1,double y1,
1332 double x2,double y2,
1333 double x3,double y3,
1334 double x4,double y4)
1340 struct plotxy p1,p2,p3,p4;
1342 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1343 if(x2>xmax) xmax=x2;
1344 if(y2>ymax) ymax=y2;
1345 if(x2<xmin) xmin=x2;
1346 if(y2<ymin) ymin=y2;
1347 if(x3>xmax) xmax=x3;
1348 if(y3>ymax) ymax=y3;
1349 if(x3<xmin) xmin=x3;
1350 if(y3<ymin) ymin=y3;
1351 if(x4>xmax) xmax=x4;
1352 if(y4>ymax) ymax=y4;
1353 if(x4<xmin) xmin=x4;
1354 if(y4<ymin) ymin=y4;
1360 {p1.x = (int)(p1.x*20)/20.0;
1361 p1.y = (int)(p1.y*20)/20.0;
1362 p2.x = (int)(p2.x*20)/20.0;
1363 p2.y = (int)(p2.y*20)/20.0;
1364 p3.x = (int)(p3.x*20)/20.0;
1365 p3.y = (int)(p3.y*20)/20.0;
1366 p4.x = (int)(p4.x*20)/20.0;
1367 p4.y = (int)(p4.y*20)/20.0;}
1370 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1371 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1372 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1373 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1375 m.tx = (int)(p1.x*20);
1376 m.ty = (int)(p1.y*20);
1379 myshapeid = ++currentswfid;
1380 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1381 swf_ShapeNew(&shape);
1382 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1383 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1384 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1385 swf_SetU16(tag, myshapeid);
1386 r.xmin = (int)(xmin*20);
1387 r.ymin = (int)(ymin*20);
1388 r.xmax = (int)(xmax*20);
1389 r.ymax = (int)(ymax*20);
1390 swf_SetRect(tag,&r);
1391 swf_SetShapeStyles(tag,shape);
1392 swf_ShapeCountBits(shape,NULL,NULL);
1393 swf_SetShapeBits(tag,shape);
1394 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1395 swflastx = swflasty = 0;
1402 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1403 ShapeSetLine (tag, shape, (int)(x1*20);
1404 ShapeSetLine (tag, shape, x*20,0);
1405 ShapeSetLine (tag, shape, 0,-y*20);
1406 ShapeSetLine (tag, shape, -x*20,0);*/
1407 swf_ShapeSetEnd(tag);
1410 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1411 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1414 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1415 double x1,double y1,
1416 double x2,double y2,
1417 double x3,double y3,
1418 double x4,double y4)
1426 int bitid = ++currentswfid;
1428 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1429 swf_SetU16(tag, bitid);
1430 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1436 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1440 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1441 double x1,double y1,
1442 double x2,double y2,
1443 double x3,double y3,
1444 double x4,double y4)
1454 int bitid = ++currentswfid;
1456 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1457 swf_SetU16(tag, bitid);
1458 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1459 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1463 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1464 double x1,double y1,
1465 double x2,double y2,
1466 double x3,double y3,
1467 double x4,double y4)
1475 int bitid = ++currentswfid;
1477 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1478 swf_SetU16(tag, bitid);
1479 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
1485 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1489 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
1490 double x1,double y1,
1491 double x2,double y2,
1492 double x3,double y3,
1493 double x4,double y4, int n)
1504 /* SWF expects scanlines to be 4 byte aligned */
1507 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
1509 for(y=0;y<sizey;y++)
1511 for(x=0;x<sizex;x++)
1512 *ptr++ = mem[y*sizex+x];
1513 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
1518 int bitid = ++currentswfid;
1520 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
1521 swf_SetU16(tag, bitid);
1522 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
1530 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1534 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
1535 double x1,double y1,
1536 double x2,double y2,
1537 double x3,double y3,
1538 double x4,double y4)
1546 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);