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, charnr);
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, int charnr)
705 for(t=0;t<this->charnum;t++) {
706 if(!strcmp(this->charname[t],name)) {
711 /* if we didn't find the character, maybe
712 we can find the capitalized version */
713 for(t=0;t<this->charnum;t++) {
714 if(!strcasecmp(this->charname[t],name))
718 /* if we didn't find it by name, use the names of the first 256 characters
719 of the font to try a new name based on charnr */
720 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
721 return getOutline(this->standardtable[charnr], -1);
724 logf("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
728 int SWFFont::getSWFCharID(char*name, int charnr)
731 for(t=0;t<this->charnum;t++) {
732 if(!strcmp(this->charname[t],name)) {
735 swfcharid2char[swfcharpos] = t;
736 char2swfcharid[t] = swfcharpos++;
739 return char2swfcharid[t];
743 /* if we didn't find the character, maybe
744 we can find the capitalized version */
745 for(t=0;t<this->charnum;t++) {
746 if(!strcasecmp(this->charname[t],name)) {
749 swfcharid2char[swfcharpos] = t;
750 char2swfcharid[t] = swfcharpos++;
753 return char2swfcharid[t];
757 /* if we didn't find it by name, use the names of the first 256 (or so) characters
758 of the font to try a new name based on charnr */
759 if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) {
760 return getSWFCharID(this->standardtable[charnr], -1);
762 logf("<warning> Didn't find character '%s' in font '%s'", FIXNULL(name), this->name);
766 int SWFFont::getWidth(char*name)
769 for(t=0;t<this->charnum;t++) {
770 if(!strcmp(this->charname[t],name)) {
771 return this->width[t];
777 char*SWFFont::getName()
788 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
789 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
791 fontlist_t*last=0,*iterator;
792 if(obj->font && !strcmp(obj->font->fontid,fontid))
797 if(!strcmp(iterator->font->fontid,fontid))
800 iterator = iterator->next;
804 obj->font = iterator->font;
809 logf("<error> internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid));
812 SWFFont*font = new SWFFont(fontid, t1id, filename);
813 iterator = new fontlist_t;
814 iterator->font = font;
818 last->next = iterator;
824 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
826 fontlist_t *iterator = fontlist;
828 if(!strcmp(iterator->font->fontid,fontid))
830 iterator = iterator->next;
835 /* set's the matrix which is to be applied to characters drawn by
836 swfoutput_drawchar() */
837 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
838 double m21,double m22)
840 if(obj->fontm11 == m11 &&
841 obj->fontm12 == m12 &&
842 obj->fontm21 == m21 &&
853 /* draws a character at x,y. */
854 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr)
857 m.m11 = obj->fontm11;
858 m.m12 = obj->fontm12;
859 m.m21 = obj->fontm21;
860 m.m22 = obj->fontm22;
863 drawchar(obj, obj->font, character, charnr, &m);
866 /* initialize the swf writer */
867 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
872 memset(obj, 0, sizeof(struct swfoutput));
873 filename = _filename;
877 logf("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
881 memset(&swf,0x00,sizeof(SWF));
884 swf.frameRate = 0x0040; // 1 frame per 4 seconds
885 swf.movieSize.xmax = 20*sizex;
886 swf.movieSize.ymax = 20*sizey;
888 swf.firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
893 swf_SetRGB(tag,&rgb);
894 if(flag_protected) // good practice! /r
895 tag = swf_InsertTag(tag, ST_PROTECT);
900 void swfoutput_setprotected() //write PROTECT tag
905 static void startshape(struct swfoutput*obj)
913 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
915 swf_ShapeNew(&shape);
916 linestyleid = swf_ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
917 rgb.r = obj->fillrgb.r;
918 rgb.g = obj->fillrgb.g;
919 rgb.b = obj->fillrgb.b;
920 fillstyleid = swf_ShapeAddSolidFillStyle(shape,&obj->fillrgb);
922 shapeid = ++currentswfid;
923 swf_SetU16(tag,shapeid); // ID
932 swf_SetShapeStyles(tag,shape);
933 swf_ShapeCountBits(shape,NULL,NULL);
934 swf_SetShapeBits(tag,shape);
936 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
941 static void starttext(struct swfoutput*obj)
947 tag = swf_InsertTag(tag,ST_DEFINETEXT);
948 textid = ++currentswfid;
949 swf_SetU16(tag, textid);
965 swf_SetMatrix(tag,&m);
969 static void endshape()
973 swf_ShapeSetEnd(tag);
974 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
975 swf_ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
979 static void endtext()
985 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
986 swf_ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL);
990 static void endpage(struct swfoutput*obj)
997 swfoutput_endclip(obj);
1001 atag = action_Stop(atag);
1002 atag = action_End(atag);
1003 tag = swf_InsertTag(tag,ST_DOACTION);
1004 swf_ActionSet(tag,atag);
1006 tag = swf_InsertTag(tag,ST_SHOWFRAME);
1009 void swfoutput_newpage(struct swfoutput*obj)
1013 for(depth--;depth>=startdepth;depth--) {
1014 tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
1015 swf_SetU16(tag,depth);
1022 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
1023 up, complete the swf, and write it out. */
1024 void swfoutput_destroy(struct swfoutput* obj)
1027 fontlist_t *tmp,*iterator = fontlist;
1029 delete iterator->font;
1032 iterator = iterator->next;
1040 fi = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0777);
1045 logf("<fatal> Could not create \"%s\". ", FIXNULL(filename));
1049 tag = swf_InsertTag(tag,ST_END);
1052 if FAILED(swf_WriteSWC(fi,&swf))
1053 logf("<error> WriteSWC() failed.\n");
1055 if FAILED(swf_WriteSWF(fi,&swf))
1056 logf("<error> WriteSWF() failed.\n");
1061 logf("<notice> SWF written\n");
1064 void swfoutput_setdrawmode(swfoutput* obj, int mode)
1067 if(mode == DRAWMODE_FILL)
1069 else if(mode == DRAWMODE_EOFILL)
1071 else if(mode == DRAWMODE_STROKE)
1073 else if(mode == DRAWMODE_CLIP)
1075 else if(mode == DRAWMODE_EOCLIP)
1079 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1081 if(obj->fillrgb.r == r &&
1082 obj->fillrgb.g == g &&
1083 obj->fillrgb.b == b &&
1084 obj->fillrgb.a == a) return;
1094 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
1096 if(obj->strokergb.r == r &&
1097 obj->strokergb.g == g &&
1098 obj->strokergb.b == b &&
1099 obj->strokergb.a == a) return;
1103 obj->strokergb.r = r;
1104 obj->strokergb.g = g;
1105 obj->strokergb.b = b;
1106 obj->strokergb.a = a;
1109 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
1111 if(obj->linewidth == (u16)(linewidth*20))
1116 obj->linewidth = (u16)(linewidth*20);
1120 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
1129 logf("<warning> Too many clip levels.");
1134 int olddrawmode = drawmode;
1135 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
1136 swfoutput_drawpath(obj, outline, m);
1137 swf_ShapeSetEnd(tag);
1138 swfoutput_setdrawmode(obj, olddrawmode);
1140 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1141 cliptags[clippos] = tag;
1142 clipshapes[clippos] = shapeid;
1143 clipdepths[clippos] = depth++;
1148 void swfoutput_endclip(swfoutput*obj)
1156 logf("<error> Invalid end of clipping region");
1160 swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
1163 static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover);
1165 void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points)
1175 actions = action_GetUrl(0, url, "_parent");
1177 actions = action_GetUrl(0, url, "_this");
1178 actions = action_End(actions);
1180 drawlink(obj, actions, 0, points,0);
1182 void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points)
1191 actions = action_GotoFrame(0, page);
1192 actions = action_End(actions);
1194 drawlink(obj, actions, 0, points,0);
1196 void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points)
1198 ActionTAG *actions1,*actions2;
1205 actions1 = action_PushString(0, "/:subtitle");
1206 actions1 = action_PushString(actions1, name);
1207 actions1 = action_SetVariable(actions1);
1208 actions1 = action_End(actions1);
1210 actions2 = action_PushString(0, "/:subtitle");
1211 actions2 = action_PushString(actions2, "");
1212 actions2 = action_SetVariable(actions2);
1213 actions2 = action_End(actions2);
1215 drawlink(obj, actions1, actions2, points,1);
1217 swf_ActionFree(actions1);
1218 swf_ActionFree(actions2);
1221 static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover)
1227 struct plotxy p1,p2,p3,p4;
1231 double xmax=xmin=points[0].x,ymax=ymin=points[0].y;
1235 int buttonid = ++currentswfid;
1238 if(points[t].x>xmax) xmax=points[t].x;
1239 if(points[t].y>ymax) ymax=points[t].y;
1240 if(points[t].x<xmin) xmin=points[t].x;
1241 if(points[t].y<ymin) ymin=points[t].y;
1244 p1.x=points[0].x; p1.y=points[0].y; p2.x=points[1].x; p2.y=points[1].y;
1245 p3.x=points[2].x; p3.y=points[2].y; p4.x=points[3].x; p4.y=points[3].y;
1247 /* the following code subtracts the upper left edge from all coordinates,
1248 and set's posx,posy so that ST_PLACEOBJECT is used with a matrix.
1249 Necessary for preprocessing with swfcombine. */
1250 posx = xmin; posy = ymin;
1251 p1.x-=posx;p2.x-=posx;p3.x-=posx;p4.x-=posx;
1252 p1.y-=posy;p2.y-=posy;p3.y-=posy;p4.y-=posy;
1253 xmin -= posx; ymin -= posy;
1254 xmax -= posx; ymax -= posy;
1257 myshapeid = ++currentswfid;
1258 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1259 swf_ShapeNew(&shape);
1260 rgb.r = rgb.b = rgb.a = rgb.g = 0;
1261 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1262 swf_SetU16(tag, myshapeid);
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);
1281 myshapeid2 = ++currentswfid;
1282 tag = swf_InsertTag(tag,ST_DEFINESHAPE3);
1283 swf_ShapeNew(&shape);
1284 rgb.r = rgb.b = rgb.a = rgb.g = 255;
1286 fsid = swf_ShapeAddSolidFillStyle(shape,&rgb);
1287 swf_SetU16(tag, myshapeid2);
1288 r.xmin = (int)(xmin*20);
1289 r.ymin = (int)(ymin*20);
1290 r.xmax = (int)(xmax*20);
1291 r.ymax = (int)(ymax*20);
1292 swf_SetRect(tag,&r);
1293 swf_SetShapeStyles(tag,shape);
1294 swf_ShapeCountBits(shape,NULL,NULL);
1295 swf_SetShapeBits(tag,shape);
1296 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,0,fsid,0);
1297 swflastx = swflasty = 0;
1303 swf_ShapeSetEnd(tag);
1307 tag = swf_InsertTag(tag,ST_DEFINEBUTTON);
1308 swf_SetU16(tag,buttonid); //id
1309 swf_ButtonSetFlags(tag, 0); //menu=no
1310 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1311 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1312 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1313 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1315 swf_ActionSet(tag,actions1);
1320 tag = swf_InsertTag(tag,ST_DEFINEBUTTON2);
1321 swf_SetU16(tag,buttonid); //id
1322 swf_ButtonSetFlags(tag, 0); //menu=no
1323 swf_ButtonSetRecord(tag,0x01,myshapeid,depth,0,0);
1324 swf_ButtonSetRecord(tag,0x02,myshapeid2,depth,0,0);
1325 swf_ButtonSetRecord(tag,0x04,myshapeid2,depth,0,0);
1326 swf_ButtonSetRecord(tag,0x08,myshapeid,depth,0,0);
1327 swf_SetU8(tag,0); // end of button records
1328 swf_ButtonSetCondition(tag, BC_IDLE_OVERUP);
1329 swf_ActionSet(tag,actions1);
1331 swf_ButtonSetCondition(tag, BC_OVERUP_IDLE);
1332 swf_ActionSet(tag,actions2);
1334 swf_ButtonPostProcess(tag, 2);
1337 swf_ButtonPostProcess(tag, 1);
1341 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1343 if(posx!=0 || posy!=0) {
1345 swf_GetMatrix(0,&m);
1346 m.tx = (int)(posx*20);
1347 m.ty = (int)(posy*20);
1348 swf_ObjectPlace(tag, buttonid, depth++,&m,0,0);
1351 swf_ObjectPlace(tag, buttonid, depth++,0,0,0);
1355 static void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey,
1356 double x1,double y1,
1357 double x2,double y2,
1358 double x3,double y3,
1359 double x4,double y4)
1365 struct plotxy p1,p2,p3,p4;
1367 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
1368 if(x2>xmax) xmax=x2;
1369 if(y2>ymax) ymax=y2;
1370 if(x2<xmin) xmin=x2;
1371 if(y2<ymin) ymin=y2;
1372 if(x3>xmax) xmax=x3;
1373 if(y3>ymax) ymax=y3;
1374 if(x3<xmin) xmin=x3;
1375 if(y3<ymin) ymin=y3;
1376 if(x4>xmax) xmax=x4;
1377 if(y4>ymax) ymax=y4;
1378 if(x4<xmin) xmin=x4;
1379 if(y4<ymin) ymin=y4;
1385 {p1.x = (int)(p1.x*20)/20.0;
1386 p1.y = (int)(p1.y*20)/20.0;
1387 p2.x = (int)(p2.x*20)/20.0;
1388 p2.y = (int)(p2.y*20)/20.0;
1389 p3.x = (int)(p3.x*20)/20.0;
1390 p3.y = (int)(p3.y*20)/20.0;
1391 p4.x = (int)(p4.x*20)/20.0;
1392 p4.y = (int)(p4.y*20)/20.0;}
1395 m.sx = (int)(65536*20*(p4.x-p1.x)/sizex);
1396 m.r1 = -(int)(65536*20*(p4.y-p1.y)/sizex);
1397 m.r0 = (int)(65536*20*(p1.x-p2.x)/sizey);
1398 m.sy = -(int)(65536*20*(p1.y-p2.y)/sizey);
1400 m.tx = (int)(p1.x*20);
1401 m.ty = (int)(p1.y*20);
1404 myshapeid = ++currentswfid;
1405 tag = swf_InsertTag(tag,ST_DEFINESHAPE);
1406 swf_ShapeNew(&shape);
1407 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
1408 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
1409 fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1);
1410 swf_SetU16(tag, myshapeid);
1411 r.xmin = (int)(xmin*20);
1412 r.ymin = (int)(ymin*20);
1413 r.xmax = (int)(xmax*20);
1414 r.ymax = (int)(ymax*20);
1415 swf_SetRect(tag,&r);
1416 swf_SetShapeStyles(tag,shape);
1417 swf_ShapeCountBits(shape,NULL,NULL);
1418 swf_SetShapeBits(tag,shape);
1419 swf_ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
1420 swflastx = swflasty = 0;
1427 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
1428 ShapeSetLine (tag, shape, (int)(x1*20);
1429 ShapeSetLine (tag, shape, x*20,0);
1430 ShapeSetLine (tag, shape, 0,-y*20);
1431 ShapeSetLine (tag, shape, -x*20,0);*/
1432 swf_ShapeSetEnd(tag);
1435 tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
1436 swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);
1439 int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey,
1440 double x1,double y1,
1441 double x2,double y2,
1442 double x3,double y3,
1443 double x4,double y4)
1451 int bitid = ++currentswfid;
1453 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1454 swf_SetU16(tag, bitid);
1455 if(swf_SetJPEGBits(tag, filename, jpegquality)<0) {
1461 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1465 int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1466 double x1,double y1,
1467 double x2,double y2,
1468 double x3,double y3,
1469 double x4,double y4)
1479 int bitid = ++currentswfid;
1481 tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2);
1482 swf_SetU16(tag, bitid);
1483 swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality);
1484 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1488 int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey,
1489 double x1,double y1,
1490 double x2,double y2,
1491 double x3,double y3,
1492 double x4,double y4)
1500 int bitid = ++currentswfid;
1502 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS);
1503 swf_SetU16(tag, bitid);
1504 if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) {
1510 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1514 int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey,
1515 double x1,double y1,
1516 double x2,double y2,
1517 double x3,double y3,
1518 double x4,double y4, int n)
1529 /* SWF expects scanlines to be 4 byte aligned */
1532 mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey);
1534 for(y=0;y<sizey;y++)
1536 for(x=0;x<sizex;x++)
1537 *ptr++ = mem[y*sizex+x];
1538 ptr+= BYTES_PER_SCANLINE(sizex)-sizex;
1543 int bitid = ++currentswfid;
1545 tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS2);
1546 swf_SetU16(tag, bitid);
1547 if(swf_SetLosslessBitsIndexed(tag,sizex,sizey,mem, pal, n)<0) {
1555 drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
1559 void swfoutput_drawimageagain(struct swfoutput*obj, int id, int sizex,int sizey,
1560 double x1,double y1,
1561 double x2,double y2,
1562 double x3,double y3,
1563 double x4,double y4)
1571 drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);