X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfrender.c;h=b21dfc3687b22e2c67b8758c30eb05614a48cea4;hb=e93c6b5a93fcdf135c10b93f1f63770f0c1a5079;hp=ad372cc25ef15fef13d5552c1b2c7d5cef44d67e;hpb=1948db8873541c788d40be5ab7028bf4354520a2;p=swftools.git diff --git a/lib/modules/swfrender.c b/lib/modules/swfrender.c index ad372cc..b21dfc3 100644 --- a/lib/modules/swfrender.c +++ b/lib/modules/swfrender.c @@ -31,16 +31,20 @@ typedef struct _dummyshape struct _dummyshape*next; } dummyshape_t; +#define clip_type 0 +#define fill_type 1 + typedef struct _renderpoint { - enum {clip_type, fill_type} type; - float fx; //for sorting - int x; + float x; U32 depth; - U32 clipdepth; + SHAPELINE*shapeline; - + + U32 clipdepth; dummyshape_t*s; + + char type; } renderpoint_t; /* @@ -93,13 +97,50 @@ typedef struct _renderbuf_internal #define DEBUG 0 +static void renderpoint_write(TAG*tag, renderpoint_t*p) +{ + if(tag->len == 0) { + swf_SetU32(tag, 1); + } else { + PUT32(tag->data, GET32(tag->data)+1); + } + //swf_SetU8(tag, 0); + swf_SetBlock(tag, (U8*)p, sizeof(renderpoint_t)); +} +static renderpoint_t renderpoint_read(TAG*tag) +{ + renderpoint_t p; + //swf_GetU8(tag); + swf_GetBlock(tag, (U8*)&p, sizeof(renderpoint_t)); + return p; +} + +static int renderpoint_num(TAG*tag) +{ + if(tag->len == 0) + return 0; + return GET32(tag->data); +} + +static renderpoint_t* renderpoint_readall(TAG*tag) +{ + int num; + int t; + renderpoint_t*p; + swf_SetTagPos(tag, 0); + num = swf_GetU32(tag); + p = (renderpoint_t*)rfx_alloc(num*sizeof(renderpoint_t)); + for(t=0;tinternal; if(x >= i->width2 || y >= i->height2 || y<0) return; - p->x = (int)x; - p->fx = x; - swf_SetBlock(i->lines[y].points, (U8*)p, sizeof(renderpoint_t)); + p->x = x; + renderpoint_write(i->lines[y].points, p); } /* set this to 0.777777 or something if the "both fillstyles set while not inside shape" @@ -109,6 +150,8 @@ static inline void add_pixel(RENDERBUF*dest, float x, int y, renderpoint_t*p) 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); @@ -125,15 +168,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; @@ -145,20 +190,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,10 +223,17 @@ static void add_solidline(RENDERBUF*buf, double x1, double y1, double x2, double double lastx,lasty; double vx,vy; double xx,yy; - - /* The Flash Player does this, too. This means every line is always at least - one pixel wide */ + + /* Make sure the line is always at least one pixel wide */ +#ifdef LINEMODE1 + /* That's what Macromedia's Player does at least at zoom level >= 1. */ width += 20; +#else + /* That's what Macromedia's Player seems to do at zoom level 0. */ + /* TODO: needs testing */ + if(width<20) + width = 20; +#endif sd = (double)dx*(double)dx+(double)dy*(double)dy; d = sqrt(sd); @@ -252,8 +306,8 @@ static int compare_renderpoints(const void * _a, const void * _b) { renderpoint_t*a = (renderpoint_t*)_a; renderpoint_t*b = (renderpoint_t*)_b; - if(a->fx < b->fx) return -1; - if(a->fx > b->fx) return 1; + if(a->x < b->x) return -1; + if(a->x > b->x) return 1; return 0; } @@ -410,7 +464,7 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept important for texture and gradient fill */ for(t=0;tnumfillstyles;t++) { MATRIX nm; - swf_MatrixJoin(&nm, &s2->fillstyles[t].m, m); //TODO: is this the right order? + 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; @@ -454,11 +508,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); } @@ -477,15 +532,16 @@ void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _dept 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; @@ -581,8 +637,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; @@ -594,8 +652,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; @@ -604,21 +662,41 @@ static void fill_bitmap(RGBA*line, int y, int x1, int x2, MATRIX*m, bitmap_t*b, } while(++xinternal; + U32 clipdepth; - layer_t*l = state->layers; + layer_t*lc = clipstate->layers; + layer_t*lf = fillstate->layers; + layer_t*l = 0; if(x1>=x2) //zero width? nothing to do. return; + + clipdepth = 0; + while(lf) { + if(lc && (!lf || lc->p->depth < lf->p->depth)) { + l = lc; + lc = lc->next; + } else if(lf && (!lc || lf->p->depth < lc->p->depth)) { + l = lf; + lf = lf->next; + } else if(lf && lc && lf->p->depth == lc->p->depth) { + /* A clipshape and a fillshape at the same depth. Yuck. + Bug in the SWF file */ + fprintf(stderr, "Error: Multiple use of depth %d in SWF\n", lf->p->depth); + l = lc; + lc = lc->next; + } else { + fprintf(stderr, "Internal error: %08x %08x\n", lc, lf); + if(lc) fprintf(stderr, " lc->depth = %08x\n", lc->p->depth); + if(lf) fprintf(stderr, " lf->depth = %08x\n", lf->p->depth); + } - U32 clipdepth = 0; - while(l) { if(l->p->depth < clipdepth) { if(DEBUG&2) printf("(clipped)"); - l = l->next; - continue; + continue; } if(l->fillid < 0 /*clip*/) { if(DEBUG&2) printf("(add clip %d)", l->clipdepth); @@ -664,7 +742,6 @@ static void fill(RENDERBUF*dest, RGBA*line, int y, int x1, int x2, state_t*state } } } - l = l->next; } } @@ -796,17 +873,23 @@ RGBA* swf_Render(RENDERBUF*dest) RGBA * line1 = rfx_alloc(sizeof(RGBA)*i->width2); RGBA * line2 = rfx_alloc(sizeof(RGBA)*i->width2); + printf("%d\n", sizeof(renderpoint_t)); + for(y=0;yheight2;y++) { TAG*tag = i->lines[y].points; int n; int size = sizeof(renderpoint_t); - int num = tag->len / size; + int num = renderpoint_num(tag); + renderpoint_t*points = renderpoint_readall(tag); RGBA*line = line1; + state_t clipstate; + state_t fillstate; + memset(&clipstate, 0, sizeof(state_t)); + memset(&fillstate, 0, sizeof(state_t)); + if((y&1) && i->antialize) line = line2; - state_t state; - memset(&state, 0, sizeof(state_t)); if(!i->background) { memset(line, 0, sizeof(RGBA)*i->width2); @@ -819,10 +902,10 @@ RGBA* swf_Render(RENDERBUF*dest) } } memory += tag->memsize; - qsort(tag->data, num, size, compare_renderpoints); + qsort(points, num, sizeof(renderpoint_t), compare_renderpoints); for(n=0;ndata[size*n]; - renderpoint_t*next= ndata[size*(n+1)]:0; + renderpoint_t*p = &points[n]; + renderpoint_t*next= nx; int endx = next?next->x:i->width2; if(endx > i->width2) @@ -830,13 +913,17 @@ RGBA* swf_Render(RENDERBUF*dest) if(startx < 0) startx = 0; - change_state(y, &state, p); + if(p->type == clip_type) + change_state(y, &clipstate, p); + else + change_state(y, &fillstate, p); - fill(dest, line, y, startx, endx, &state); + fill(dest, line, y, startx, endx, &clipstate, &fillstate); if(endx == i->width2) break; } - free_layers(&state); + free_layers(&clipstate); + free_layers(&fillstate); if(DEBUG&2) printf("\n"); if(!i->antialize) {