From: kramm Date: Mon, 22 Oct 2001 15:43:31 +0000 (+0000) Subject: fonts now work. output size is a small fraction of what it used to be. X-Git-Tag: release-0-0-2~32 X-Git-Url: http://git.asbjorn.it/?a=commitdiff_plain;h=679bc1b62b72c098256a9bde8c49a61952efc069;p=swftools.git fonts now work. output size is a small fraction of what it used to be. --- diff --git a/pdf2swf/swfoutput.cc b/pdf2swf/swfoutput.cc index 2c99345..31b57ef 100644 --- a/pdf2swf/swfoutput.cc +++ b/pdf2swf/swfoutput.cc @@ -28,17 +28,25 @@ extern "C" { #include "../lib/rfxswf.h" } +int ignoredraworder=0; +int drawonlyshapes=0; +int jpegquality=85; + typedef unsigned char u8; typedef unsigned short int u16; typedef unsigned long int u32; +static int drawmode; static int fi; static int flag_protected; static SWF swf; static TAG *tag; -static int shapeid = -1; static int currentswfid = 0; + static SHAPE* shape; +static int shapeid = -1; +static int textid = -1; + static int fillstyleid; static int linestyleid; static int swflastx=0; @@ -48,6 +56,7 @@ static char* filename = 0; static int sizex; static int sizey; static char fill = 0; +static char storefont = 0; static int depth = 1; static int startdepth = 1; TAG* cliptags[128]; @@ -55,7 +64,13 @@ int clipshapes[128]; u32 clipdepths[128]; int clippos = 0; +int CHARMIDX = 0; +int CHARMIDY = 0; + void startshape(struct swfoutput* obj); +void starttext(struct swfoutput* obj); +void endshape(); +void endtext(); // matrix multiplication. changes p0 void transform (plotxy*p0,struct swfmatrix*m) @@ -68,7 +83,7 @@ void transform (plotxy*p0,struct swfmatrix*m) } // write a move-to command into the swf -void moveto(plotxy p0) +void moveto(TAG*tag, plotxy p0) { int rx = (int)(p0.x*20); int ry = (int)(p0.y*20); @@ -80,7 +95,7 @@ void moveto(plotxy p0) } // write a line-to command into the swf -void lineto(plotxy p0) +void lineto(TAG*tag, plotxy p0) { int rx = ((int)(p0.x*20)-swflastx); int ry = ((int)(p0.y*20)-swflasty); @@ -92,7 +107,7 @@ void lineto(plotxy p0) } // write a spline-to command into the swf -void splineto(plotxy control,plotxy end) +void splineto(TAG*tag, plotxy control,plotxy end) { int cx = ((int)(control.x*20)-swflastx); int cy = ((int)(control.y*20)-swflasty); @@ -107,17 +122,17 @@ void splineto(plotxy control,plotxy end) /* write a line, given two points and the transformation matrix. */ -void line(plotxy p0, plotxy p1, struct swfmatrix*m) +void line(TAG*tag, plotxy p0, plotxy p1, struct swfmatrix*m) { transform(&p0,m); transform(&p1,m); - moveto(p0); - lineto(p1); + moveto(tag, p0); + lineto(tag, p1); } /* write a cubic (!) spline. This involves calling the approximate() function out of spline.cc to convert it to a quadratic spline. */ -void spline(plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) +void spline(TAG*tag,plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) { double d; struct qspline q[16]; @@ -130,35 +145,52 @@ void spline(plotxy p0,plotxy p1,plotxy p2,plotxy p3,struct swfmatrix*m) num = approximate(p0,p1,p2,p3,q); for(t=0;tid != ST_DEFINEFONT && + tag->id != ST_DEFINESHAPE && + tag->id != ST_DEFINESHAPE2 && + tag->id != ST_DEFINESHAPE3) + { + 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; + int init=1; + if(log) printf("shape-start %d\n", fill); while (outline) { - logf(" Pathtype:%s",outline->type == T1_PATHTYPE_MOVE?"MOVE": - (outline->type == T1_PATHTYPE_LINE?"LINE" - :"BEZIER")); - logf(" relative coordinates: %08x,%08x", outline->dest.x, outline->dest.y); x += (outline->dest.x/(float)0xffff); y += (outline->dest.y/(float)0xffff); - logf(" coordinates: %f,%f", x, y); if(outline->type == T1_PATHTYPE_MOVE) { + if(((int)(lastx*20) != (int)(firstx*20) || + (int)(lasty*20) != (int)(firsty*20)) && + fill) + { + plotxy p0; + plotxy p1; + p0.x=lastx; + p0.y=lasty; + p1.x=firstx; + p1.y=firsty; + if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); + line(tag, p0, p1, m); + } + firstx=x; + firsty=y; } else if(outline->type == T1_PATHTYPE_LINE) { @@ -168,7 +200,8 @@ void drawpath(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint) p0.y=lasty; p1.x=x; p1.y=y; - line(p0,p1,m); + if(log) printf("line: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); + line(tag, p0,p1,m); } else if(outline->type == T1_PATHTYPE_BEZIER) { @@ -185,7 +218,8 @@ void drawpath(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint) p2.y=o2->B.y/(float)0xffff+lasty; p3.x=lastx; p3.y=lasty; - spline(p0,p1,p2,p3,m); + if(log) printf("spline: %f,%f -> %f,%f\n",p3.x,p3.y,p0.x,p0.y); + spline(tag,p0,p1,p2,p3,m); } else { logf(" drawpath: unknown outline type:%d\n", outline->type); @@ -194,42 +228,248 @@ void drawpath(T1_OUTLINE*outline, struct swfmatrix*m, char*namehint) lasty=y; outline = outline->link; } + if(((int)(lastx*20) != (int)(firstx*20) || + (int)(lasty*20) != (int)(firsty*20)) && + fill) + { + plotxy p0; + plotxy p1; + p0.x=lastx; + p0.y=lasty; + p1.x=firstx; + p1.y=firsty; + if(log) printf("fix: %f,%f -> %f,%f\n",p0.x,p0.y,p1.x,p1.y); + line(tag, p0, p1, m); + } + if(log) printf("shape-end\n"); } - //logf(" Font name is %s", T1_GetFontFileName(t1fontindex)); - //logf(" char 0x%02x is named %s\n",character,charname); - //logf(" bbox: %d %d %d %d\n",bbox.llx,bbox.lly,bbox.urx,bbox.ury); - //char*charname = T1_GetCharName(t1fontindex, character); -/* process a character. */ -void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) +int colorcompare(RGBA*a,RGBA*b) { - T1_OUTLINE*outline = font->getOutline(character); - char* charname = character; - if(!outline) { - logf("Didn't find %s in current charset", character); - return; + if(a->r!=b->r || + a->g!=b->g || + a->b!=b->b || + a->a!=b->a) { + return 0; } - - swfmatrix m2=*m; - m2.m11/=100; - m2.m21/=100; - m2.m12/=100; - m2.m22/=100; + return 1; +} - if(shapeid<0) - startshape(obj); +static const int CHARDATAMAX = 1024; +struct chardata { + int charid; + int fontid; + int x; + int y; + int size; + RGBA color; +} chardata[CHARDATAMAX]; +int chardatapos = 0; + +int once=0; +void putcharacters(TAG*tag) +{ + int t; + SWFFONT font; + RGBA color; + color.r = chardata[0].color.r^255; + color.g = 0; + color.b = 0; + color.a = 0; + int lastfontid; + int lastx; + int lasty; + int lastsize; + int charids[128]; + int charadvance[128]; + int charstorepos; + int pass; + int glyphbits=1; //TODO: can this be zero? + int advancebits=1; + + if(tag->id != ST_DEFINETEXT && + tag->id != ST_DEFINETEXT2) { + logf(" internal error: putcharacters needs an text tag, not %d\n",tag->id); + exit(1); + } + + for(pass = 0; pass < 2; pass++) + { + charstorepos = 0; + lastfontid = -1; + lastx = CHARMIDX; + lasty = CHARMIDY; + lastsize = -1; + + if(pass==1) + { + advancebits++; + SetU8(tag, glyphbits); + SetU8(tag, advancebits); + } + + for(t=0;t<=chardatapos;t++) + { + if(lastfontid != chardata[t].fontid || + lastx!=chardata[t].x || + lasty!=chardata[t].y || + !colorcompare(&color, &chardata[t].color) || + charstorepos==127 || + lastsize != chardata[t].size || + t == chardatapos) + { + if(charstorepos && pass==0) + { + int s; + for(s=0;s=(1<=(1<bitcount = 0; + SetBits(tag, 0, 1); // GLYPH Record + SetBits(tag, charstorepos, 7); // one glyph + int s; + for(s=0;sbitcount = 0; + TextSetInfoRecord(tag, newfont, chardata[t].size, newcolor, newx,newy); + } + + lastfontid = chardata[t].fontid; + lastx = chardata[t].x; + lasty = chardata[t].y; + lastsize = chardata[t].size; + } + + if(t==chardatapos) + break; + + int advance; + int nextt = t==chardatapos-1?t:t+1; + int rel = chardata[nextt].x-chardata[t].x; + if(rel>=0 && (rel<(1<<(advancebits-1)) || pass==0)) { + advance = rel; + lastx=chardata[nextt].x; + } + else { + advance = 0; + lastx=chardata[t].x; + } + charids[charstorepos] = chardata[t].charid; + charadvance[charstorepos] = advance; + charstorepos ++; + } + } + chardatapos = 0; +} + +void putcharacter(struct swfoutput*obj, int fontid, int charid, int x,int y, int size) +{ + if(chardatapos == CHARDATAMAX) + { + endtext(); + starttext(obj); + } + chardata[chardatapos].fontid = fontid; + chardata[chardatapos].charid = charid; + chardata[chardatapos].x = x; + chardata[chardatapos].y = y; + chardata[chardatapos].color = obj->fillrgb; + chardata[chardatapos].size = size; + chardatapos++; +} - if(!lastwasfill) - ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); - lastwasfill = 1; - drawpath(outline, &m2, charname); +/* process a character. */ +void drawchar(struct swfoutput*obj, SWFFont*font, char*character, swfmatrix*m) +{ + int usefonts=1; + if(m->m12!=0 || m->m21!=0) + usefonts=0; + if(m->m11 != m->m22) + usefonts=0; + + if(usefonts && ! drawonlyshapes) + { + int charid = font->getSWFCharID(character); + if(shapeid>=0) + endshape(); + if(textid<0) + starttext(obj); + putcharacter(obj, font->swfid, charid, (int)(m->m13*20),(int)(m->m23*20), + (int)(m->m11*20/2+0.5)); //where does the /2 come from? + } + else + { + T1_OUTLINE*outline = font->getOutline(character); + char* charname = character; + + if(!outline) { + logf("Didn't find %s in current charset (%s)", character,font->getName()); + return; + } + + swfmatrix m2=*m; + m2.m11/=100; + m2.m21/=100; + m2.m12/=100; + m2.m22/=100; + + if(textid>=0) + endtext(); + if(shapeid<0) + startshape(obj); + + if(!lastwasfill) + ShapeSetStyle(tag,shape,0x8000,fillstyleid,0); + lastwasfill = 1; + + int lf = fill; + fill = 1; + drawpath(tag, outline, &m2); + fill = lf; + } } /* draw a curved polygon. */ void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m) { + if(textid>=0) + endtext(); if(shapeid<0) startshape(output); @@ -244,9 +484,11 @@ void swfoutput_drawpath(swfoutput*output, T1_OUTLINE*outline, struct swfmatrix*m lastwasfill = 1; } - drawpath(outline,m, 0); + drawpath(tag, outline,m); } +/* SWFFont: copy all t1 font outlines to a local + array. */ SWFFont::SWFFont(char*name, int id, char*filename) { if(!T1_GetFontName(id)) @@ -265,18 +507,19 @@ SWFFont::SWFFont(char*name, int id, char*filename) this->charnum = t; if(!t) return; - logf(" Font %s(%d): Storing %d outlines.\n", name, id, t); + logf(" Font %s(%d): Storing %d outlines.\n", name, id, t); 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); + swfcharpos = 0; + memset(used,0,t*sizeof(char)); - /* - tag = InsertTag(tag,ST_DEFINEFONT); - SetU16(tag, ++currentswfid); - this->swfid = currentswfid; - */ + this->swfid = ++currentswfid; + t=0; while(*a) @@ -310,12 +553,59 @@ SWFFont::SWFFont(char*name, int id, char*filename) } } +/* free all tables, write out definefont tags */ SWFFont::~SWFFont() { - int t,s=0; + int t,usednum=0; + int*ptr = (int*)malloc(swfcharpos*sizeof(int)); + for(t=0;t Font %s has %d used characters",fontid, s); + if(used[t]) usednum++; + + if(usednum && !drawonlyshapes) + { + logf(" Font %s has %d used characters",fontid, usednum); + TAG*ftag = InsertTag(swf.FirstTag,ST_DEFINEFONT); + SetU16(ftag, this->swfid); + int initpos = GetDataSize(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]] = GetDataSize(ftag)-initpos; + swflastx=0; + swflasty=0; + SetU8(ftag,0x10); //0 fill bits, 0 linestyle bits + SHAPE s; + s.bits.fill = 1; + s.bits.line = 0; + ShapeSetStyle(ftag,&s,0,1,0); + int lastfill = fill; + fill = 1; + storefont = 1; + drawpath(ftag, outline[swfcharid2char[t]],&m); + storefont = 0; + fill = lastfill; + ShapeSetEnd(ftag); + } + } + + free(ptr); + free(outline); + for(t=0;tcharnum;t++) { if(!strcmp(this->charname[t],name)) { - used[t] = 1; + + if(!used[t]) + { + swfcharid2char[swfcharpos] = t; + char2swfcharid[t] = swfcharpos; + swfcharpos++; + used[t] = 1; + } return outline[t]; } } return 0; } +int SWFFont::getSWFCharID(char*name) +{ + int t; + for(t=0;tcharnum;t++) { + if(!strcmp(this->charname[t],name)) { + + if(!used[t]) + { + swfcharid2char[swfcharpos] = t; + char2swfcharid[t] = swfcharpos++; + used[t] = 1; + } + return char2swfcharid[t]; + } + } + return 0; +} + char*SWFFont::getName() { return this->name; @@ -393,6 +708,13 @@ int swfoutput_queryfont(struct swfoutput*obj, char*fontid) void swfoutput_setfontmatrix(struct swfoutput*obj,double m11,double m12, double m21,double m22) { + if(obj->fontm11 == m11 && + obj->fontm12 == m12 && + obj->fontm21 == m21 && + obj->fontm22 == m22) + return; +// if(textid>=0) +// endtext(); obj->fontm11 = m11; obj->fontm12 = m12; obj->fontm21 = m21; @@ -456,6 +778,10 @@ void startshape(struct swfoutput*obj) { RGBA rgb; SRECT r; + + if(textid>=0) + endtext(); + tag = InsertTag(tag,ST_DEFINESHAPE); NewShape(&shape); @@ -484,6 +810,34 @@ void startshape(struct swfoutput*obj) lastwasfill = 0; } +void starttext(struct swfoutput*obj) +{ + SRECT r; + MATRIX m; + if(shapeid>=0) + endshape(); + tag = InsertTag(tag,ST_DEFINETEXT); + textid = ++currentswfid; + SetU16(tag, textid); + + r.xmin = 0; + r.ymin = 0; + r.xmax = 20*sizex; + r.ymax = 20*sizey; + + SetRect(tag,&r); + + m.sx = 65536; + m.sy = 65536; + m.r0 = 0; + m.r1 = 0; + m.tx = 0; + m.ty = 0; + + SetMatrix(tag,&m); + swflastx=swflasty=0; +} + void endshape() { if(shapeid<0) @@ -494,10 +848,23 @@ void endshape() shapeid = -1; } +void endtext() +{ + if(textid<0) + return; + putcharacters(tag); + SetU8(tag,0); + tag = InsertTag(tag,ST_PLACEOBJECT2); + ObjectPlace(tag,textid,/*depth*/depth++,NULL,NULL,NULL); + textid = -1; +} + void endpage(struct swfoutput*obj) { if(shapeid>=0) endshape(); + if(textid>=0) + endtext(); while(clippos) swfoutput_endclip(obj); tag = InsertTag(tag,ST_SHOWFRAME); @@ -521,11 +888,13 @@ void swfoutput_newpage(struct swfoutput*obj) void swfoutput_destroy(struct swfoutput* obj) { endpage(obj); - fontlist_t *iterator = fontlist; + fontlist_t *tmp,*iterator = fontlist; while(iterator) { delete iterator->font; iterator->font = 0; + tmp = iterator; iterator = iterator->next; + delete tmp; } T1_CloseLib(); @@ -547,11 +916,12 @@ void swfoutput_destroy(struct swfoutput* obj) logf(" WriteSWF() failed.\n"); if(filename) close(fi); - printf("SWF written\n"); + logf(" SWF written\n"); } void swfoutput_setdrawmode(swfoutput* obj, int mode) { + drawmode = mode; if(mode == DRAWMODE_FILL) fill = 1; else if(mode == DRAWMODE_EOFILL) @@ -571,7 +941,7 @@ void swfoutput_setfillcolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a) obj->fillrgb.b == b && obj->fillrgb.a == a) return; - if(shape>=0) + if(shapeid>=0) endshape(); obj->fillrgb.r = r; obj->fillrgb.g = g; @@ -586,7 +956,7 @@ void swfoutput_setstrokecolor(swfoutput* obj, u8 r, u8 g, u8 b, u8 a) obj->strokergb.b == b && obj->strokergb.a == a) return; - if(shape>=0) + if(shapeid>=0) endshape(); obj->strokergb.r = r; obj->strokergb.g = g; @@ -599,7 +969,7 @@ void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth) if(obj->linewidth == (u16)(linewidth*20)) return; - if(shape>=0) + if(shapeid>=0) endshape(); obj->linewidth = (u16)(linewidth*20); } @@ -607,7 +977,9 @@ void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth) void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m) { - if(shape>=0) + if(textid>=0) + endtext(); + if(shapeid>=0) endshape(); if(clippos >= 127) @@ -617,11 +989,10 @@ void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m) } startshape(obj); - swfoutput_setdrawmode(obj, DRAWMODE_CLIP); swfoutput_drawpath(obj, outline, m); - ShapeSetEnd(tag); + tag = InsertTag(tag,ST_PLACEOBJECT2); cliptags[clippos] = tag; clipshapes[clippos] = shapeid; @@ -632,7 +1003,9 @@ void swfoutput_startclip(swfoutput*obj, T1_OUTLINE*outline, struct swfmatrix*m) void swfoutput_endclip(swfoutput*obj) { - if(shape>=0) + if(textid>=0) + endtext(); + if(shapeid>=0) endshape(); if(!clippos) { @@ -649,6 +1022,11 @@ void swfoutput_drawimagefile(struct swfoutput*, char*filename, int sizex,int siz double x3,double y3, double x4,double y4) { + if(shapeid>=0) + endshape(); + if(textid>=0) + endtext(); + RGBA rgb; SRECT r; int lsid=0; @@ -686,16 +1064,13 @@ void swfoutput_drawimagefile(struct swfoutput*, char*filename, int sizex,int siz m.tx = (int)(x1*20); m.ty = (int)(y1*20); - - if(shape>=0) - endshape(); bitid = ++currentswfid; /* bitmap */ tag = InsertTag(tag,ST_DEFINEBITSJPEG2); SetU16(tag, bitid); - SetJPEGBits(tag, filename, 85); + SetJPEGBits(tag, filename, jpegquality); /* shape */ myshapeid = ++currentswfid; @@ -715,11 +1090,11 @@ void swfoutput_drawimagefile(struct swfoutput*, char*filename, int sizex,int siz SetShapeBits(tag,shape); ShapeSetAll(tag,shape,/*x*/0,/*y*/0,lsid,fsid,0); swflastx = swflasty = 0; - moveto(p1); - lineto(p2); - lineto(p3); - lineto(p4); - lineto(p1); + moveto(tag, p1); + lineto(tag, p2); + lineto(tag, p3); + lineto(tag, p4); + lineto(tag, p1); /* ShapeMoveTo (tag, shape, (int)(x1*20),(int)(y1*20)); ShapeSetLine (tag, shape, (int)(x1*20);