X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfrender.c;h=f44c79ca1c75b6ca472d2f65eca47a3bf6b4892e;hb=8e8f6b759d5bf5b64793909713d198d673534f1e;hp=ba59776d92e7ad483e12cc165646c131ef746da3;hpb=ea28c68e722e1c3718973213d80146ff64b46c37;p=swftools.git diff --git a/lib/modules/swfrender.c b/lib/modules/swfrender.c index ba59776..f44c79c 100644 --- a/lib/modules/swfrender.c +++ b/lib/modules/swfrender.c @@ -22,18 +22,49 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + +typedef struct _dummyshape +{ + SHAPE2*shape; + //CXFORM //TODO + struct _dummyshape*next; +} dummyshape_t; + typedef struct _renderpoint { enum {clip_type, fill_type} type; - float fx; + float fx; //for sorting int x; U32 depth; U32 clipdepth; - SHAPE2*shape; SHAPELINE*shapeline; - //CXFORM? + + dummyshape_t*s; } renderpoint_t; +/* + enum {clip_type, solidfill_type, texturefill_type, gradientfill_type} type; + float fx; + int x; + U32 depth; + U32 clipdepth; + + // solidfill; + RGBA color; + + // texturefill + bitmap_t* bitmap; + + // gradientfill + gradient_t* gradient; + + // texture- & gradientfill; + U32 x,y; + U32 dx,dy; + +*/ + typedef struct _renderline { TAG*points; //incremented in 128 byte steps @@ -47,12 +78,6 @@ typedef struct _bitmap { struct _bitmap*next; } bitmap_t; -typedef struct _dummyshape -{ - SHAPE2*shape; - struct _dummyshape*next; -} dummyshape_t; - typedef struct _renderbuf_internal { renderline_t*lines; @@ -62,6 +87,8 @@ typedef struct _renderbuf_internal int width2,height2; dummyshape_t*dshapes; dummyshape_t*dshapes_next; + RGBA*background; + int background_width, background_height; } renderbuf_internal; #define DEBUG 0 @@ -79,9 +106,11 @@ static inline void add_pixel(RENDERBUF*dest, float x, int y, renderpoint_t*p) problem appears to often */ #define CUT 0.5 -static void add_line(RENDERBUF*buf, double x1, double y1, double x2, double y2, renderpoint_t*p, char thin) +static void add_line(RENDERBUF*buf, double x1, double y1, double x2, double y2, renderpoint_t*p) { renderbuf_internal*i = (renderbuf_internal*)buf->internal; + double diffx, diffy; + double ny1, ny2, stepx; /* if(DEBUG&4) { int l = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); printf(" l[%d - %.2f/%.2f -> %.2f/%.2f]", l, x1/20.0, y1/20.0, x2/20.0, y2/20.0); @@ -98,15 +127,17 @@ static void add_line(RENDERBUF*buf, double x1, double y1, double x2, double y2, x2 = x2/20.0; if(y2 < y1) { - double x = x1;x1 = x2;x2=x; - double y = y1;y1 = y2;y2=y; + double x; + double y; + x = x1;x1 = x2;x2=x; + y = y1;y1 = y2;y2=y; } - double diffx = x2 - x1; - double diffy = y2 - y1; + diffx = x2 - x1; + diffy = y2 - y1; - double ny1 = (int)(y1)+CUT; - double ny2 = (int)(y2)+CUT; + ny1 = (int)(y1)+CUT; + ny2 = (int)(y2)+CUT; if(ny1 < y1) { ny1 = (int)(y1) + 1.0 + CUT; @@ -118,20 +149,22 @@ static void add_line(RENDERBUF*buf, double x1, double y1, double x2, double y2, if(ny1 > ny2) return; - double stepx = diffx/diffy; + stepx = diffx/diffy; x1 = x1 + (ny1-y1)*stepx; x2 = x2 + (ny2-y2)*stepx; - int posy=(int)ny1; - int endy=(int)ny2; - double posx=0; - double startx = x1; - - while(posy<=endy) { - float xx = (float)(startx + posx); - add_pixel(buf, xx ,posy, p); - posx+=stepx; - posy++; + { + int posy=(int)ny1; + int endy=(int)ny2; + double posx=0; + double startx = x1; + + while(posy<=endy) { + float xx = (float)(startx + posx); + add_pixel(buf, xx ,posy, p); + posx+=stepx; + posy++; + } } } #define PI 3.14159265358979 @@ -176,7 +209,7 @@ static void add_solidline(RENDERBUF*buf, double x1, double y1, double x2, double xx = x2+vx; yy = y2+vy; - add_line(buf, x1+vx, y1+vy, xx, yy, p, 0); + add_line(buf, x1+vx, y1+vy, xx, yy, p); lastx = xx; lasty = yy; for(t=1;tposy = posy; buf->internal = (renderbuf_internal*)rfx_calloc(sizeof(renderbuf_internal)); i = (renderbuf_internal*)buf->internal; - i->antialize = antialize; + i->antialize = !!antialize; i->multiply = antialize?multiply*2:multiply; i->height2 = antialize?2*buf->height:buf->height; i->width2 = antialize?2*buf->width:buf->width; @@ -250,6 +283,19 @@ void swf_Render_Init(RENDERBUF*buf, int posx, int posy, int width, int height, c i->lines[y].points = swf_InsertTag(0, 0); } } +void swf_Render_SetBackground(RENDERBUF*buf, RGBA*img, int width, int height) +{ + renderbuf_internal*i = (renderbuf_internal*)buf->internal; + RGBA*bck = (RGBA*)rfx_alloc(sizeof(RGBA)*width*height); + memcpy(bck, img, sizeof(RGBA)*width*height); + i->background = bck; + i->background_width = width; + i->background_height = height; +} +void swf_Render_SetBackgroundColor(RENDERBUF*buf, RGBA color) +{ + swf_Render_SetBackground(buf, &color, 1, 1); +} void swf_Render_AddImage(RENDERBUF*buf, U16 id, RGBA*img, int width, int height) { renderbuf_internal*i = (renderbuf_internal*)buf->internal; @@ -278,6 +324,10 @@ void swf_Render_Delete(RENDERBUF*dest) bitmap_t*b = i->bitmaps; dummyshape_t*d = i->dshapes; + if(i->background) { + free(i->background);i->background=0; + } + /* delete line buffers */ for(y=0;yheight2;y++) { swf_DeleteTag(i->lines[y].points); @@ -305,6 +355,34 @@ void swf_Render_Delete(RENDERBUF*dest) rfx_free(dest->internal); dest->internal = 0; } +static void swf_Render_AddShape(RENDERBUF*dest,dummyshape_t*s) +{ + renderbuf_internal*i = (renderbuf_internal*)dest->internal; + + s->next = 0; + if(i->dshapes_next) + i->dshapes_next->next = s; + i->dshapes_next = s; + if(!i->dshapes) { + i->dshapes = s; + } +} + +static SHAPE2* linestyle2fillstyle(SHAPE2*shape) +{ + SHAPE2*s = rfx_calloc(sizeof(SHAPE2)); + int t; + s->numfillstyles = shape->numlinestyles; + s->fillstyles = (FILLSTYLE*)rfx_calloc(sizeof(FILLSTYLE)*shape->numlinestyles); + s->lines = (SHAPELINE*)rfx_calloc(sizeof(SHAPELINE)*shape->numlinestyles); + for(t=0;tnumlinestyles;t++) { + s->lines[t].fillstyle0 = t+1; + s->fillstyles[t].type = FILL_SOLID; + s->fillstyles[t].color = shape->linestyles[t].color; + } + return s; +} + void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _depth,U16 _clipdepth) { renderbuf_internal*i = (renderbuf_internal*)dest->internal; @@ -317,41 +395,60 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept renderpoint_t p, lp; memset(&p, 0, sizeof(renderpoint_t)); memset(&lp, 0, sizeof(renderpoint_t)); + p.type = _clipdepth?clip_type:fill_type; - p.shape = shape; p.depth = _depth << 16; p.clipdepth = _clipdepth << 16; + mat.tx -= dest->posx*20; mat.ty -= dest->posy*20; - if(shape->numlinestyles) { - dummyshape_t*dshape = rfx_calloc(sizeof(dummyshape_t)); - lshape = rfx_calloc(sizeof(SHAPE2)); + if(shape->numfillstyles) { + dummyshape_t*fshape = rfx_calloc(sizeof(dummyshape_t)); int t; - lshape->numfillstyles = shape->numlinestyles; - lshape->fillstyles = (FILLSTYLE*)rfx_calloc(sizeof(FILLSTYLE)*shape->numlinestyles); - lshape->lines = (SHAPELINE*)rfx_calloc(sizeof(SHAPELINE)*shape->numlinestyles); - for(t=0;tnumlinestyles;t++) { - lshape->lines[t].fillstyle0 = t+1; - lshape->fillstyles[t].type = FILL_SOLID; - lshape->fillstyles[t].color = shape->linestyles[t].color; + SHAPE2* s2 = swf_Shape2Clone(shape); + + fshape->shape = s2; + + p.s = fshape; + + /* multiply fillstyles matrices with placement matrix- + important for texture and gradient fill */ + for(t=0;tnumfillstyles;t++) { + MATRIX nm; + swf_MatrixJoin(&nm, &s2->fillstyles[t].m, &mat); //TODO: is this the right order? + nm.sx *= i->multiply; + nm.sy *= i->multiply; + nm.r0 *= i->multiply; + nm.r1 *= i->multiply; + nm.tx *= i->multiply; + nm.ty *= i->multiply; + s2->fillstyles[t].m = nm; } - lp.type = fill_type; - lp.shape = lshape; - lp.depth = p.depth+1; /* add this shape to the global shape list, for deallocing */ + swf_Render_AddShape(dest, fshape); + } + + if(shape->numlinestyles) { + dummyshape_t*dshape = rfx_calloc(sizeof(dummyshape_t)); + + lshape = linestyle2fillstyle(shape); + + lp.type = fill_type; + lp.s = dshape; + lp.depth = (_depth << 16)+1; + dshape->shape = lshape; - i->dshapes_next = dshape; - if(!i->dshapes) { - i->dshapes = dshape; - } + + /* add this shape to the global shape list, for deallocing */ + swf_Render_AddShape(dest, dshape); } if(p.clipdepth) { /* reverse shape */ p.shapeline = 0; - add_line(dest, -20, 0, -20, i->height2*20, &p, 0); + add_line(dest, -20, 0, -20, i->height2*20, &p); } while(line) @@ -363,11 +460,12 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept if(line->type == moveTo) { } else if(line->type == lineTo) { if(DEBUG&4) { + int l; x1 = x; y1 = y; x2 = line->x; y2 = line->y; - int l = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); + l = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); printf("%d - %.2f/%.2f -> %.2f/%.2f ", l, x1/20.0, y1/20.0, x2/20.0, y2/20.0); } @@ -379,20 +477,23 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept add_solidline(dest, x1, y1, x3, y3, shape->linestyles[line->linestyle-1].width, &lp); lp.depth++; } - if(line->fillstyle0 || line->fillstyle1) - add_line(dest, x1, y1, x3, y3, &p, 0); + if(line->fillstyle0 || line->fillstyle1) { + assert(shape->numfillstyles); + add_line(dest, x1, y1, x3, y3, &p); + } if(DEBUG&4) printf("\n"); } else if(line->type == splineTo) { + int c,t,parts,qparts; + double xx,yy; transform_point(&mat, x, y, &x1, &y1); transform_point(&mat, line->sx, line->sy, &x2, &y2); transform_point(&mat, line->x, line->y, &x3, &y3); - int c = abs(x3-2*x2+x1) + abs(y3-2*y2+y1); - int parts,qparts; - int t; - double xx=x1,yy=y1; + c = abs(x3-2*x2+x1) + abs(y3-2*y2+y1); + xx=x1; + yy=y1; parts = (int)(sqrt(c)/3); if(!parts) parts = 1; @@ -414,8 +515,10 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept add_solidline(dest, xx, yy, nx, ny, shape->linestyles[line->linestyle-1].width, &lp); lp.depth++; } - if(line->fillstyle0 || line->fillstyle1) - add_line(dest, (int)xx, (int)yy, (int)nx, (int)ny, &p, 0); + if(line->fillstyle0 || line->fillstyle1) { + assert(shape->numfillstyles); + add_line(dest, (int)xx, (int)yy, (int)nx, (int)ny, &p); + } xx = nx; yy = ny; @@ -486,8 +589,10 @@ static void fill_bitmap(RGBA*line, int y, int x1, int x2, MATRIX*m, bitmap_t*b, } do { + RGBA col; int xx = (int)(( (x - rx) * m22 - (y - ry) * m21)*det); int yy = (int)((- (x - rx) * m12 + (y - ry) * m11)*det); + int ainv; if(clip) { if(xx<0) xx=0; @@ -499,8 +604,8 @@ static void fill_bitmap(RGBA*line, int y, int x1, int x2, MATRIX*m, bitmap_t*b, yy %= b->height; } - RGBA col = b->data[yy*b->width+xx]; - int ainv = 255-col.a; + col = b->data[yy*b->width+xx]; + ainv = 255-col.a; line[x].r = ((line[x].r*ainv)>>8)+col.r; line[x].g = ((line[x].g*ainv)>>8)+col.g; @@ -512,13 +617,14 @@ static void fill_bitmap(RGBA*line, int y, int x1, int x2, MATRIX*m, bitmap_t*b, static void fill(RENDERBUF*dest, RGBA*line, int y, int x1, int x2, state_t*state) { renderbuf_internal*i = (renderbuf_internal*)dest->internal; + U32 clipdepth; layer_t*l = state->layers; if(x1>=x2) //zero width? nothing to do. return; - U32 clipdepth = 0; + clipdepth = 0; while(l) { if(l->p->depth < clipdepth) { if(DEBUG&2) printf("(clipped)"); @@ -533,14 +639,14 @@ static void fill(RENDERBUF*dest, RGBA*line, int y, int x1, int x2, state_t*state /* not filled. TODO: we should never add those in the first place */ if(DEBUG&2) printf("(not filled)"); - } else if(l->fillid > l->p->shape->numfillstyles) { - fprintf(stderr, "Fill style out of bounds (%d>%d)", l->fillid, l->p->shape->numlinestyles); + } else if(l->fillid > l->p->s->shape->numfillstyles) { + fprintf(stderr, "Fill style out of bounds (%d>%d)", l->fillid, l->p->s->shape->numlinestyles); } else { FILLSTYLE*f; if(DEBUG&2) printf("(%d -> %d style %d)", x1, x2, l->fillid); - f = &l->p->shape->fillstyles[l->fillid-1]; + f = &l->p->s->shape->fillstyles[l->fillid-1]; if(f->type == FILL_SOLID) { /* plain color fill */ @@ -555,16 +661,17 @@ static void fill(RENDERBUF*dest, RGBA*line, int y, int x1, int x2, state_t*state fprintf(stderr, "Shape references unknown bitmap %d\n", f->id_bitmap); fill_plain(line, x1, x2, color_red); } else { - MATRIX m = f->m; - m.tx -= dest->posx*20; - m.ty -= dest->posy*20; - m.sx *= i->multiply; - m.sy *= i->multiply; - m.r0 *= i->multiply; - m.r1 *= i->multiply; - m.tx *= i->multiply; - m.ty *= i->multiply; - fill_bitmap(line, y, x1, x2, &m, b, FILL_CLIPPED?1:0); + //done in swf_RenderShape now + //MATRIX m = f->m; + //m.tx -= dest->posx*20; + //m.ty -= dest->posy*20; + //m.sx *= i->multiply; + //m.sy *= i->multiply; + //m.r0 *= i->multiply; + //m.r1 *= i->multiply; + //m.tx *= i->multiply; + //m.ty *= i->multiply; + fill_bitmap(line, y, x1, x2, &f->m, b, FILL_CLIPPED?1:0); } } } @@ -706,13 +813,23 @@ RGBA* swf_Render(RENDERBUF*dest) int size = sizeof(renderpoint_t); int num = tag->len / size; RGBA*line = line1; + state_t state; + memset(&state, 0, sizeof(state_t)); + if((y&1) && i->antialize) line = line2; - state_t state; - memset(&state, 0, sizeof(state_t)); - memset(line, 0, sizeof(RGBA)*i->width2); + if(!i->background) { + memset(line, 0, sizeof(RGBA)*i->width2); + } else { + int x,xx; + int xstep=i->background_width*65536/i->width2; + RGBA*src = &i->background[(i->background_height*y/i->height2)*i->background_width]; + for(x=0,xx=0;xwidth2;x++,xx+=xstep) { + line[x] = src[xx>>16]; + } + } memory += tag->memsize; qsort(tag->data, num, size, compare_renderpoints); for(n=0;n