X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2Fswfoutput.cc;h=2161d9e3fed2e074857df4a99a4204a7030207d0;hb=602d0f0a1c8ad614029f235cc6ff38bfe26334e8;hp=ccc4c1b9ab428e4f82c31432da69bbf2d11774ad;hpb=af8c85b9336c4a64f75499e7546557fbfe3e9cf9;p=swftools.git diff --git a/pdf2swf/swfoutput.cc b/pdf2swf/swfoutput.cc index ccc4c1b..2161d9e 100644 --- a/pdf2swf/swfoutput.cc +++ b/pdf2swf/swfoutput.cc @@ -27,11 +27,15 @@ extern "C" { #include "../lib/log.h" #include "../lib/rfxswf.h" } +#define standardEncodingSize 335 +extern char *standardEncodingNames[standardEncodingSize]; int opennewwindow=0; int ignoredraworder=0; int drawonlyshapes=0; int jpegquality=85; +int storeallcharacters=0; +int enablezlib=0; static int flag_protected = 0; typedef unsigned char u8; @@ -68,13 +72,15 @@ int clippos = 0; int CHARMIDX = 0; int CHARMIDY = 0; -void startshape(struct swfoutput* obj); -void starttext(struct swfoutput* obj); -void endshape(); -void endtext(); +char fillstylechanged = 0; + +static void startshape(struct swfoutput* obj); +static void starttext(struct swfoutput* obj); +static void endshape(); +static void endtext(); // matrix multiplication. changes p0 -void transform (plotxy*p0,struct swfmatrix*m) +static void transform (plotxy*p0,struct swfmatrix*m) { double x,y; x = m->m11*p0->x+m->m12*p0->y; @@ -84,19 +90,20 @@ void transform (plotxy*p0,struct swfmatrix*m) } // write a move-to command into the swf -void moveto(TAG*tag, plotxy p0) +static void moveto(TAG*tag, plotxy p0) { int rx = (int)(p0.x*20); int ry = (int)(p0.y*20); - if(rx!=swflastx || ry!=swflasty) { + if(rx!=swflastx || ry!=swflasty || fillstylechanged) { swf_ShapeSetMove (tag, shape, rx,ry); + fillstylechanged = 0; } swflastx=rx; swflasty=ry; } // write a line-to command into the swf -void lineto(TAG*tag, plotxy p0) +static void lineto(TAG*tag, plotxy p0) { int rx = ((int)(p0.x*20)-swflastx); int ry = ((int)(p0.y*20)-swflasty); @@ -108,7 +115,7 @@ void lineto(TAG*tag, plotxy p0) } // write a spline-to command into the swf -void splineto(TAG*tag, plotxy control,plotxy end) +static void splineto(TAG*tag, plotxy control,plotxy end) { int cx = ((int)(control.x*20)-swflastx); int cy = ((int)(control.y*20)-swflasty); @@ -118,12 +125,13 @@ void splineto(TAG*tag, plotxy control,plotxy end) int ey = ((int)(end.y*20)-swflasty); swflastx += ex; swflasty += ey; - swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey); + if(cx || cy || ex || ey) + swf_ShapeSetCurve(tag, shape, cx,cy,ex,ey); } /* write a line, given two points and the transformation matrix. */ -void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m) +static void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m) { transform(&p0,m); transform(&p1,m); @@ -133,7 +141,7 @@ void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m) /* write a cubic (!) spline. This involves calling the approximate() function out of spline.cc to convert it to a quadratic spline. */ -void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) +static void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) { double d; struct qspline q[16]; @@ -151,9 +159,15 @@ void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) } } +void resetdrawer() +{ + swflastx = 0; + swflasty = 0; +} + /* draw a T1 outline. These are generated by pdf2swf and by t1lib. (representing characters) */ -void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m) +void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m, int log) { if(tag->id != ST_DEFINEFONT && tag->id != ST_DEFINESHAPE && @@ -163,8 +177,6 @@ void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m) logf(" internal error: drawpath needs a shape tag, not %d\n",tag->id); exit(1); } - int log = 0; - double x=0,y=0; double lastx=0,lasty=0; double firstx=0,firsty=0; @@ -244,7 +256,7 @@ void drawpath(TAG*tag, T1_OUTLINE*outline, struct swfmatrix*m) } } -int colorcompare(RGBA*a,RGBA*b) +static inline int colorcompare(RGBA*a,RGBA*b) { if(a->r!=b->r || @@ -267,7 +279,7 @@ struct chardata { } chardata[CHARDATAMAX]; int chardatapos = 0; -void putcharacters(TAG*tag) +static void putcharacters(TAG*tag) { int t; SWFFONT font; @@ -399,7 +411,7 @@ void putcharacters(TAG*tag) chardatapos = 0; } -void putcharacter(struct swfoutput*obj, int fontid, int charid, +static void putcharacter(struct swfoutput*obj, int fontid, int charid, int x,int y, int size) { if(chardatapos == CHARDATAMAX) @@ -418,7 +430,7 @@ void putcharacter(struct swfoutput*obj, int fontid, int charid, /* process a character. */ -void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) +static void drawchar(struct swfoutput*obj, SWFFont*font, char*character, int charnr, swfmatrix*m) { int usefonts=1; if(m->m12!=0 || m->m21!=0) @@ -428,7 +440,7 @@ void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) if(usefonts && ! drawonlyshapes) { - int charid = font->getSWFCharID(character); + int charid = font->getSWFCharID(character, charnr); if(shapeid>=0) endshape(); if(textid<0) @@ -443,7 +455,7 @@ void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) if(!outline) { logf(" Didn't find %s in current charset (%s)", - character,font->getName()); + FIXNULL(character),FIXNULL(font->getName())); return; } @@ -458,13 +470,15 @@ void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) if(shapeid<0) startshape(obj); - if(!lastwasfill) + if(!lastwasfill) { swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); + fillstylechanged = 1; + } lastwasfill = 1; int lf = fill; fill = 1; - drawpath(tag, outline, &m2); + drawpath(tag, outline, &m2, 0); fill = lf; } } @@ -475,21 +489,31 @@ void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, { if(textid>=0) endtext(); + + /* Multiple polygons in one shape don't overlap correctly, + so we better start a new shape here if the polygon is filled + */ + if(shapeid>=0 && fill && !ignoredraworder) { + endshape(); + } + if(shapeid<0) startshape(output); if(lastwasfill && !fill) { swf_ShapeSetStyle(tag,shape,linestyleid,0x8000,0); + fillstylechanged = 1; lastwasfill = 0; } if(!lastwasfill && fill) { swf_ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); + fillstylechanged = 1; lastwasfill = 1; } - drawpath(tag, outline,m); + drawpath(tag, outline,m, 0); } /* SWFFont: copy all t1 font outlines to a local @@ -502,29 +526,45 @@ SWFFont::SWFFont(char*name, int id, char*filename) this->name = strdup(T1_GetFontFileName(id)); this->fontid = strdup(name); this->t1id = id; - + char**a= T1_GetAllCharNames(id); - int t=0, outlinepos=0; + int t, outlinepos=0; char*map[256]; + + t=0; while(a[t]) t++; - this->charnum = t; - if(!t) + + if(!charnum) return; - logf(" Font %s(%d): Storing %d outlines.\n", name, id, t); + logf(" Font %s(%d): Storing %d outlines.\n", FIXNULL(name), id, charnum); + + this->standardtablesize = 256; + if(this->charnum < this->standardtablesize) + this->standardtablesize = this->charnum; + this->standardtable = (char**)malloc(standardtablesize*sizeof(char*)); + + for(t = 0; t < this->standardtablesize; t++) { + char*name = T1_GetCharName(id,t); + if(!name) + name = ""; + standardtable[t] = strdup(name); + } - outline = (T1_OUTLINE**)malloc(t*sizeof(T1_OUTLINE*)); - charname = (char**)malloc(t*sizeof(char*)); - used = (char*)malloc(t*sizeof(char)); - char2swfcharid = (U16*)malloc(t*2); - swfcharid2char = (U16*)malloc(t*2); + outline = (T1_OUTLINE**)malloc(charnum*sizeof(T1_OUTLINE*)); + charname = (char**)malloc(charnum*sizeof(char*)); + width = (int*)malloc(charnum*sizeof(int)); + memset(width, 0, charnum*sizeof(int)); + memset(charname, 0, charnum*sizeof(char*)); + used = (char*)malloc(charnum*sizeof(char)); + char2swfcharid = (U16*)malloc(charnum*2); + swfcharid2char = (U16*)malloc(charnum*2); swfcharpos = 0; - memset(used,0,t*sizeof(char)); + memset(used,0,charnum*sizeof(char)); this->swfid = ++currentswfid; - t=0; while(*a) @@ -549,8 +589,11 @@ SWFFont::SWFFont(char*name, int id, char*filename) // parsecharacters for(s=0;soutline[outlinepos] = T1_CopyOutline(T1_GetCharOutline(id, s, 100.0, 0)); - this->charname[outlinepos] = strdup(T1_GetCharName(id, s)); + this->width[outlinepos] = T1_GetCharWidth(id, s); + this->charname[outlinepos] = strdup(name); outlinepos++; } t=0; @@ -562,52 +605,94 @@ SWFFont::SWFFont(char*name, int id, char*filename) SWFFont::~SWFFont() { int t,usednum=0; - int*ptr = (int*)malloc(swfcharpos*sizeof(int)); + int*ptr; + + if(storeallcharacters) + { + int t; + for(t=0;tcharnum;t++) + { + if(this->charname[t]) + getSWFCharID(this->charname[t], -1); + } + } + + ptr = (int*)malloc(swfcharpos*sizeof(int)); for(t=0;t Font %s has %d used characters",fontid, usednum); + logf(" Font %s has %d used characters",FIXNULL(fontid), usednum); TAG*ftag = swf_InsertTag(swf.firstTag,ST_DEFINEFONT); swf_SetU16(ftag, this->swfid); - int initpos = swf_GetDataSize(ftag); + int initpos = swf_GetTagLen(ftag); swfmatrix m; m.m11 = m.m22 = 1; m.m21 = m.m12 = 0; m.m13 = CHARMIDX; m.m23 = CHARMIDY; + for(t=0;tdata[ptr[t]] = swf_GetDataSize(ftag)-initpos; + *(U16*)&ftag->data[ptr[t]] = + SWAP16(swf_GetTagLen(ftag)-initpos); + swflastx=0; swflasty=0; - swf_SetU8(ftag,0x10); //0 fill bits, 0 linestyle bits + swf_SetU8(ftag,0x10); //1 fill bits, 0 linestyle bits SHAPE s; s.bits.fill = 1; s.bits.line = 0; swf_ShapeSetStyle(ftag,&s,0,1,0); + fillstylechanged = 1; int lastfill = fill; fill = 1; storefont = 1; - drawpath(ftag, outline[swfcharid2char[t]],&m); + drawpath(ftag, outline[swfcharid2char[t]],&m, 0); storefont = 0; fill = lastfill; swf_ShapeSetEnd(ftag); } + ftag = swf_InsertTag(ftag,ST_DEFINEFONTINFO); + swf_SetU16(ftag, this->swfid); + if(this->fontid) { + swf_SetU8(ftag, strlen(this->fontid)); + swf_SetBlock(ftag, (U8*)this->fontid, strlen(this->fontid)); + } else { + swf_SetU8(ftag, 0); + } + swf_SetU8(ftag, 0); //flags + for(t=0;tcharname[this->swfcharid2char[t]]; + for(s=0;s<256;s++) { + if(standardEncodingNames[s] && + !strcmp(name,standardEncodingNames[s])) + break; + } + swf_SetU8(ftag, (U8)s); + } } free(ptr); free(outline); for(t=0;tcharnum;t++) { + if(!strcmp(this->charname[t],name)) { + return this->width[t]; + } + } + return 0; +} + +int SWFFont::getSWFCharID(char*name, int charnr) { int t; for(t=0;tcharnum;t++) { @@ -645,7 +741,10 @@ int SWFFont::getSWFCharID(char*name) return char2swfcharid[t]; } } - logf(" Didn't find character '%s' in font '%s'", name, this->name); + if(this->standardtable && charnr>=0 && charnr < this->standardtablesize) { + return getSWFCharID(this->standardtable[charnr], -1); + } + logf(" Didn't find character '%s' in font '%s'", FIXNULL(name), this->name); return 0; } @@ -681,7 +780,7 @@ void swfoutput_setfont(struct swfoutput*obj, char*fontid, int t1id, char*filenam } if(t1id<0) { - logf(" internal error: t1id:%d, fontid:%s\n", t1id,fontid); + logf(" internal error: t1id:%d, fontid:%s\n", t1id,FIXNULL(fontid)); } SWFFont*font = new SWFFont(fontid, t1id, filename); @@ -726,7 +825,7 @@ void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12, } /* draws a character at x,y. */ -void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character) +void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character, int charnr) { swfmatrix m; m.m11 = obj->fontm11; @@ -735,7 +834,7 @@ void swfoutput_drawchar(struct swfoutput* obj,double x,double y,char*character) m.m22 = obj->fontm22; m.m13 = x; m.m23 = y; - drawchar(obj, obj->font, character, &m); + drawchar(obj, obj->font, character, charnr, &m); } /* initialize the swf writer */ @@ -777,7 +876,7 @@ void swfoutput_setprotected() //write PROTECT tag flag_protected = 1; } -void startshape(struct swfoutput*obj) +static void startshape(struct swfoutput*obj) { RGBA rgb; SRECT r; @@ -813,7 +912,7 @@ void startshape(struct swfoutput*obj) lastwasfill = 0; } -void starttext(struct swfoutput*obj) +static void starttext(struct swfoutput*obj) { SRECT r; MATRIX m; @@ -841,7 +940,7 @@ void starttext(struct swfoutput*obj) swflastx=swflasty=0; } -void endshape() +static void endshape() { if(shapeid<0) return; @@ -851,7 +950,7 @@ void endshape() shapeid = -1; } -void endtext() +static void endtext() { if(textid<0) return; @@ -862,7 +961,7 @@ void endtext() textid = -1; } -void endpage(struct swfoutput*obj) +static void endpage(struct swfoutput*obj) { if(shapeid>=0) endshape(); @@ -909,14 +1008,20 @@ void swfoutput_destroy(struct swfoutput* obj) fi = 1; // stdout if(fi<=0) { - logf(" Could not create \"%s\". ", filename); + logf(" Could not create \"%s\". ", FIXNULL(filename)); exit(1); } tag = swf_InsertTag(tag,ST_END); - if FAILED(swf_WriteSWF(fi,&swf)) - logf(" WriteSWF() failed.\n"); + if(enablezlib) { + if FAILED(swf_WriteSWC(fi,&swf)) + logf(" WriteSWC() failed.\n"); + } else { + if FAILED(swf_WriteSWF(fi,&swf)) + logf(" WriteSWF() failed.\n"); + } + if(filename) close(fi); logf(" SWF written\n"); @@ -943,9 +1048,9 @@ void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a) obj->fillrgb.g == g && obj->fillrgb.b == b && obj->fillrgb.a == a) return; - if(shapeid>=0) endshape(); + obj->fillrgb.r = r; obj->fillrgb.g = g; obj->fillrgb.b = b; @@ -1021,7 +1126,7 @@ void swfoutput_endclip(swfoutput*obj) swf_ObjectPlaceClip(cliptags[clippos],clipshapes[clippos],clipdepths[clippos],NULL,NULL,NULL,depth++); } -void drawlink(struct swfoutput*obj, ActionTAG*, swfcoord*points); +static void drawlink(struct swfoutput*obj, ActionTAG*,ActionTAG*, swfcoord*points, char mouseover); void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points) { @@ -1032,15 +1137,13 @@ void swfoutput_linktourl(struct swfoutput*obj, char*url, swfcoord*points) if(textid>=0) endtext(); - actions = swf_ActionStart(tag); if(opennewwindow) - action_GetUrl(url, "_parent"); + actions = action_GetUrl(0, url, "_parent"); else - action_GetUrl(url, "_this"); - action_End(); - swf_ActionEnd(); + actions = action_GetUrl(0, url, "_this"); + actions = action_End(actions); - drawlink(obj, actions, points); + drawlink(obj, actions, 0, points,0); } void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points) { @@ -1051,15 +1154,37 @@ void swfoutput_linktopage(struct swfoutput*obj, int page, swfcoord*points) if(textid>=0) endtext(); - actions = swf_ActionStart(tag); - action_GotoFrame(page); - action_End(); - swf_ActionEnd(); + actions = action_GotoFrame(0, page); + actions = action_End(actions); - drawlink(obj, actions, points); + drawlink(obj, actions, 0, points,0); } +void swfoutput_namedlink(struct swfoutput*obj, char*name, swfcoord*points) +{ + ActionTAG *actions1,*actions2; -void drawlink(struct swfoutput*obj, ActionTAG*actions, swfcoord*points) + if(shapeid>=0) + endshape(); + if(textid>=0) + endtext(); + + actions1 = action_PushString(0, "/:subtitle"); + actions1 = action_PushString(actions1, name); + actions1 = action_SetVariable(actions1); + actions1 = action_End(actions1); + + actions2 = action_PushString(0, "/:subtitle"); + actions2 = action_PushString(actions2, ""); + actions2 = action_SetVariable(actions2); + actions2 = action_End(actions2); + + drawlink(obj, actions1, actions2, points,1); + + swf_ActionFree(actions1); + swf_ActionFree(actions2); +} + +static void drawlink(struct swfoutput*obj, ActionTAG*actions1, ActionTAG*actions2, swfcoord*points, char mouseover) { RGBA rgb; SRECT r; @@ -1070,17 +1195,29 @@ void drawlink(struct swfoutput*obj, ActionTAG*actions, swfcoord*points) int myshapeid2; double xmin,ymin; double xmax=xmin=points[0].x,ymax=ymin=points[0].y; + double posx = 0; + double posy = 0; int t; int buttonid = ++currentswfid; for(t=1;t<4;t++) { - if(points[t].x>xmax) xmax=points[t].x; - if(points[t].y>ymax) ymax=points[t].y; - if(points[t].xxmax) xmax=points[t].x; + if(points[t].y>ymax) ymax=points[t].y; + if(points[t].xymax) ymax=y4; if(x4linewidth,&obj->strokergb); //fsid = ShapeAddSolidFillStyle(shape,&obj->fillrgb); - fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,0); + fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1); swf_SetU16(tag, myshapeid); r.xmin = (int)(xmin*20); r.ymin = (int)(ymin*20); @@ -1225,61 +1402,121 @@ void drawimage(struct swfoutput*obj, int bitid, int sizex,int sizey, swf_ObjectPlace(tag,myshapeid,/*depth*/depth++,NULL,NULL,NULL); } -int swfoutput_drawimagejpeg(struct swfoutput*obj, char*filename, int sizex,int sizey, +int swfoutput_drawimagejpeg_old(struct swfoutput*obj, char*filename, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4) { + TAG*oldtag; if(shapeid>=0) endshape(); if(textid>=0) endtext(); int bitid = ++currentswfid; + oldtag = tag; tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2); swf_SetU16(tag, bitid); - swf_SetJPEGBits(tag, filename, jpegquality); + if(swf_SetJPEGBits(tag, filename, jpegquality)<0) { + swf_DeleteTag(tag); + tag = oldtag; + return -1; + } drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4); return bitid; } +int swfoutput_drawimagejpeg(struct swfoutput*obj, RGBA*mem, int sizex,int sizey, + double x1,double y1, + double x2,double y2, + double x3,double y3, + double x4,double y4) +{ + TAG*oldtag; + JPEGBITS*jpeg; + + if(shapeid>=0) + endshape(); + if(textid>=0) + endtext(); + + int bitid = ++currentswfid; + oldtag = tag; + tag = swf_InsertTag(tag,ST_DEFINEBITSJPEG2); + swf_SetU16(tag, bitid); + swf_SetJPEGBits2(tag,sizex,sizey,mem,jpegquality); + drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4); + return bitid; +} + int swfoutput_drawimagelossless(struct swfoutput*obj, RGBA*mem, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, double x4,double y4) { + TAG*oldtag; if(shapeid>=0) endshape(); if(textid>=0) endtext(); int bitid = ++currentswfid; + oldtag = tag; tag = swf_InsertTag(tag,ST_DEFINEBITSLOSSLESS); swf_SetU16(tag, bitid); - swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT); + if(swf_SetLosslessBits(tag,sizex,sizey,mem, BMF_32BIT)<0) { + swf_DeleteTag(tag); + tag = oldtag; + return -1; + } drawimage(obj, bitid, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4); return bitid; } -int swfoutput_drawimagelossless256(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey, +int swfoutput_drawimagelosslessN(struct swfoutput*obj, U8*mem, RGBA*pal, int sizex,int sizey, double x1,double y1, double x2,double y2, double x3,double y3, - double x4,double y4) + double x4,double y4, int n) { + TAG*oldtag; + U8*mem2 = 0; if(shapeid>=0) endshape(); if(textid>=0) endtext(); + if(sizex&3) + { + /* SWF expects scanlines to be 4 byte aligned */ + int x,y; + U8*ptr; + mem2 = (U8*)malloc(BYTES_PER_SCANLINE(sizex)*sizey); + ptr = mem2; + for(y=0;y=0) endshape(); if(textid>=0)