X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fdevices%2Fswf.c;h=b090c7bfe52e10b261da2963eea36c703f37f148;hp=4f691b604020a820e791a0503542886827a352a3;hb=7fb4a4ac393f19a0b8a8998a2f1deac88c97eda0;hpb=2e5b799fa6e0fe9ef61a168e9d1d107ca7f17e32 diff --git a/lib/devices/swf.c b/lib/devices/swf.c index 4f691b6..b090c7b 100644 --- a/lib/devices/swf.c +++ b/lib/devices/swf.c @@ -42,7 +42,7 @@ #include "../gfxtools.h" #include "swf.h" #include "../gfxpoly.h" -#include "../png.h" +#include "../gfximage.h" #define CHARDATAMAX 1024 #define CHARMIDX 0 @@ -102,6 +102,7 @@ typedef struct _swfoutput_internal int config_storeallcharacters; int config_enablezlib; int config_insertstoptag; + int config_showimages; int config_watermark; int config_noclips; int config_flashversion; @@ -114,6 +115,7 @@ typedef struct _swfoutput_internal int config_bboxvars; int config_disable_polygon_conversion; int config_normalize_polygon_positions; + int config_alignfonts; char config_disablelinks; RGBA config_linkcolor; float config_minlinewidth; @@ -203,6 +205,8 @@ typedef struct _swfoutput_internal char* mark; } swfoutput_internal; + +static const int NO_FONT3=0; static void swf_fillbitmap(gfxdevice_t*driver, gfxline_t*line, gfximage_t*img, gfxmatrix_t*move, gfxcxform_t*cxform); static int swf_setparameter(gfxdevice_t*driver, const char*key, const char*value); @@ -537,7 +541,7 @@ static inline int colorcompare(RGBA*a,RGBA*b) return 1; } -static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m) +static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m, int flashversion) { SRECT r; char debug = 0; @@ -546,17 +550,19 @@ static SRECT getcharacterbbox(chararray_t*chardata, MATRIX* m) int t; if(debug) printf("\n"); + double div = 1.0 / 1024.0; + if(flashversion>=8 && !NO_FONT3) { + div = 1.0 / 20480.0; + } + while(chardata) { for(t=0;tpos;t++) { charatposition_t*chr = &chardata->chr[t]; SRECT b = chr->font->layout->bounds[chr->charid]; - b.xmin *= chr->size; - b.ymin *= chr->size; - b.xmax *= chr->size; - b.ymax *= chr->size; - - /* divide by 1024, rounding xmax/ymax up */ - b.xmax += 1023; b.ymax += 1023; b.xmin /= 1024; b.ymin /= 1024; b.xmax /= 1024; b.ymax /= 1024; + b.xmin = floor((b.xmin*(double)chr->size) *div); + b.ymin = floor((b.ymin*(double)chr->size) *div); + b.xmax = ceil((b.xmax*(double)chr->size) *div); + b.ymax = ceil((b.ymax*(double)chr->size) *div); b.xmin += chr->x; b.ymin += chr->y; @@ -619,6 +625,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) int lastx; int lasty; int lastsize; + int lastchar; int charids[128]; int charadvance[128]; int charstorepos; @@ -642,6 +649,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) lastx = CHARMIDX; lasty = CHARMIDY; lastsize = -1; + lastchar = -1; if(pass==1) { @@ -666,9 +674,9 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) charatposition_t*chr = &chardata->chr[t]; - if(lastfont != chardata->chr[t].font || - lastx!=chardata->chr[t].x || - lasty!=chardata->chr[t].y || + if(lastfont != chr->font || + lastx!=chr->x || + lasty!=chr->y || !colorcompare(&color, &chardata->chr[t].color) || charstorepos==127 || lastsize != chardata->chr[t].size || @@ -725,7 +733,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) newfont = &font; tag->writeBit = 0; // Q&D - swf_TextSetInfoRecord(tag, newfont, chr->size, newcolor, newx,newy); + swf_TextSetInfoRecord(tag, newfont, chr->size, newcolor, newx, newy); } lastfont = chr->font; @@ -741,7 +749,7 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) if(tpos-1) nextx = chardata->chr[t+1].x; if(t==chardata->pos-1 && chardata->next) nextx = chardata->next->chr[0].x; int dx = nextx-chr->x; - + int advance; if(dx>=0 && (dx<(1<<(advancebits-1)) || pass==0)) { advance = dx; @@ -750,8 +758,10 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag) advance = 0; lastx=chr->x; } + charids[charstorepos] = chr->charid; charadvance[charstorepos] = advance; + lastchar = chr->charid; charstorepos ++; } chardata = chardata->next; @@ -814,7 +824,7 @@ static void chararray_writetodev(gfxdevice_t*dev, chararray_t*array, MATRIX*matr i->tag = swf_InsertTag(i->tag,ST_DEFINETEXT2); swf_SetU16(i->tag, textid); SRECT r; - r = getcharacterbbox(array, matrix); + r = getcharacterbbox(array, matrix, i->config_flashversion); r = swf_ClipRect(i->pagebbox, r); swf_SetRect(i->tag,&r); swf_SetMatrix(i->tag, matrix); @@ -834,6 +844,8 @@ static void chararray_writetodev(gfxdevice_t*dev, chararray_t*array, MATRIX*matr swf_SetU32(i->tag, 0);//thickness swf_SetU32(i->tag, 0);//sharpness + //swf_SetU32(i->tag, 0x20000);//thickness + //swf_SetU32(i->tag, 0x800000);//sharpness swf_SetU8(i->tag, 0);//reserved } if(invisible && i->config_flashversion>=8) { @@ -865,45 +877,6 @@ static void endtext(gfxdevice_t*dev) i->textmode = 0; } -/* sets the matrix which is to be applied to characters drawn by swfoutput_drawchar() */ -static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,double m22,double x, double y, char force) -{ - m11 *= 1024; - m12 *= 1024; - m21 *= 1024; - m22 *= 1024; - swfoutput_internal*i = (swfoutput_internal*)dev->internal; - if(i->lastfontm11 == m11 && - i->lastfontm12 == m12 && - i->lastfontm21 == m21 && - i->lastfontm22 == m22 && !force) - return; - if(i->textmode) - endtext(dev); - - i->lastfontm11 = m11; - i->lastfontm12 = m12; - i->lastfontm21 = m21; - i->lastfontm22 = m22; - - double xsize = sqrt(m11*m11 + m12*m12); - double ysize = sqrt(m21*m21 + m22*m22); - i->current_font_size = (xsize>ysize?xsize:ysize)*1; - if(i->current_font_size < 1) - i->current_font_size = 1; - double ifs = 1.0 / (i->current_font_size*GLYPH_SCALE); - - MATRIX m; - m.sx = (S32)((m11*ifs)*65536); m.r1 = (S32)((m21*ifs)*65536); - m.r0 = (S32)((m12*ifs)*65536); m.sy = (S32)((m22*ifs)*65536); - /* this is the position of the first char to set a new fontmatrix- - we hope that it's close enough to all other characters using the - font, so we use its position as origin for the matrix */ - m.tx = x*20; - m.ty = y*20; - i->fontmatrix = m; -} - static int watermark2_width=47; static int watermark2_height=11; static int watermark2[47] = {95,1989,71,0,2015,337,1678,0,2015,5,1921,320,1938,25,2006,1024, @@ -983,6 +956,7 @@ static void endpage(gfxdevice_t*dev) swfoutput_internal*i = (swfoutput_internal*)dev->internal; if(i->pagefinished) return; + if(i->shapeid>=0) endshape(dev); if(i->textmode) @@ -1498,6 +1472,8 @@ void swfoutput_finalize(gfxdevice_t*dev) endpage(dev); fontlist_t *iterator = i->fontlist; + char use_font3 = i->config_flashversion>=8 && !NO_FONT3; + while(iterator) { TAG*mtag = i->swf->firstTag; if(iterator->swffont) { @@ -1507,16 +1483,25 @@ void swfoutput_finalize(gfxdevice_t*dev) } int used = iterator->swffont->use && iterator->swffont->use->used_glyphs; if(used) { - mtag = swf_InsertTag(mtag, ST_DEFINEFONT2); - swf_FontSetDefine2(mtag, iterator->swffont); + if(!use_font3) { + mtag = swf_InsertTag(mtag, ST_DEFINEFONT2); + swf_FontSetDefine2(mtag, iterator->swffont); + } else { + mtag = swf_InsertTag(mtag, ST_DEFINEFONT3); + swf_FontSetDefine2(mtag, iterator->swffont); + } } } iterator = iterator->next; } - + i->tag = swf_InsertTag(i->tag,ST_END); TAG* tag = i->tag->prev; + + if(use_font3 && i->config_storeallcharacters && i->config_alignfonts) { + swf_FontPostprocess(i->swf); // generate alignment information + } /* remove the removeobject2 tags between the last ST_SHOWFRAME and the ST_END- they confuse the flash player */ @@ -2137,6 +2122,10 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value) i->config_dumpfonts = atoi(value); } else if(!strcmp(name, "animate")) { i->config_animate = atoi(value); + } else if(!strcmp(name, "linknameurl")) { + i->config_linknameurl = atoi(value); + } else if(!strcmp(name, "showimages")) { + i->config_showimages = atoi(value); } else if(!strcmp(name, "disablelinks")) { i->config_disablelinks = atoi(value); } else if(!strcmp(name, "simpleviewer")) { @@ -2180,7 +2169,7 @@ int swf_setparameter(gfxdevice_t*dev, const char*name, const char*value) printf("linkcolor==7)\n"); + printf("enablezlib switch on zlib compression (also done if flashversion>=6)\n"); printf("bboxvars store the bounding box of the SWF file in actionscript variables\n"); printf("dots Take care to handle dots correctly\n"); printf("reordertags=0/1 (default: 1) perform some tag optimizations\n"); @@ -2272,7 +2261,9 @@ static int add_image(swfoutput_internal*i, gfximage_t*img, int targetwidth, int if(newsizex Scaling %dx%d image to %dx%d", sizex, sizey, newsizex, newsizey); - newpic = swf_ImageScale(mem, sizex, sizey, newsizex, newsizey); + gfximage_t*ni = gfximage_rescale(img, newsizex, newsizey); + newpic = (RGBA*)ni->data; + free(ni); *newwidth = sizex = newsizex; *newheight = sizey = newsizey; mem = newpic; @@ -2374,6 +2365,11 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm SHAPE*shape; swf_ShapeNew(&shape); int fsid = swf_ShapeAddBitmapFillStyle(shape,&m,bitid,1); + int lsid = 0; + if(i->config_showimages) { + RGBA pink = {255,255,0,255}; + lsid = swf_ShapeAddLineStyle(shape, 20, &pink); + } swf_SetU16(i->tag, myshapeid); SRECT r = gfxline_getSWFbbox(line); r = swf_ClipRect(i->pagebbox, r); @@ -2381,7 +2377,7 @@ static void swf_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxm swf_SetShapeStyles(i->tag,shape); swf_ShapeCountBits(shape,NULL,NULL); swf_SetShapeBits(i->tag,shape); - swf_ShapeSetAll(i->tag,shape,UNDEFINED_COORD,UNDEFINED_COORD,0,fsid,0); + swf_ShapeSetAll(i->tag,shape,UNDEFINED_COORD,UNDEFINED_COORD,lsid,fsid,0); i->swflastx = i->swflasty = UNDEFINED_COORD; drawgfxline(dev, line, 1); swf_ShapeSetEnd(i->tag); @@ -2810,13 +2806,13 @@ static void swf_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*grad swf_FreeGradient(swfgradient);free(swfgradient); } -static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) +static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id, int version) { SWFFONT*swffont = (SWFFONT*)rfx_calloc(sizeof(SWFFONT)); int t; SRECT bounds = {0,0,0,0}; swffont->id = -1; - swffont->version = 2; + swffont->version = version; swffont->name = (U8*)strdup(id); swffont->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT)); swffont->layout->ascent = 0; @@ -2830,21 +2826,26 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) swffont->glyph2ascii = (U16*)rfx_calloc(sizeof(U16)*swffont->numchars); swffont->glyph = (SWFGLYPH*)rfx_calloc(sizeof(SWFGLYPH)*swffont->numchars); swffont->glyphnames = (char**)rfx_calloc(sizeof(char*)*swffont->numchars); - for(t=0;tmax_unicode;t++) { - swffont->ascii2glyph[t] = font->unicode2glyph[t]; - } + SRECT max = {0,0,0,0}; for(t=0;tnum_glyphs;t++) { drawer_t draw; gfxline_t*line; double advance = 0; - swffont->glyph2ascii[t] = font->glyphs[t].unicode; - if(swffont->glyph2ascii[t] == 0xffff || swffont->glyph2ascii[t] == 0x0000) { + int u = font->glyphs[t].unicode; + int s; + char twice=0; + for(s=0;snum_glyphs;s++) { + if(swffont->glyph2ascii[s]==u) + twice=1; + } + if(u >= 0xe000 || u == 0x0000 || twice) { /* flash 8 flashtype requires unique unicode IDs for each character. We use the Unicode private user area to assign characters, hoping that the font doesn't contain more than 2048 glyphs */ - swffont->glyph2ascii[t] = 0xe000 + (t&0x1fff); + u = 0xe000 + (t&0x1fff); } + swffont->glyph2ascii[t] = u; if(font->glyphs[t].name) { swffont->glyphnames[t] = strdup(font->glyphs[t].name); @@ -2856,10 +2857,17 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) swf_Shape01DrawerInit(&draw, 0); line = font->glyphs[t].line; + const double scale = GLYPH_SCALE; while(line) { FPOINT c,to; - c.x = line->sx * GLYPH_SCALE; c.y = line->sy * GLYPH_SCALE; - to.x = line->x * GLYPH_SCALE; to.y = line->y * GLYPH_SCALE; + c.x = line->sx * scale; c.y = -line->sy * scale; + //to.x = floor(line->x * scale); to.y = floor(-line->y * scale); + to.x = line->x * scale; to.y = -line->y * scale; + + /*if(strstr(swffont->name, "BIRNU") && t==90) { + to.x += 1; + }*/ + if(line->type == gfx_moveTo) { draw.moveTo(&draw, &to); } else if(line->type == gfx_lineTo) { @@ -2888,6 +2896,7 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) swf_ExpandRect2(&bounds, &swffont->layout->bounds[t]); } + for(t=0;tnum_glyphs;t++) { SRECT bbox = swffont->layout->bounds[t]; @@ -2915,12 +2924,8 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) The baseline is defined as the y-position zero */ - swffont->layout->ascent = -bounds.ymin; - if(swffont->layout->ascent < 0) - swffont->layout->ascent = 0; - swffont->layout->descent = bounds.ymax; - if(swffont->layout->descent < 0) - swffont->layout->descent = 0; + swffont->layout->ascent = bounds.ymin<0?-bounds.ymin:0; + swffont->layout->descent = bounds.ymax>0?bounds.ymax:0; swffont->layout->leading = bounds.ymax - bounds.ymin; /* if the font has proper ascent/descent values (>0) and those define @@ -2931,6 +2936,7 @@ static SWFFONT* gfxfont_to_swffont(gfxfont_t*font, const char* id) if(font->descent*20 > swffont->layout->descent) swffont->layout->descent = font->descent*20; + swf_FontSort(swffont); return swffont; } @@ -2950,7 +2956,7 @@ static void swf_addfont(gfxdevice_t*dev, gfxfont_t*font) l = l->next; } l = (fontlist_t*)rfx_calloc(sizeof(fontlist_t)); - l->swffont = gfxfont_to_swffont(font, font->id); + l->swffont = gfxfont_to_swffont(font, font->id, (i->config_flashversion>=8 && !NO_FONT3)?3:2); l->next = 0; if(last) { last->next = l; @@ -2977,11 +2983,6 @@ static void swf_addfont(gfxdevice_t*dev, gfxfont_t*font) l->swffont->layout->bounds[iii].xmax/20.0, l->swffont->layout->bounds[iii].ymax/20.0 ); - int t; - for(t=0;tswffont->maxascii;t++) { - if(l->swffont->ascii2glyph[t] == iii) - msg(" | - maps to %d",t); - } } } } @@ -3005,6 +3006,56 @@ static void swf_switchfont(gfxdevice_t*dev, const char*fontid) return; } +/* sets the matrix which is to be applied to characters drawn by swfoutput_drawchar() */ +static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,double m22,double x, double y, char force) +{ + m11 *= 1024; + m12 *= 1024; + m21 *= 1024; + m22 *= 1024; + swfoutput_internal*i = (swfoutput_internal*)dev->internal; + if(i->lastfontm11 == m11 && + i->lastfontm12 == m12 && + i->lastfontm21 == m21 && + i->lastfontm22 == m22 && !force) + return; + if(i->textmode) + endtext(dev); + + i->lastfontm11 = m11; + i->lastfontm12 = m12; + i->lastfontm21 = m21; + i->lastfontm22 = m22; + + double xsize = sqrt(m11*m11 + m12*m12); + double ysize = sqrt(m21*m21 + m22*m22); + + int extrazoom = 1; + if(i->config_flashversion>=8 && !NO_FONT3) + extrazoom = 20; + + i->current_font_size = (xsize>ysize?xsize:ysize)*extrazoom; + if(i->current_font_size < 1) + i->current_font_size = 1; + + MATRIX m; + swf_GetMatrix(0, &m); + + if(m21 || m12 || fabs(m11+m22)>0.001) { + double ifs = (double)extrazoom/(i->current_font_size); + m.sx = (S32)((m11*ifs)*65536); m.r1 = -(S32)((m21*ifs)*65536); + m.r0 = (S32)((m12*ifs)*65536); m.sy = -(S32)((m22*ifs)*65536); + } + + /* this is the position of the first char to set a new fontmatrix- + we hope that it's close enough to all other characters using the + font, so we use its position as origin for the matrix */ + m.tx = x*20; + m.ty = y*20; + i->fontmatrix = m; +} + + static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix) { swfoutput_internal*i = (swfoutput_internal*)dev->internal; @@ -3035,6 +3086,7 @@ static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t* msg(" No character %d in font %s (%d chars)", glyph, FIXNULL((char*)i->swffont->name), i->swffont->numchars); return; } + glyph = i->swffont->glyph2glyph[glyph]; setfontscale(dev, matrix->m00, matrix->m01, matrix->m10, matrix->m11, matrix->tx, matrix->ty, 0); @@ -3088,6 +3140,6 @@ static void swf_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t* } else { i->chardata = charbuffer_append(i->chardata, i->swffont, glyph, x, y, i->current_font_size, *(RGBA*)color, &i->fontmatrix); } - swf_FontUseGlyph(i->swffont, glyph); + swf_FontUseGlyph(i->swffont, glyph, i->current_font_size); return; }