SHAPE* swf_ShapeDrawerToShape(drawer_t*draw) { SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal; SHAPE* shape = (SHAPE*)rfx_alloc(sizeof(SHAPE)); if(!sdraw->isfinished) { fprintf(stderr, "Warning: you should Finish() your drawer before calling DrawerToShape"); swf_ShapeDrawerFinish(draw); } memcpy(shape, sdraw->shape, sizeof(SHAPE)); shape->bitlen = (sdraw->tag->len-1)*8; shape->data = (U8*)rfx_alloc(sdraw->tag->len-1); memcpy(shape->data, &sdraw->tag->data[1], sdraw->tag->len-1); return shape; }
void swf_Render_Init(RENDERBUF*buf, int posx, int posy, int width, int height, int antialize, int multiply) { renderbuf_internal*i; int y; memset(buf, 0, sizeof(RENDERBUF)); buf->width = width*multiply; buf->height = height*multiply; buf->posx = posx; buf->posy = posy; buf->internal = (renderbuf_internal*)rfx_calloc(sizeof(renderbuf_internal)); i = (renderbuf_internal*)buf->internal; if(antialize < 1) antialize = 1; i->antialize = antialize; i->multiply = multiply*antialize; i->height2 = antialize*buf->height; i->width2 = antialize*buf->width; i->lines = (renderline_t*)rfx_alloc(i->height2*sizeof(renderline_t)); for(y=0;y<i->height2;y++) { memset(&i->lines[y], 0, sizeof(renderline_t)); i->lines[y].points = swf_InsertTag(0, 0); i->lines[y].num = 0; } i->zbuf = (int*)rfx_calloc(sizeof(int)*i->width2*i->height2); i->img = (RGBA*)rfx_calloc(sizeof(RGBA)*i->width2*i->height2); i->shapes = 0; i->ymin = 0x7fffffff; i->ymax = -0x80000000; }
gfxline_t* gfxline_from_gfxpoly(gfxpoly_t*poly) { ArtSVP*svp = (ArtSVP*)poly; int size = 0; int t; int pos = 0; msg("<verbose> Casting polygon of %d segments back to gfxline", svp->n_segs); for(t=0;t<svp->n_segs;t++) { size += svp->segs[t].n_points; } size = size + 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; } }
gfxdevice_t*gfxfilter_apply(gfxfilter_t*_filter, gfxdevice_t*out) { internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t)); gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t)); gfxfilter_t*filter = (gfxfilter_t*)rfx_alloc(sizeof(gfxfilter_t)); memcpy(filter, _filter, sizeof(gfxfilter_t)); i->out = out; i->filter = filter; i->pass = 1; dev->internal = i; dev->name = filter->name?filter->name:"filter"; dev->setparameter = filter->setparameter?filter_setparameter:passthrough_setparameter; dev->startpage = filter->startpage?filter_startpage:passthrough_startpage; dev->startclip = filter->startclip?filter_startclip:passthrough_startclip; dev->endclip = filter->endclip?filter_endclip:passthrough_endclip; dev->stroke = filter->stroke?filter_stroke:passthrough_stroke; dev->fill = filter->fill?filter_fill:passthrough_fill; dev->fillbitmap = filter->fillbitmap?filter_fillbitmap:passthrough_fillbitmap; dev->fillgradient = filter->fillgradient?filter_fillgradient:passthrough_fillgradient; dev->addfont = filter->addfont?filter_addfont:passthrough_addfont; dev->drawchar = filter->drawchar?filter_drawchar:passthrough_drawchar; dev->drawlink = filter->drawlink?filter_drawlink:passthrough_drawlink; dev->endpage = filter->endpage?filter_endpage:passthrough_endpage; dev->finish = filter_finish; return dev; }
ActionTAG* swf_ActionGet(TAG*tag) { U8 op = 1; int length; ActionTAG tmp; ActionTAG*action = &tmp; U8*data; while(op) { action->next = (ActionTAG*)rfx_calloc(sizeof(ActionTAG)); action->next->prev = action; action->next->next = 0; action->next->parent = tmp.next; action = action->next; op = swf_GetU8(tag); if(op<0x80) length = 0; else length = swf_GetU16(tag); if(length) { data = (U8*)rfx_alloc(length); swf_GetBlock(tag, data, length); } else { data = 0; } action->op = op; action->len = length; action->data = data; } return tmp.next; }
ActionTAG* action_PushString(ActionTAG*atag, const char*str) { int l = strlen(str); char*ptr = (char*)rfx_alloc(l+2); ptr[0] = 0; // string strcpy(&ptr[1], str); return swf_AddActionTAG(atag, ACTION_PUSH, (U8*)ptr, l+2); }
ActionTAG* action_GetUrl(ActionTAG*atag, const char* url, char* label) { int l1= strlen(url); int l2= strlen(label); char*ptr = (char*)rfx_alloc(l1+l2+2); strcpy(ptr, url); strcpy(&ptr[l1+1], label); return swf_AddActionTAG(atag, ACTION_GETURL, (U8*)ptr, l1+l2+2); }
ActionTAG* action_PushFloat(ActionTAG*atag, float f) { char*ptr = (char*)rfx_alloc(5); U32 fd = *(U32*)&f; ptr[0] = 1; //float ptr[1] = fd; ptr[2] = fd>>8; ptr[3] = fd>>16; ptr[4] = fd>>24; return swf_AddActionTAG(atag, ACTION_PUSH, (U8*)ptr, 5); }
void swf_Render_AddImage(RENDERBUF*buf, U16 id, RGBA*img, int width, int height) { renderbuf_internal*i = (renderbuf_internal*)buf->internal; bitmap_t*bm = (bitmap_t*)rfx_calloc(sizeof(bitmap_t)); bm->id = id; bm->width = width; bm->height = height; bm->data = (RGBA*)rfx_alloc(width*height*4); memcpy(bm->data, img, width*height*4); bm->next = i->bitmaps; i->bitmaps = bm; }
static void linedraw_moveTo(gfxdrawer_t*d, gfxcoord_t x, gfxcoord_t y) { linedraw_internal_t*i = (linedraw_internal_t*)d->internal; gfxline_t*l = (gfxline_t*)rfx_alloc(sizeof(gfxline_t)); l->type = gfx_moveTo; i->has_moveto = 1; i->x0 = x; i->y0 = y; l->sx = l->sy = 0; d->x = l->x = x; d->y = l->y = y; l->next = 0; if(i->next) i->next->next = l; i->next = l; if(!i->start) i->start = l; }
ActionTAG* action_PushDouble(ActionTAG*atag, double d) { char*ptr = (char*)rfx_alloc(9); U8*dd = (U8*)&d; ptr[0] = 6; //double #ifdef WORDS_BIGENDIAN ptr[1] = dd[7];ptr[2] = dd[6]; ptr[3] = dd[5];ptr[4] = dd[4]; ptr[5] = dd[3];ptr[6] = dd[2]; ptr[7] = dd[1];ptr[8] = dd[0]; #else ptr[1] = dd[0];ptr[2] = dd[1]; ptr[3] = dd[2];ptr[4] = dd[3]; ptr[5] = dd[4];ptr[6] = dd[5]; ptr[7] = dd[6];ptr[8] = dd[7]; #endif return swf_AddActionTAG(atag, ACTION_PUSH, (U8*)ptr, 9); }
static void maketransparent_fillbitmap(gfxfilter_t*f, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform, gfxdevice_t*out) { internal_t*i = (internal_t*)f->internal; gfximage_t img2; img2.width = img->width; img2.height = img->height; img2.data = (gfxcolor_t*)rfx_alloc(img->width*img->height*4); int x,y; for(y=0;y<img->height;y++) { gfxcolor_t*in = &img->data[y*img->width]; gfxcolor_t*out = &img2.data[y*img->width]; for(x=0;x<img->width;x++) { out[x] = transform_color(i, &in[x]); } } out->fillbitmap(out, line, &img2, matrix, cxform); rfx_free(img2.data); }
static void linedraw_splineTo(gfxdrawer_t*d, gfxcoord_t sx, gfxcoord_t sy, gfxcoord_t x, gfxcoord_t y) { linedraw_internal_t*i = (linedraw_internal_t*)d->internal; if(!i->has_moveto) { linedraw_moveTo(d, x, y); return; } gfxline_t*l = (gfxline_t*)rfx_alloc(sizeof(gfxline_t)); l->type = gfx_splineTo; d->x = l->x = x; d->y = l->y = y; l->sx = sx; l->sy = sy; l->next = 0; if(i->next) i->next->next = l; i->next = l; if(!i->start) i->start = l; }
static void linedraw_lineTo(gfxdrawer_t*d, gfxcoord_t x, gfxcoord_t y) { linedraw_internal_t*i = (linedraw_internal_t*)d->internal; if(!i->has_moveto) { /* starts with a line, not with a moveto. As this is the first entry in the list, this is probably *meant* to be a moveto */ linedraw_moveTo(d, x, y); return; } gfxline_t*l = (gfxline_t*)rfx_alloc(sizeof(gfxline_t)); l->type = gfx_lineTo; d->x = l->x = x; d->y = l->y = y; l->next = 0; if(i->next) i->next->next = l; i->next = l; if(!i->start) i->start = l; }
ActionTAG* swf_AddActionTAG(ActionTAG*atag, U8 op, U8*data, U16 len) { ActionTAG*tmp; tmp = (ActionTAG*)rfx_alloc(sizeof(ActionTAG)); tmp->next = 0; if(atag) { tmp->prev = atag; atag->next = tmp; tmp->parent = atag->parent; } else { tmp->prev = 0; tmp->parent = tmp; } if(data || !len) { tmp->data = data; } else { tmp->data = tmp->tmp; } tmp->len = len; tmp->op = op; return tmp; }
static void maketransparent_fillgradient(gfxfilter_t*f, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix, gfxdevice_t*out) { internal_t*i = (internal_t*)f->internal; gfxgradient_t*g = 0, *prev = 0; while(gradient) { gfxgradient_t*n = rfx_alloc(sizeof(gfxgradient_t)); n->pos = gradient->pos; n->color = transform_color(i, &gradient->color); n->next = 0; if(prev) { prev->next = n; prev = n; } else { g = prev = n; } gradient = gradient->next; } out->fillgradient(out, line, g, type, matrix); gfxgradient_destroy(g); }
gfxdevice_t*gfxtwopassfilter_apply(gfxtwopassfilter_t*_twopass, gfxdevice_t*out) { internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t)); gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t)); gfxtwopassfilter_t*twopass = (gfxtwopassfilter_t*)rfx_alloc(sizeof(gfxtwopassfilter_t)); memcpy(twopass, _twopass, sizeof(gfxtwopassfilter_t)); gfxdevice_record_init(&i->record, /*use tempfile*/1); i->out = &i->record; i->final_out = out; i->twopass = twopass; i->pass = 1; i->num_passes = 2; dev->internal = i; i->filter = &twopass->pass1; setup_twopass(dev, i->filter); dev->finish = twopass_finish; return dev; }
unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, windrule_t*rule, windcontext_t*context) { renderbuf_t _buf, *buf=&_buf; buf->width = (bbox->xmax - bbox->xmin); buf->height = (bbox->ymax - bbox->ymin); buf->bbox = *bbox; buf->zoom = zoom * polygon->gridsize; int width8 = (buf->width+7) >> 3; char bleeding = 0; unsigned char* image = (unsigned char*)malloc_safe(width8*buf->height); memset(image, 0, width8*buf->height); buf->lines = (renderline_t*)rfx_alloc(buf->height*sizeof(renderline_t)); int y; for(y=0;y<buf->height;y++) { memset(&buf->lines[y], 0, sizeof(renderline_t)); buf->lines[y].points = 0; buf->lines[y].num = 0; } int polygon_nr = 0; int s,t; gfxpolystroke_t*stroke = polygon->strokes; for(;stroke;stroke=stroke->next) { for(t=0;t<stroke->num_points-1;t++) { point_t a = stroke->points[t]; point_t b = stroke->points[t+1]; add_line(buf, a.x, a.y, b.x, b.y, stroke->fs, stroke->dir, polygon_nr); } } for(y=0;y<buf->height;y++) { renderpoint_t*points = buf->lines[y].points; unsigned char*line = &image[width8*y]; int n; int num = buf->lines[y].num; qsort(points, num, sizeof(renderpoint_t), compare_renderpoints); int lastx = 0; windstate_t fill = rule->start(context); for(n=0;n<num;n++) { renderpoint_t*p = &points[n]; int x = (int)(p->x - bbox->xmin); if(x < lastx) x = lastx; if(x > buf->width) x = buf->width; if(fill.is_filled && lastx<x) { fill_bitwise(line, lastx, x); } fill = rule->add(context, fill, p->fs, p->dir, p->polygon_nr); lastx = x; } if(fill.is_filled && lastx!=buf->width) { /* we're bleeding, fill over padding, too. */ fprintf(stderr, "Polygon %p is bleeding in line %d\n", polygon, y); fill_bitwise(line, lastx, width8*8); assert(line[width8-1]&0x01); bleeding = 1; exit(1); } } for(y=0;y<buf->height;y++) { if(buf->lines[y].points) { free(buf->lines[y].points); } memset(&buf->lines[y], 0, sizeof(renderline_t)); } if(bleeding) { assert(!bitmap_ok(bbox, image)); } free(buf->lines);buf->lines=0; return image; }
int swf_ActionEnumerate(ActionTAG*atag, char*(*callback)(char*), int type) { int t; U8*data; char* cp; int count = 0; while(atag) { U16 poollen = 0; for(t=0;t<definedactions;t++) if(actions[t].op == atag->op) break; if(t==definedactions) { // unknown actiontag atag = atag->next; count++; continue; } cp = actions[t].flags; data = atag->data; if(atag->len) { while(*cp) { U8 * replacepos = 0; int replacelen = 0; U8 * replacement = 0; switch(*cp) { case 'u': { if(type&TYPE_URL) { replacelen = strlen((const char*)data); replacepos = data; replacement = (U8*)callback((char*)data); // may be null } } break; case 't': { if(type&TYPE_TARGET) { replacelen = strlen((const char*)data); replacepos = data; replacement = (U8*)callback((char*)data); // may be null } } break; case 'c': { if(type&TYPE_STRING) { replacelen = strlen((const char*)data); replacepos = data; replacement = (U8*)callback((char*)data); // may be null } } break; case 'C': { poollen = (data[0]+256*data[1]); } break; case 'o': { } break; case 'p': { U8 datatype = *data; char*value = (char*)&data[1]; if(datatype == 0) { //string if(type&TYPE_STRING) { replacelen = strlen(value); replacepos = (U8*)value; replacement = (U8*)callback(value); // may be null } } else if (datatype == 8) { //lookup } } break; } data += OpAdvance(*cp, data); if(*cp!='c' || !poollen) cp++; if(poollen) poollen--; if(replacement) { int newlen = strlen((const char *)replacement); char * newdata = (char*)rfx_alloc(atag->len - replacelen + newlen); int rpos = replacepos - atag->data; memcpy(newdata, atag->data, rpos); memcpy(&newdata[rpos], replacement, newlen); memcpy(&newdata[rpos+newlen], &replacepos[replacelen], &data[atag->len] - &replacepos[replacelen]); rfx_free(atag->data); atag->data = (U8*)newdata; data = &atag->data[rpos+newlen+1]; } } } atag = atag->next; count ++; } return count; }
unsigned char* render_svp(ArtSVP*svp, intbbox_t*bbox, double zoom, ArtWindRule rule) { renderbuf_t _buf, *buf=&_buf; buf->width = (bbox->xmax - bbox->xmin); buf->height = (bbox->ymax - bbox->ymin); buf->bbox = *bbox; buf->zoom = zoom; int width8 = (buf->width+7) >> 3; unsigned char* image = (unsigned char*)malloc(width8*buf->height); memset(image, 0, width8*buf->height); buf->lines = (renderline_t*)rfx_alloc(buf->height*sizeof(renderline_t)); int y; for(y=0;y<buf->height;y++) { memset(&buf->lines[y], 0, sizeof(renderline_t)); buf->lines[y].points = 0; buf->lines[y].num = 0; } int t; for(t=0;t<svp->n_segs;t++) { ArtSVPSeg* seg = &svp->segs[t]; int s; for(s=0;s<seg->n_points-1;s++) { int dir = seg->dir? 1 : -1; add_line(buf, seg->points[s].x, seg->points[s].y, seg->points[s+1].x, seg->points[s+1].y, dir); } } for(y=0;y<buf->height;y++) { renderpoint_t*points = buf->lines[y].points; unsigned char*line = &image[width8*y]; int n; int num = buf->lines[y].num; int wind = 0; qsort(points, num, sizeof(renderpoint_t), compare_renderpoints); int lastx = 0; int fill = 0; for(n=0;n<num;n++) { renderpoint_t*p = &points[n]; int x = (int)(p->x - bbox->xmin); if(x < lastx) x = lastx; if(x > buf->width) { break; } if(fill && x!=lastx) { fill_bitwise(line, lastx, x); } wind += p->direction; if(rule == ART_WIND_RULE_INTERSECT) { fill = wind>=2; } else if (rule == ART_WIND_RULE_NONZERO) { fill = wind!=0; } else if (rule == ART_WIND_RULE_ODDEVEN) { fill = wind&1; } else { // rule == ART_WIND_RULE_POSITIVE fill = wind>=1; } lastx = x; } if(fill && lastx!=buf->width) fill_bitwise(line, lastx, buf->width); } for(y=0;y<buf->height;y++) { if(buf->lines[y].points) { free(buf->lines[y].points); } memset(&buf->lines[y], 0, sizeof(renderline_t)); } free(buf->lines);buf->lines=0; return image; }