X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfrender.c;h=5a822b927fcc47b2e4356b7e101663e8d1cb322c;hb=740d0ef26c9be6147611276fd48cd835282b8b49;hp=db1a2d1a76a77597a2291c654a788f3833a16a91;hpb=90e82ae6c7f404670088aba9bebd012ce90ba932;p=swftools.git diff --git a/lib/modules/swfrender.c b/lib/modules/swfrender.c index db1a2d1..5a822b9 100644 --- a/lib/modules/swfrender.c +++ b/lib/modules/swfrender.c @@ -31,16 +31,21 @@ typedef struct _dummyshape struct _dummyshape*next; } dummyshape_t; +/* one bit flag: */ +#define clip_type 0 +#define fill_type 1 + typedef struct _renderpoint { - enum {clip_type, fill_type} type; - float fx; //for sorting - int x; + char type; + float x; U32 depth; - U32 clipdepth; + SHAPELINE*shapeline; - + + U32 clipdepth; dummyshape_t*s; + } renderpoint_t; /* @@ -93,13 +98,103 @@ 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 { + int num = GET32(tag->data); + PUT32(tag->data, num+1); + } + + swf_SetBits(tag, p->type, 1); + swf_SetBits(tag, *(U32*)&p->x, 32); + if(p->depth & 0xffff) { + swf_SetBits(tag, 1, 1); + swf_SetBits(tag, p->depth, 32); + } else { + swf_SetBits(tag, 0, 1); + swf_SetBits(tag, p->depth >> 16, 16); + } + swf_SetBits(tag, *(U32*)&p->shapeline, 32); + if(p->type == clip_type) { + if(p->clipdepth & 0xffff) { + swf_SetBits(tag, 1, 1); + swf_SetBits(tag, p->clipdepth, 32); + } else { + swf_SetBits(tag, 0, 1); + swf_SetBits(tag, p->clipdepth >> 16, 16); + } + /* don't set s */ + } else { + swf_SetBits(tag, *(U32*)&p->s, 32); + /* don't set clipdepth */ + } +} +static renderpoint_t renderpoint_read(TAG*tag, int num) +{ + renderpoint_t p; + U8 flag = 0; + U32 dummy = 0; + + p.type = swf_GetBits(tag, 1); + + dummy = swf_GetBits(tag, 32);p.x = *(float*)&dummy; + flag = swf_GetBits(tag, 1); + if(flag) { + p.depth = swf_GetBits(tag, 32); + } else { + p.depth = swf_GetBits(tag, 16) << 16; + } + dummy = swf_GetBits(tag, 32);p.shapeline = *(SHAPELINE**)&dummy; + if(p.type == clip_type) { + flag = swf_GetBits(tag, 1); + if(flag) { + p.clipdepth = swf_GetBits(tag, 32); + } else { + p.clipdepth = swf_GetBits(tag, 16) << 16; + } + p.s = 0; + } else { + dummy = swf_GetBits(tag, 32);p.s = *(dummyshape_t**)&dummy; + p.clipdepth = 0; + } + + 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); + if(tag->len == 0) + num = 0; + else + 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; + if(y<10) + renderpoint_write(i->lines[y].points, p); + else + renderpoint_write(i->lines[y].points, p); } /* set this to 0.777777 or something if the "both fillstyles set while not inside shape" @@ -184,7 +279,6 @@ static void add_solidline(RENDERBUF*buf, double x1, double y1, double x2, double double xx,yy; /* Make sure the line is always at least one pixel wide */ -#define LINEMODE1 #ifdef LINEMODE1 /* That's what Macromedia's Player does at least at zoom level >= 1. */ width += 20; @@ -266,8 +360,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; } @@ -622,22 +716,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(l) { + 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); + } + 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); @@ -683,7 +796,6 @@ static void fill(RENDERBUF*dest, RGBA*line, int y, int x1, int x2, state_t*state } } } - l = l->next; } } @@ -815,19 +927,22 @@ 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 state; - memset(&state, 0, sizeof(state_t)); + 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; - if(!i->background) { memset(line, 0, sizeof(RGBA)*i->width2); } else { @@ -839,10 +954,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) @@ -850,13 +965,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) { @@ -877,6 +996,7 @@ RGBA* swf_Render(RENDERBUF*dest) } } } + free(points); } free(line1); free(line2);