+ double l1 = sqrt((x4-x1)*(x4-x1) + (y4-y1)*(y4-y1));
+ double l2 = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+
+ gfxline_t p1,p2,p3,p4,p5;
+ p1.type=gfx_moveTo;p1.x=x1; p1.y=y1;p1.next=&p2;
+ p2.type=gfx_lineTo;p2.x=x2; p2.y=y2;p2.next=&p3;
+ p3.type=gfx_lineTo;p3.x=x3; p3.y=y3;p3.next=&p4;
+ p4.type=gfx_lineTo;p4.x=x4; p4.y=y4;p4.next=&p5;
+ p5.type=gfx_lineTo;p5.x=x1; p5.y=y1;p5.next=0;
+
+ {p1.x = (int)(p1.x*20)/20.0;
+ p1.y = (int)(p1.y*20)/20.0;
+ p2.x = (int)(p2.x*20)/20.0;
+ p2.y = (int)(p2.y*20)/20.0;
+ p3.x = (int)(p3.x*20)/20.0;
+ p3.y = (int)(p3.y*20)/20.0;
+ p4.x = (int)(p4.x*20)/20.0;
+ p4.y = (int)(p4.y*20)/20.0;
+ p5.x = (int)(p5.x*20)/20.0;
+ p5.y = (int)(p5.y*20)/20.0;
+ }
+
+ float m00,m10,tx;
+ float m01,m11,ty;
+
+ gfxmatrix_t m;
+ m.m00 = (p4.x-p1.x)/sizex; m.m10 = (p2.x-p1.x)/sizey;
+ m.m01 = (p4.y-p1.y)/sizex; m.m11 = (p2.y-p1.y)/sizey;
+ m.tx = p1.x - 0.5;
+ m.ty = p1.y - 0.5;
+
+ gfximage_t img;
+ img.data = (gfxcolor_t*)data;
+ img.width = sizex;
+ img.height = sizey;
+
+ if(type == IMAGE_TYPE_JPEG)
+ /* TODO: pass image_dpi to device instead */
+ i->device.setparameter(&i->device, "next_bitmap_is_jpeg", "1");
+
+ i->device.fillbitmap(&i->device, &p1, &img, &m, 0);
+}
+
+void 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)
+{
+ swfoutput_drawimage(obj,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_JPEG);
+}
+
+void 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)
+{
+ swfoutput_drawimage(obj,mem,sizex,sizey,x1,y1,x2,y2,x3,y3,x4,y4, IMAGE_TYPE_LOSSLESS);
+}
+
+void swfoutput_setparameter(char*name, char*value)
+{
+ if(!strcmp(name, "jpegsubpixels")) {
+ config_jpegsubpixels = atof(value);
+ } else if(!strcmp(name, "ppmsubpixels")) {
+ config_ppmsubpixels = atof(value);
+ } else if(!strcmp(name, "drawonlyshapes")) {
+ config_drawonlyshapes = atoi(value);
+ } else if(!strcmp(name, "ignoredraworder")) {
+ config_ignoredraworder = atoi(value);
+ } else if(!strcmp(name, "filloverlap")) {
+ config_filloverlap = atoi(value);
+ } else if(!strcmp(name, "linksopennewwindow")) {
+ config_opennewwindow = atoi(value);
+ } else if(!strcmp(name, "opennewwindow")) {
+ config_opennewwindow = atoi(value);
+ } else if(!strcmp(name, "storeallcharacters")) {
+ config_storeallcharacters = atoi(value);
+ } else if(!strcmp(name, "enablezlib")) {
+ config_enablezlib = atoi(value);
+ } else if(!strcmp(name, "bboxvars")) {
+ config_bboxvars = atoi(value);
+ } else if(!strcmp(name, "insertstop")) {
+ config_insertstoptag = atoi(value);
+ } else if(!strcmp(name, "protected")) {
+ config_protect = atoi(value);
+ } else if(!strcmp(name, "flashversion")) {
+ config_flashversion = atoi(value);
+ } else if(!strcmp(name, "minlinewidth")) {
+ config_minlinewidth = atof(value);
+ } else if(!strcmp(name, "caplinewidth")) {
+ config_caplinewidth = atof(value);
+ } else if(!strcmp(name, "dumpfonts")) {
+ config_dumpfonts = atoi(value);
+ } else if(!strcmp(name, "jpegquality")) {
+ int val = atoi(value);
+ if(val<0) val=0;
+ if(val>100) val=100;
+ config_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;
+ config_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;
+ config_fontsplinemaxerror = v;
+ } else {
+ fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);
+ }
+}
+
+// --------------------------------------------------------------------
+
+static CXFORM gfxcxform_to_cxform(gfxcxform_t* c)
+{
+ CXFORM cx;
+ swf_GetCXForm(0, &cx, 1);
+ if(!c)
+ return cx;
+ if(c->rg!=0 || c->rb!=0 || c->ra!=0 ||
+ c->gr!=0 || c->gb!=0 || c->ga!=0 ||
+ c->br!=0 || c->bg!=0 || c->ba!=0 ||
+ c->ar!=0 || c->ag!=0 || c->ab!=0)
+ msg("<warning> CXForm not SWF-compatible");
+
+ cx.a0 = (S16)(c->aa*256);
+ cx.r0 = (S16)(c->rr*256);
+ cx.g0 = (S16)(c->gg*256);
+ cx.b0 = (S16)(c->bb*256);
+ cx.a1 = c->t.a;
+ cx.r1 = c->t.r;
+ cx.g1 = c->t.g;
+ cx.b1 = c->t.b;
+ return cx;
+}
+
+ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit)
+{
+ ArtVpath *vec = NULL;
+ ArtSVP *svp = NULL;
+ int pos=0,len=0;
+ gfxline_t*l2;
+ double x=0,y=0;
+
+ l2 = line;
+ while(l2) {
+ if(l2->type == gfx_moveTo) {
+ pos ++;
+ } if(l2->type == gfx_lineTo) {
+ pos ++;
+ } if(l2->type == gfx_splineTo) {
+ int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))/3);
+ if(!parts) parts = 1;
+ pos += parts + 1;
+ }
+ x = l2->x;
+ y = l2->y;
+ l2 = l2->next;
+ }
+ pos++;
+ len = pos;
+
+ vec = art_new (ArtVpath, len);
+
+ pos = 0;
+ l2 = line;
+ while(l2) {
+ if(l2->type == gfx_moveTo) {
+ vec[pos].code = ART_MOVETO;
+ vec[pos].x = l2->x;
+ vec[pos].y = l2->y;
+ pos++;
+ assert(pos<=len);
+ } else if(l2->type == gfx_lineTo) {
+ vec[pos].code = ART_LINETO;
+ vec[pos].x = l2->x;
+ vec[pos].y = l2->y;
+ pos++;
+ assert(pos<=len);
+ } else if(l2->type == gfx_splineTo) {
+ int i;
+ int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))/3);
+ if(!parts) parts = 1;
+ for(i=0;i<=parts;i++) {
+ double t = (double)i/(double)parts;
+ vec[pos].code = ART_LINETO;
+ vec[pos].x = l2->x*t*t + 2*l2->sx*t*(1-t) + x*(1-t)*(1-t);
+ vec[pos].y = l2->y*t*t + 2*l2->sy*t*(1-t) + y*(1-t)*(1-t);
+ pos++;
+ assert(pos<=len);
+ }
+ }
+ x = l2->x;
+ y = l2->y;
+ l2 = l2->next;
+ }
+ vec[pos].code = ART_END;
+
+ svp = art_svp_vpath_stroke (vec,
+ (joint_style==gfx_joinMiter)?ART_PATH_STROKE_JOIN_MITER:
+ ((joint_style==gfx_joinRound)?ART_PATH_STROKE_JOIN_ROUND:
+ ((joint_style==gfx_joinBevel)?ART_PATH_STROKE_JOIN_BEVEL:ART_PATH_STROKE_JOIN_BEVEL)),
+ (cap_style==gfx_capButt)?ART_PATH_STROKE_CAP_BUTT:
+ ((cap_style==gfx_capRound)?ART_PATH_STROKE_CAP_ROUND:
+ ((cap_style==gfx_capSquare)?ART_PATH_STROKE_CAP_SQUARE:ART_PATH_STROKE_CAP_SQUARE)),
+ width, //line_width
+ miterLimit, //miter_limit
+ 0.05 //flatness
+ );
+ free(vec);
+ return svp;
+}
+
+gfxline_t* SVPtogfxline(ArtSVP*svp)
+{
+ int size = 0;
+ int t;
+ int pos = 0;
+ for(t=0;t<svp->n_segs;t++) {
+ size += svp->segs[t].n_points + 1;
+ }
+ gfxline_t* lines = (gfxline_t*)rfx_alloc(sizeof(gfxline_t)*size);
+
+ for(t=0;t<svp->n_segs;t++) {
+ ArtSVPSeg* seg = &svp->segs[t];
+ int p;
+ for(p=0;p<seg->n_points;p++) {
+ lines[pos].type = p==0?gfx_moveTo:gfx_lineTo;
+ ArtPoint* point = &seg->points[p];
+ lines[pos].x = point->x;
+ lines[pos].y = point->y;
+ lines[pos].next = &lines[pos+1];
+ pos++;
+ }
+ }
+ if(pos) {
+ lines[pos-1].next = 0;
+ return lines;
+ } else {
+ return 0;
+ }
+}