int flashversion=5;
int splinemaxerror=1;
int fontsplinemaxerror=1;
+int filloverlap=0;
+float minlinewidth=0.05;
static char storefont = 0;
static int flag_protected = 0;
static void startshape(struct swfoutput* obj);
static void starttext(struct swfoutput* obj);
-static void endshape(int clip);
+static void endshape(struct swfoutput* obj,int clip);
static void endtext(struct swfoutput* obj);
// matrix multiplication. changes p0
}
return 0;
}
-
+static int moveto(TAG*tag, float x, float y)
+{
+ plotxy p;
+ p.x = x;
+ p.y = y;
+ return moveto(tag, p);
+}
static void addPointToBBox(int px, int py)
{
SPOINT p;
swflastx+=rx;
swflasty+=ry;
}
+static void lineto(TAG*tag, double x, double y)
+{
+ plotxy p;
+ p.x = x;
+ p.y = y;
+ lineto(tag, p);
+}
+
// write a spline-to command into the swf
static void splineto(TAG*tag, plotxy control,plotxy end)
y += (outline->dest.y/(float)0xffff);
if(outline->type == SWF_PATHTYPE_MOVE)
{
- if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
+ //if(!init && fill && output->drawmode != DRAWMODE_EOFILL && !ignoredraworder) {
+ if(filloverlap && !init && fill && output->drawmode != DRAWMODE_EOFILL) {
/* drawmode=FILL (not EOFILL) means that
seperate shapes do not cancel each other out.
On SWF side, we need to start a new shape for each
closed polygon, because SWF only knows EOFILL.
*/
- endshape(0);
+ endshape(output,0);
startshape(output);
startFill();
}
int back = 0;
if(line_cap == LINE_CAP_BUTT || line_cap == LINE_CAP_SQUARE) {
- endshape(0);
+ endshape(output,0);
startshape(output);
SWF_OUTLINE *last, *tmp=outline;
plotxy s,e,p0,p1,p2,p3,m0,m1,m2,m3;
if(line_cap == LINE_CAP_BUTT) {
lineto(tag, q0);
- endshape(depth+2-nr);
+ endshape(output, depth+2-nr);
startshape(output);
}
p0 = m0;
drawShortPath(output,x,y,m,outline);
if(line_cap == LINE_CAP_BUTT) {
- endshape(0);
+ endshape(output,0);
startshape(output);
}
}
need to draw) are very likely to overlap. To avoid that
they cancel each other out at the end points, start a new
shape for the second one */
- endshape(0);startshape(output);
+ endshape(output,0);startshape(output);
startFill();
}
static const int CHARDATAMAX = 8192;
struct chardata {
int charid;
- int fontid;
+ int fontid; /* TODO: use a SWFFONT instead */
int x;
int y;
int size;
fontlist_t*next;
} *fontlist = 0;
-/* todo: why don't higher values (64, 1024) work here? */
-#define FONT_INTERNAL_SIZE 1
+/* Notice: we can only put chars in the range -1639,1638 (-32768/20,32768/20).
+ So if we set this value to high, the char coordinates will overflow.
+ If we set it to low, however, the char positions will be inaccurate */
+#define FONT_INTERNAL_SIZE 4
/* process a character. */
static int drawchar(struct swfoutput*obj, SWFFONT *swffont, char*character, int charnr, int u, swfmatrix*m)
}
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid<0)
starttext(obj);
so we better start a new shape here if the polygon is filled
*/
if(shapeid>=0 && fill && !ignoredraworder) {
- endshape(0);
+ endshape(output,0);
}
if(shapeid<0)
if(textid>=0)
endtext(output);
if(shapeid>=0)
- endshape(0);
+ endshape(output,0);
assert(shapeid<0);
startshape(output);
stopFill();
return charnr;
}
- /* the following is technically wrong, and only works if the font encoding
- is US-ASCII based. It's needed for fonts which return broken unicode
- indices */
-/* if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
- return font->ascii2glyph[charnr];
- }*/
+ if(font->encoding != FONT_ENCODING_UNICODE) {
+ /* the following only works if the font encoding
+ is US-ASCII based. It's needed for fonts which return broken unicode
+ indices */
+ if(charnr>=0 && charnr<font->maxascii && font->ascii2glyph[charnr]>=0) {
+ return font->ascii2glyph[charnr];
+ }
+ }
return -1;
}
swffont->layout->bounds[iii].xmax/20.0,
swffont->layout->bounds[iii].ymax/20.0
);
+ int t;
+ for(t=0;t<swffont->maxascii;t++) {
+ if(swffont->ascii2glyph[t] == iii)
+ msg("<debug> | - maps to %d",t);
+ }
}
}
shapeid = ++currentswfid;
swf_SetU16(tag,shapeid); // ID
- /* TODO: patch back */
bboxrectpos = tag->len;
r.xmin = 0;
r.ymin = 0;
static void starttext(struct swfoutput*obj)
{
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
textid = ++currentswfid;
tag->pos = tag->readBit = 0;
}
-static void endshape(int clipdepth)
+void cancelshape(swfoutput*obj)
+{
+ /* delete old shape tag */
+ TAG*todel = tag;
+ tag = tag->prev;
+ swf_DeleteTag(todel);
+ shapeid = -1;
+ bboxrectpos = -1;
+}
+
+void fixAreas(swfoutput*obj)
+{
+ if(!shapeisempty && fill &&
+ (bboxrect.xmin == bboxrect.xmax ||
+ bboxrect.ymin == bboxrect.ymax) &&
+ minlinewidth >= 0.001
+ ) {
+ msg("<debug> Shape has size 0: width=%.2f height=%.2f",
+ (bboxrect.xmax-bboxrect.xmin)/20.0,
+ (bboxrect.ymax-bboxrect.ymin)/20.0
+ );
+
+ SRECT r = bboxrect;
+
+ if(r.xmin == r.xmax && r.ymin == r.ymax) {
+ /* this thing comes down to a single dot- nothing to fix here */
+ return;
+ }
+
+ cancelshape(obj);
+
+ RGBA save_col = obj->strokergb;
+ int save_width = linewidth;
+
+ obj->strokergb = obj->fillrgb;
+ linewidth = (int)(minlinewidth*20);
+ if(linewidth==0) linewidth = 1;
+
+ startshape(obj);
+
+ moveto(tag, r.xmin/20.0,r.ymin/20.0);
+ lineto(tag, r.xmax/20.0,r.ymax/20.0);
+
+ obj->strokergb = save_col;
+ linewidth = save_width;
+ }
+
+}
+
+static void endshape(swfoutput*obj, int clipdepth)
{
if(shapeid<0)
return;
- swf_ShapeSetEnd(tag);
- if(shapeisempty) {
- // delete the tag again, we didn't do anything
- TAG*todel = tag;
- tag = tag->prev;
- swf_DeleteTag(todel);
- shapeid = -1;
- bboxrectpos = -1;
+ if(!clipdepth)
+ fixAreas(obj);
+
+ if(shapeisempty ||
+ (bboxrect.xmin == bboxrect.xmax && bboxrect.ymin == bboxrect.ymax))
+ {
+ // delete the shape again, we didn't do anything
+ cancelshape(obj);
return;
}
+
+ swf_ShapeSetEnd(tag);
changeRect(tag, bboxrectpos, &bboxrect);
static void endpage(struct swfoutput*obj)
{
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
while(clippos)
obj->fillrgb.b == b &&
obj->fillrgb.a == a) return;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
obj->fillrgb.r = r;
obj->fillrgb.g = g;
obj->strokergb.a == a) return;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
obj->strokergb.r = r;
obj->strokergb.g = g;
obj->strokergb.b = b;
obj->strokergb.a = a;
}
-void swfoutput_setlinewidth(struct swfoutput*obj, double linewidth)
+void swfoutput_setlinewidth(struct swfoutput*obj, double _linewidth)
{
- if(linewidth == (u16)(linewidth*20))
+ if(linewidth == (u16)(_linewidth*20))
return;
if(shapeid>=0)
- endshape(0);
- linewidth = (u16)(linewidth*20);
+ endshape(obj,0);
+ linewidth = (u16)(_linewidth*20);
}
if(textid>=0)
endtext(obj);
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(clippos >= 127)
{
if(textid>=0)
endtext(obj);
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(!clippos) {
msg("<error> Invalid end of clipping region");
}
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
ActionTAG* actions;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
char mouseover = 1;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
{
TAG*oldtag;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
JPEGBITS*jpeg;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
{
TAG*oldtag;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
TAG*oldtag;
U8*mem2 = 0;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
{
if(id<0) return;
if(shapeid>=0)
- endshape(0);
+ endshape(obj,0);
if(textid>=0)
endtext(obj);
drawimage(obj, id, sizex, sizey, x1,y1,x2,y2,x3,y3,x4,y4);
}
+void swfoutput_setparameter(char*name, char*value)
+{
+ if(!strcmp(name, "drawonlyshapes")) {
+ drawonlyshapes = atoi(value);
+ } else if(!strcmp(name, "ignoredraworder")) {
+ ignoredraworder = atoi(value);
+ } else if(!strcmp(name, "filloverlap")) {
+ filloverlap = atoi(value);
+ } else if(!strcmp(name, "linksopennewwindow")) {
+ opennewwindow = atoi(value);
+ } else if(!strcmp(name, "opennewwindow")) {
+ opennewwindow = atoi(value);
+ } else if(!strcmp(name, "storeallcharacters")) {
+ storeallcharacters = atoi(value);
+ } else if(!strcmp(name, "enablezlib")) {
+ enablezlib = atoi(value);
+ } else if(!strcmp(name, "insertstop")) {
+ insertstoptag = atoi(value);
+ } else if(!strcmp(name, "flashversion")) {
+ flashversion = atoi(value);
+ } else if(!strcmp(name, "minlinewidth")) {
+ minlinewidth = atof(value);
+ } else if(!strcmp(name, "jpegquality")) {
+ int val = atoi(value);
+ if(val<0) val=0;
+ if(val>100) val=100;
+ jpegquality = val;
+ } else if(!strcmp(name, "splinequality")) {
+ int v = atoi(value);
+ v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
+ if(v<1) v = 1;
+ splinemaxerror = v;
+ } else if(!strcmp(name, "fontquality")) {
+ int v = atoi(value);
+ v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
+ if(v<1) v = 1;
+ fontsplinemaxerror = v;
+ } else {
+ fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);
+ }
+}
+