#include <string.h>
#include "../../config.h"
#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
#ifdef HAVE_ASSERT_H
#include <assert.h>
#else
#define assert(a)
#endif
#include <math.h>
+#include "../mem.h"
#include "../log.h"
#include "../rfxswf.h"
#include "../gfxdevice.h"
#include "../gfxtools.h"
#include "../art/libart.h"
-#include "artsutils.c"
+#include "swf.h"
+#include "artsutils.h"
#define CHARDATAMAX 8192
#define CHARMIDX 0
int config_drawonlyshapes;
int config_jpegquality;
int config_storeallcharacters;
- int config_generate_fake_tags;
int config_enablezlib;
int config_insertstoptag;
int config_flashversion;
i->config_jpegquality=85;
i->config_storeallcharacters=0;
i->config_enablezlib=0;
- i->config_generate_fake_tags=0;
i->config_insertstoptag=0;
i->config_flashversion=6;
i->config_framerate=0.25;
If we set it to low, however, the char positions will be inaccurate */
#define GLYPH_SCALE 1
-/* process a character. */
-static int drawchar(gfxdevice_t*dev, SWFFONT *swffont, int charid, float x, float y, gfxcolor_t*col)
-{
- swfoutput_internal*i = (swfoutput_internal*)dev->internal;
- if(!swffont) {
- msg("<warning> Font is NULL");
- return 0;
- }
-
- if(charid<0 || charid>=swffont->numchars) {
- msg("<warning> No character %d in font %s (%d chars)", charid, FIXNULL((char*)swffont->name), swffont->numchars);
- return 0;
- }
- /*if(swffont->glyph[charid].shape->bitlen <= 16) {
- msg("<warning> Glyph %d in current charset (%s, %d characters) is empty",
- charid, FIXNULL((char*)swffont->name), swffont->numchars);
- return 1;
- }*/
-
- if(i->shapeid>=0)
- endshape(dev);
- if(i->textid<0)
- starttext(dev);
-
- double det = i->fontmatrix.sx/65536.0 * i->fontmatrix.sy/65536.0 -
- i->fontmatrix.r0/65536.0 * i->fontmatrix.r1/65536.0;
-
- if(fabs(det) < 0.0005) {
- /* x direction equals y direction- the text is invisible */
- return 1;
- }
- det = 20 * GLYPH_SCALE / det;
-
- SPOINT p;
- p.x = (SCOORD)(( x * i->fontmatrix.sy/65536.0 - y * i->fontmatrix.r1/65536.0)*det);
- p.y = (SCOORD)((- x * i->fontmatrix.r0/65536.0 + y * i->fontmatrix.sx/65536.0)*det);
-
- RGBA rgba = *(RGBA*)col;
- putcharacter(dev, swffont->id, charid,p.x,p.y,i->current_font_size, rgba);
- swf_FontUseGlyph(swffont, charid);
- return 1;
-}
-
static void endtext(gfxdevice_t*dev)
{
swfoutput_internal*i = (swfoutput_internal*)dev->internal;
}
/* set's 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)
+static void setfontscale(gfxdevice_t*dev,double m11,double m12, double m21,double m22,double x, double y, char force)
{
m11 *= 1024;
m12 *= 1024;
if(i->lastfontm11 == m11 &&
i->lastfontm12 == m12 &&
i->lastfontm21 == m21 &&
- i->lastfontm22 == m22)
+ i->lastfontm22 == m22 && !force)
return;
if(i->textid>=0)
endtext(dev);
MATRIX m;
m.sx = (U32)((m11*ifs)*65536); m.r1 = (U32)((m21*ifs)*65536);
m.r0 = (U32)((m12*ifs)*65536); m.sy = (U32)((m22*ifs)*65536);
- m.tx = 0;
- m.ty = 0;
+ /* 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;
}
if(!i->pagefinished)
endpage(dev);
- if(i->config_insertstoptag) {
+ if( (i->swf->fileVersion <= 8) && (i->config_insertstoptag) ) {
ActionTAG*atag=0;
atag = action_Stop(atag);
atag = action_End(atag);
swfoutput_internal*i = (swfoutput_internal*)dev->internal;
i->dev = dev;
- SRECT r;
RGBA rgb;
msg("<verbose> initializing swf output\n", i->max_x,i->max_y);
}
}
-
void swfoutput_finalize(gfxdevice_t*dev)
{
swfoutput_internal*i = (swfoutput_internal*)dev->internal;
}
endpage(dev);
- fontlist_t *tmp,*iterator = i->fontlist;
+ fontlist_t *iterator = i->fontlist;
while(iterator) {
TAG*mtag = i->swf->firstTag;
if(iterator->swffont) {
swf_FontReduce(iterator->swffont);
}
int used = iterator->swffont->use && iterator->swffont->use->used_glyphs;
- if(i->config_storeallcharacters || used) {
+ if(used) {
mtag = swf_InsertTag(mtag, ST_DEFINEFONT2);
swf_FontSetDefine2(mtag, iterator->swffont);
}
i->swf->compressed = 1;
}
+ /* Initialize AVM2 if it is a Flash9 file */
+ if(i->config_flashversion>=9 && i->config_insertstoptag) {
+ AVM2_InsertStops(i->swf);
+ }
// if(i->config_reordertags)
// swf_Optimize(i->swf);
}
return -1;
}
- if(swf->compressed) {
- if FAILED(swf_WriteSWC(fi,swf))
- msg("<error> WriteSWC() failed.\n");
- } else {
- if FAILED(swf_WriteSWF(fi,swf))
- msg("<error> WriteSWF() failed.\n");
- }
+ if FAILED(swf_WriteSWF(fi,swf))
+ msg("<error> WriteSWF() failed.\n");
if(filename)
close(fi);
SRECT r;
int lsid=0;
int fsid;
- plotxy_t p1,p2,p3,p4;
int myshapeid;
int myshapeid2;
double posx = 0;
double posy = 0;
- int t;
int buttonid = getNewID(dev);
gfxbbox_t bbox = gfxline_getbbox(points);
if(i->config_protect && i->tag) {
i->tag = swf_InsertTag(i->tag, ST_PROTECT);
}
- } else if(!strcmp(name, "faketags")) {
- i->config_generate_fake_tags = atoi(value);
} else if(!strcmp(name, "flashversion")) {
i->config_flashversion = atoi(value);
if(i->swf) {
i->config_linkcolor.b,
i->config_linkcolor.a);
+ } else if(!strcmp(name, "help")) {
+ printf("\nSWF layer options:\n");
+ printf("jpegdpi=<dpi> resolution adjustment for jpeg images\n");
+ printf("jpegsubpixels=<pixels> resolution adjustment for jpeg images (same as jpegdpi, but in pixels)\n");
+ printf("ppmdpi=<dpi> resolution adjustment for lossless images\n");
+ printf("ppmsubpixels=<pixels resolution adjustment for lossless images (same as ppmdpi, but in pixels)\n");
+ printf("subpixels=<pixels> shortcut for setting both jpegsubpixels and ppmsubpixels\n");
+ printf("drawonlyshapes convert everything to shapes (currently broken)\n");
+ printf("ignoredraworder allow to perform a few optimizations for creating smaller SWFs\n");
+ printf("linksopennewwindow make links open a new browser window\n");
+ printf("linktarget target window name of new links\n");
+ printf("linkcolor=<color) color of links (format: RRGGBBAA)\n");
+ printf("storeallcharacters don't reduce the fonts to used characters in the output file\n");
+ printf("enablezlib switch on zlib compression (also done if flashversion>=7)\n");
+ printf("bboxvars store the bounding box of the SWF file in actionscript variables\n");
+ printf("reordertags=0/1 (default: 1) perform some tag optimizations\n");
+ printf("internallinkfunction=<name> when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called\n");
+ printf("externallinkfunction=<name> when the user clicks an external link (e.g. http://www.foo.bar/) on the converted file, this actionscript function is called\n");
+ printf("disable_polygon_conversion never convert strokes to polygons (will remove capstyles and joint styles)\n");
+ printf("caplinewidth=<width> the minimum thichness a line needs to have so that capstyles become visible (and are converted)\n");
+ printf("insertstop put an ActionScript \"STOP\" tag in every frame\n");
+ printf("protect add a \"protect\" tag to the file, to prevent loading in the Flash editor\n");
+ printf("flashversion=<version> the SWF fileversion (6)\n");
+ printf("minlinewidth=<width> convert horizontal/vertical boxes smaller than this width to lines (0.05) \n");
+ printf("animate insert a showframe tag after each placeobject (animate draw order of PDF files)\n");
+ printf("jpegquality=<quality> set compression quality of jpeg images\n");
} else {
return 0;
}
double fy = (double)img->height / (double)newheight;
MATRIX m;
- float m00,m10,tx;
- float m01,m11,ty;
m.sx = (int)(65536*20*matrix->m00*fx); m.r1 = (int)(65536*20*matrix->m10*fy);
m.r0 = (int)(65536*20*matrix->m01*fx); m.sy = (int)(65536*20*matrix->m11*fy);
m.tx = (int)(matrix->tx*20);
advance = xmax;
}
- if(advance<32768) {
- swffont->glyph[t].advance = advance;
+ if(advance<32768/20) {
+ swffont->glyph[t].advance = advance*20;
} else {
swffont->glyph[t].advance = 32767;
}
swffont->layout->descent = (bounds.ymax - bounds.ymin)/2;
swffont->layout->leading = bounds.ymax - bounds.ymin;
}
+ swffont->layout->descent= (bounds.ymax - bounds.ymin);
+ swffont->layout->ascent = 0;
+ swffont->layout->leading = bounds.ymax - bounds.ymin;
return swffont;
}
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;
- if(!font)
+ if(!font) {
+ msg("<error> swf_drawchar called (glyph %d) without font", glyph);
return;
-
+ }
if(!i->swffont || !i->swffont->name || strcmp((char*)i->swffont->name,font->id)) // not equal to current font
{
/* TODO: remove the need for this (enhance getcharacterbbox so that it can cope
with multiple fonts */
endtext(dev);
-
swf_switchfont(dev, font->id); // set the current font
}
- setfontscale(dev, matrix->m00, matrix->m01, matrix->m10, matrix->m11);
+ if(!i->swffont) {
+ msg("<warning> Font is NULL");
+ return;
+ }
+ if(glyph<0 || glyph>=i->swffont->numchars) {
+ msg("<warning> No character %d in font %s (%d chars)", glyph, FIXNULL((char*)i->swffont->name), i->swffont->numchars);
+ return;
+ }
+
+ setfontscale(dev, matrix->m00, matrix->m01, matrix->m10, matrix->m11, matrix->tx, matrix->ty, 0);
+
+ double det = i->fontmatrix.sx/65536.0 * i->fontmatrix.sy/65536.0 -
+ i->fontmatrix.r0/65536.0 * i->fontmatrix.r1/65536.0;
+ if(fabs(det) < 0.0005) {
+ /* x direction equals y direction- the text is invisible */
+ msg("<verbose> Not drawing invisible character character %d (det=%f, m=[%f %f;%f %f]\n", glyph,
+ i->fontmatrix.sx/65536.0, i->fontmatrix.r1/65536.0,
+ i->fontmatrix.r0/65536.0, i->fontmatrix.sy/65536.0);
+ return;
+ }
-/* printf("%f %f\n", m.m31, m.m32);
- {
- static int xpos = 40;
- static int ypos = 200;
- m.m31 = xpos;
- m.m32 = ypos;
- xpos += 10;
+ /*if(i->swffont->glyph[glyph].shape->bitlen <= 16) {
+ msg("<warning> Glyph %d in current charset (%s, %d characters) is empty",
+ glyph, FIXNULL((char*)i->swffont->name), i->swffont->numchars);
+ return 1;
}*/
+ /* calculate character position with respect to the current font matrix */
+ double s = 20 * GLYPH_SCALE / det;
+ double px = matrix->tx - i->fontmatrix.tx/20.0;
+ double py = matrix->ty - i->fontmatrix.ty/20.0;
+ int x = (SCOORD)(( px * i->fontmatrix.sy/65536.0 - py * i->fontmatrix.r1/65536.0)*s);
+ int y = (SCOORD)((- px * i->fontmatrix.r0/65536.0 + py * i->fontmatrix.sx/65536.0)*s);
+ if(x>32767 || x<-32768 || y>32767 || y<-32768) {
+ msg("<verbose> Moving character origin to %f %f\n", matrix->tx, matrix->ty);
+ endtext(dev);
+ setfontscale(dev, matrix->m00, matrix->m01, matrix->m10, matrix->m11, matrix->tx, matrix->ty, 1);
+ }
+
+ if(i->shapeid>=0)
+ endshape(dev);
+ if(i->textid<0)
+ starttext(dev);
+
+ msg("<trace> Drawing char %d in font %d at %d,%d in color %02x%02x%02x%02x",
+ glyph, i->swffont->id, x, y, color->r, color->g, color->b, color->a);
- drawchar(dev, i->swffont, glyph, matrix->tx, matrix->ty, color);
+ putcharacter(dev, i->swffont->id, glyph, x, y, i->current_font_size, *(RGBA*)color);
+ swf_FontUseGlyph(i->swffont, glyph);
+ return;
}