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"
31 typedef unsigned char u8;
32 typedef unsigned short int u16;
33 typedef unsigned long int u32;
36 static int flag_protected;
39 static int shapeid = -1;
40 static int shapecount = 0;
42 static int fillstyleid;
43 static int linestyleid;
44 static int swflastx=0;
45 static int swflasty=0;
46 static int lastwasfill = 0;
47 static char* filename = 0;
52 static int startdepth = 1;
58 void startshape(struct swfoutput* obj);
60 // matrix multiplication. changes p0
61 void transform (plotxy*p0,struct swfmatrix*m)
64 x = m->m11*p0->x+m->m12*p0->y;
65 y = m->m21*p0->x+m->m22*p0->y;
70 // write a move-to command into the swf
71 void moveto(plotxy p0)
73 int rx = (int)(p0.x*20);
74 int ry = (int)(p0.y*20);
75 if(rx!=swflastx || ry!=swflasty) {
76 ShapeSetMove (tag, shape, rx,ry);
82 // write a line-to command into the swf
83 void lineto(plotxy p0)
85 int rx = ((int)(p0.x*20)-swflastx);
86 int ry = ((int)(p0.y*20)-swflasty);
87 /* we can't skip this for rx=0,ry=0, those
89 ShapeSetLine (tag, shape, rx,ry);
94 // write a spline-to command into the swf
95 void splineto(plotxy control,plotxy end)
97 int cx = ((int)(control.x*20)-swflastx);
98 int cy = ((int)(control.y*20)-swflasty);
101 int ex = ((int)(end.x*20)-swflastx);
102 int ey = ((int)(end.y*20)-swflasty);
105 ShapeSetCurve(tag, shape, cx,cy,ex,ey);
108 /* write a line, given two points and the transformation
110 void line(plotxy p0, plotxy p1, struct swfmatrix*m)
118 /* write a cubic (!) spline. This involves calling the approximate()
119 function out of spline.cc to convert it to a quadratic spline. */
120 void spline(plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m)
123 struct qspline q[16];
131 num = approximate(p0,p1,p2,p3,q);
134 splineto(q[t].control, q[t].end);
138 /* Adds an outline to a font. Applies only the 2x2 component of the transformation matrix.
140 void addtofont(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint)
144 /* draw a T1 outline. These are generated by pdf2swf and by t1lib.
145 (representing characters) */
146 void drawpath(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint)
149 double lastx=0,lasty=0;
153 logf("<debug> Pathtype:%s",outline->type == T1_PATHTYPE_MOVE?"MOVE":
154 (outline->type == T1_PATHTYPE_LINE?"LINE"
156 logf("<debug> relative coordinates: %08x,%08x", outline->dest.x, outline->dest.y);
157 x += (outline->dest.x/(float)0xffff);
158 y += (outline->dest.y/(float)0xffff);
159 logf("<debug> coordinates: %f,%f", x, y);
160 if(outline->type == T1_PATHTYPE_MOVE)
163 else if(outline->type == T1_PATHTYPE_LINE)
173 else if(outline->type == T1_PATHTYPE_BEZIER)
179 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
182 p1.x=o2->C.x/(float)0xffff+lastx;
183 p1.y=o2->C.y/(float)0xffff+lasty;
184 p2.x=o2->B.x/(float)0xffff+lastx;
185 p2.y=o2->B.y/(float)0xffff+lasty;
188 spline(p0,p1,p2,p3,m);
191 logf("<error> drawpath: unknown outline type:%d\n", outline->type);
195 outline = outline->link;
198 //logf("<debug> Font name is %s", T1_GetFontFileName(t1fontindex));
199 //logf("<debug> char 0x%02x is named %s\n",character,charname);
200 //logf("<debug> bbox: %d %d %d %d\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury);
201 //char*charname = T1_GetCharName(t1fontindex, character);
203 /* process a character. */
204 void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m)
206 T1_OUTLINE*outline = font->getOutline(character);
207 char* charname = character;
210 logf("Didn't find %s in current charset", character);
224 ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
227 drawpath(outline, &m2, charname);
230 /* draw a curved polygon. */
231 void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m)
236 if(lastwasfill && !fill)
238 ShapeSetStyle(tag,shape,linestyleid,0x8000,0);
241 if(!lastwasfill && fill)
243 ShapeSetStyle(tag,shape,0x8000,fillstyleid,0);
247 drawpath(outline,m, 0);
250 SWFFont::SWFFont(char*name, int id, char*filename)
252 if(!T1_GetFontName(id))
255 this->name = strdup(T1_GetFontFileName(id));
256 this->fontid = strdup(name);
259 char**a= T1_GetAllCharNames(id);
260 int t=0, outlinepos=0;
268 logf("<notice> Font %s(%d): Storing %d outlines.\n", name, id, t);
270 outline = (T1_OUTLINE**)malloc(t*sizeof(T1_OUTLINE*));
271 charname = (char**)malloc(t*sizeof(char*));
284 int ret = T1_ReencodeFont(id, map);
288 int ret = T1_ReencodeFont(id, map);
290 fprintf(stderr,"Can't reencode font: (%s) ret:%d\n",filename, ret);
296 this->outline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0));
297 this->charname[outlinepos] = strdup(T1_GetCharName(id, s));
305 T1_OUTLINE*SWFFont::getOutline(char*name)
308 for(t=0;t<this->charnum;t++) {
309 if(!strcmp(this->charname[t],name))
315 char*SWFFont::getName()
326 /* set's the t1 font index of the font to use for swfoutput_drawchar(). */
327 void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filename)
329 fontlist_t*last=0,*iterator;
330 if(obj->font && !strcmp(obj->font->fontid,fontid))
335 if(!strcmp(iterator->font->fontid,fontid))
338 iterator = iterator->next;
342 obj->font = iterator->font;
347 logf("<error> internal error: t1id:%d, fontid:%s\n", t1id,fontid);
350 SWFFont*font = new SWFFont(fontid, t1id, filename);
351 iterator = new fontlist_t;
352 iterator->font = font;
356 last->next = iterator;
362 int swfoutput_queryfont(struct swfoutput*obj, char*fontid)
364 fontlist_t *iterator = fontlist;
366 if(!strcmp(iterator->font->fontid,fontid))
368 iterator = iterator->next;
373 /* set's the matrix which is to be applied to characters drawn by
374 swfoutput_drawchar() */
375 void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12,
376 double m21,double m22)
384 /* draws a character at x,y. */
385 void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character)
388 m.m11 = obj->fontm11;
389 m.m12 = obj->fontm12;
390 m.m21 = obj->fontm21;
391 m.m22 = obj->fontm22;
394 drawchar(obj, obj->font, character, &m);
397 /* initialize the swf writer */
398 void swfoutput_init(struct swfoutput* obj, char*_filename, int _sizex, int _sizey)
403 memset(obj, 0, sizeof(struct swfoutput));
404 filename = _filename;
408 logf("<verbose> initializing swf output for size %d*%d\n", sizex,sizey);
412 memset(&swf,0x00,sizeof(SWF));
415 // swf.FrameRate = 0x1900;
416 swf.FrameRate = 0x0040; // 1 frame per 4 seconds
417 swf.MovieSize.xmax = 20*sizex;
418 swf.MovieSize.ymax = 20*sizey;
420 swf.FirstTag = InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
427 tag = InsertTag(tag, ST_PROTECT);
432 void swfoutput_setprotected() //write PROTECT tag
437 void startshape(struct swfoutput*obj)
441 tag = InsertTag(tag,ST_DEFINESHAPE);
444 linestyleid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
445 rgb.r = obj->fillrgb.r;
446 rgb.g = obj->fillrgb.g;
447 rgb.b = obj->fillrgb.b;
448 fillstyleid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
450 shapeid = ++shapecount;
451 SetU16(tag,shapeid); // ID
460 SetShapeStyles(tag,shape);
461 ShapeCountBits(shape,NULL,NULL);
462 SetShapeBits(tag,shape);
464 ShapeSetAll(tag,shape,/*x*/0,/*y*/0,linestyleid,0,0);
474 tag = InsertTag(tag,ST_PLACEOBJECT2);
475 ObjectPlace(tag,shapeid,/*depth*/depth++,NULL,NULL,NULL);
479 void endpage(struct swfoutput*obj)
484 swfoutput_endclip(obj);
485 tag = InsertTag(tag,ST_SHOWFRAME);
488 void swfoutput_newpage(struct swfoutput*obj)
492 for(depth--;depth>=startdepth;depth--) {
493 tag = InsertTag(tag,ST_REMOVEOBJECT2);
501 /* "destroy" like in (oo-terminology) "destructor". Perform cleaning
502 up, complete the swf, and write it out. */
503 void swfoutput_destroy(struct swfoutput* obj)
511 fi = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0777);
516 logf("<fatal> Could not create \"%s\". ", filename);
520 tag = InsertTag(tag,ST_END);
522 if FAILED(WriteSWF(fi,&swf))
523 logf("<error> WriteSWF() failed.\n");
526 printf("SWF written\n");
529 void swfoutput_setdrawmode(swfoutput* obj, int mode)
531 if(mode == DRAWMODE_FILL)
533 else if(mode == DRAWMODE_EOFILL)
535 else if(mode == DRAWMODE_STROKE)
537 else if(mode == DRAWMODE_CLIP)
539 else if(mode == DRAWMODE_EOCLIP)
543 void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
545 if(obj->fillrgb.r == r &&
546 obj->fillrgb.g == g &&
547 obj->fillrgb.b == b &&
548 obj->fillrgb.a == a) return;
558 void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a)
560 if(obj->strokergb.r == r &&
561 obj->strokergb.g == g &&
562 obj->strokergb.b == b &&
563 obj->strokergb.a == a) return;
567 obj->strokergb.r = r;
568 obj->strokergb.g = g;
569 obj->strokergb.b = b;
570 obj->strokergb.a = a;
573 void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
575 if(obj->linewidth == (u16)(linewidth*20))
580 obj->linewidth = (u16)(linewidth*20);
584 void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m)
591 logf("<warning> Too many clip levels.");
597 swfoutput_setdrawmode(obj, DRAWMODE_CLIP);
598 swfoutput_drawpath(obj, outline, m);
601 tag = InsertTag(tag,ST_PLACEOBJECT2);
602 cliptags[clippos] = tag;
603 clipshapes[clippos] = shapeid;
604 clipdepths[clippos] = depth++;
609 void swfoutput_endclip(swfoutput*obj)
615 logf("<error> Invalid end of clipping region");
619 PlaceObject(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++);
622 void swfoutput_drawimagefile(struct swfoutput*, char*filename, int sizex,int sizey,
633 struct plotxy p1,p2,p3,p4;
635 double xmax=x1,ymax=y1,xmin=x1,ymin=y1;
658 m.sx = (int)(65536*20*(x4-x1))/sizex;
659 m.r1 = -(int)(65536*20*(y4-y1))/sizex;
660 m.r0 = (int)(65536*20*(x1-x2))/sizey;
661 m.sy = -(int)(65536*20*(y1-y2))/sizey;
669 bitid = ++shapecount;
672 tag = InsertTag(tag,ST_DEFINEBITSJPEG2);
674 SetJPEGBits(tag, filename, 85);
677 myshapeid = ++shapecount;
678 tag = InsertTag(tag,ST_DEFINESHAPE);
680 //lsid = ShapeAddLineStyle(shape,obj->linewidth,&obj->strokergb);
681 //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb);
682 fsid = ShapeAddBitmapFillStyle(shape,&m,bitid,0);
683 SetU16(tag, myshapeid);
684 r.xmin = (int)(xmin*20);
685 r.ymin = (int)(ymin*20);
686 r.xmax = (int)(xmax*20);
687 r.ymax = (int)(ymax*20);
689 SetShapeStyles(tag,shape);
690 ShapeCountBits(shape,NULL,NULL);
691 SetShapeBits(tag,shape);
692 ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0);
693 swflastx = swflasty = 0;
700 ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20));
701 ShapeSetLine (tag, shape, (int)(x1*20);
702 ShapeSetLine (tag, shape, x*20,0);
703 ShapeSetLine (tag, shape, 0,-y*20);
704 ShapeSetLine (tag, shape, -x*20,0);*/
708 tag = InsertTag(tag,ST_PLACEOBJECT2);
709 ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL);