renamed png functions
[swftools.git] / lib / readers / swf.c
index 1bad19b..bf95022 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <assert.h>
 #include "../gfxdevice.h"
 #include "../gfxsource.h"
@@ -21,7 +22,6 @@ typedef struct _swf_page_internal
 typedef struct _swf_doc_internal
 {
     map16_t*id2char;
-    int clips;
     SWF swf;
     int width,height;
     MATRIX m;
@@ -92,7 +92,7 @@ void map16_free(map16_t*map)
 void map16_add_id(map16_t*map, int nr, void*id)
 {
     if(map->ids[nr])
-       fprintf(stderr, "Warning: ID %d defined more than once\n");
+       fprintf(stderr, "Warning: ID %d defined more than once\n", nr);
     map->ids[nr] = id;
 }
 void map16_remove_id(map16_t*map, int nr)
@@ -149,21 +149,27 @@ static gfxgradient_t* convertGradient(GRADIENT*from)
 gfxline_t* swfline_to_gfxline(SHAPELINE*line, int linestyle, int fillstyle0)
 {
     gfxdrawer_t d;
-    SCOORD x=0,y=0;
+    SCOORD x=0,y=0,xx=0,yy=0;
     gfxline_t*l;
     gfxdrawer_target_gfxline(&d);
     if(line && line->type != moveTo) {
        fprintf(stderr, "Warning: Shape doesn't start with a moveTo\n");
     }
+    xx = line?line->x+1:0;
     while(line) {
-       if(line->fillstyle0 == fillstyle0 || line->fillstyle1 == fillstyle0 || 
+       if(line->fillstyle0 == fillstyle0 || 
+          line->fillstyle1 == fillstyle0 || 
           line->linestyle == linestyle) {
            if(line->type == lineTo) {
-               d.moveTo(&d, x/20.0,y/20.0);
+               if(xx!=x || yy!=y) d.moveTo(&d, x/20.0,y/20.0);
                d.lineTo(&d, line->x/20.0,line->y/20.0);
+               xx = line->x;
+               yy = line->y;
            } else if(line->type == splineTo) {
-               d.moveTo(&d, x/20.0,y/20.0);
+               if(xx!=x || yy!=y) d.moveTo(&d, x/20.0,y/20.0);
                d.splineTo(&d, line->sx/20.0, line->sy/20.0, line->x/20.0,line->y/20.0);
+               xx = line->x;
+               yy = line->y;
            }
        }
        x = line->x;
@@ -177,7 +183,7 @@ gfxline_t* swfline_to_gfxline(SHAPELINE*line, int linestyle, int fillstyle0)
 
 //---- bitmap handling ----
 
-gfximage_t* gfximage_new(RGBA*data, int width, int height)
+static gfximage_t* gfximage_new(RGBA*data, int width, int height)
 {
     gfximage_t* b = (gfximage_t*)rfx_calloc(sizeof(gfximage_t));
     b->data = (gfxcolor_t*)data;
@@ -186,13 +192,6 @@ gfximage_t* gfximage_new(RGBA*data, int width, int height)
     return b;
 }
 
-void gfximage_free(gfximage_t*b)
-{
-    free(b->data); //!
-    b->data = 0;
-    free(b);
-}
-
 static gfximage_t* findimage(render_t*r, U16 id)
 {
     character_t*c = (character_t*)map16_get_id(r->id2char, id);
@@ -201,7 +200,7 @@ static gfximage_t* findimage(render_t*r, U16 id)
 
     /*char filename[80];
     sprintf(filename, "bitmap%d.png", id);
-    writePNG(filename, (unsigned char*)img->data, img->width, img->height);
+    png_write(filename, (unsigned char*)img->data, img->width, img->height);
     printf("saving bitmap %d to %s\n", id, filename);*/
 
     return c->data;
@@ -228,7 +227,15 @@ static void renderFilled(render_t*r, gfxline_t*line, FILLSTYLE*f, CXFORM*cx, MAT
     } else if(f->type == FILL_LINEAR || f->type == FILL_RADIAL) {
        gfxmatrix_t m;
        gfxgradient_t* g;
-       convertMatrix(&f->m, &m);
+       MATRIX* m2 = &f->m;
+       //swf_MatrixJoin(&m2, po_m, &f->m);
+
+       double z = f->type==FILL_RADIAL?4:4;
+       m.m00 = m2->sx/z/20.0; m.m10 = m2->r1/z/20.0;
+       m.m01 = m2->r0/z/20.0; m.m11 = m2->sy/z/20.0;
+       m.tx = m2->tx/20.0;
+       m.ty = m2->ty/20.0;
+
        g = convertGradient(&f->gradient);
        r->device->fillgradient(r->device, line, g, f->type == FILL_LINEAR ? gfxgradient_linear : gfxgradient_radial, &m);
        free(g);
@@ -333,7 +340,8 @@ static map16_t* extractDefinitions(SWF*swf)
            map16_add_id(map, id, c);
        }
        else if(tag->id == ST_DEFINEFONT ||
-               tag->id == ST_DEFINEFONT2) {
+               tag->id == ST_DEFINEFONT2 ||
+               tag->id == ST_DEFINEFONT3) {
            character_t*c = rfx_calloc(sizeof(character_t));
            SWFFONT*swffont = 0;
            font_t*font = (font_t*)rfx_calloc(sizeof(font_t));
@@ -348,6 +356,10 @@ static map16_t* extractDefinitions(SWF*swf)
                 }
                 SHAPE2*s2 = swf_ShapeToShape2(swffont->glyph[t].shape);
                 font->glyphs[t] = swfline_to_gfxline(s2->lines, 0, 1);
+               if(tag->id==ST_DEFINEFONT3) {
+                   gfxmatrix_t m = {1/20.0,0,0, 0,1/20.0,0};
+                   gfxline_transform(font->glyphs[t], &m);
+               }
                 swf_Shape2Free(s2);
             }
             swf_FontFree(swffont);
@@ -409,9 +421,11 @@ static map16_t* extractFrame(TAG*startTag, int frame_to_extract)
     TAG*tag = startTag;
     int frame = 1;
     int insprite = 0;
+
+    SWF*swf = rfx_calloc(sizeof(SWF));
+    swf->firstTag = startTag;
+
     for(;tag;tag = tag->next) {
-       if(tag->id == ST_END) 
-           break;
        if(tag->id == ST_DEFINESPRITE) {
            while(tag->id != ST_END)
                tag = tag->next;
@@ -437,7 +451,7 @@ static map16_t* extractFrame(TAG*startTag, int frame_to_extract)
            U16 depth = swf_GetDepth(tag);
            map16_remove_id(depthmap, depth);
        }
-       if(tag->id == ST_SHOWFRAME || tag->id == ST_END) {
+       if(tag->id == ST_SHOWFRAME || tag->id == ST_END || !tag->next) {
            if(frame == frame_to_extract) {
                return depthmap;
            }
@@ -446,21 +460,14 @@ static map16_t* extractFrame(TAG*startTag, int frame_to_extract)
                map16_enumerate(depthmap, increaseAge, 0);
            }
        }
+       if(tag->id == ST_END) 
+           break;
     }
-    fprintf(stderr, "gfxsource_swf: frame %d not found\n", frame_to_extract);
     return depthmap;
 }
 
 // ---- rendering ----
 
-static void stopClippings(int from, render_t*r)
-{
-    int t;
-    for(t=from;t<r->clips;t++)
-       r->device->endclip(r->device);
-    r->clips = from;
-}
-
 void swf_ShapeApplyMatrix(SHAPE2*shape, MATRIX*m)
 {
 }
@@ -513,7 +520,6 @@ static void renderCharacter(render_t*r, placement_t*p, character_t*c)
               } else { 
                   r->device->startclip(r->device, line);
                    r->clips_waiting[p->po.clipdepth]++;
-                  r->clips++;
               }
           }
           gfxline_free(line);
@@ -554,11 +560,23 @@ static void placeObject(void*self, int id, void*data)
         return;
     }
     if(c->type == TYPE_SPRITE) {
-        int oldclip = r->clips;
+        int*old_clips_waiting = r->clips_waiting;
+        r->clips_waiting = rfx_calloc(sizeof(r->clips_waiting[0])*65536);
+
         sprite_t* s = (sprite_t*)c->data;
-        map16_t* depths = extractFrame(c->tag, p->age % s->frameCount);
+
+        map16_t* depths = extractFrame(c->tag->next, s->frameCount>0? p->age % s->frameCount : 0);
         map16_enumerate(depths, placeObject, r);
-        stopClippings(oldclip, r);
+       
+        int t;
+        for(t=0;t<65536;t++) {
+            int i;
+            for(i=0; i<r->clips_waiting[t]; i++) {
+                r->device->endclip(r->device);
+            }
+        }
+        free(r->clips_waiting);
+        r->clips_waiting = old_clips_waiting;
         return;
     }
     renderCharacter(r, p, c);
@@ -586,13 +604,13 @@ void swfpage_render(gfxpage_t*page, gfxdevice_t*output)
 
     int t;
     for(t=0;t<65536;t++) {
+       if(depths->ids[t]) {
+           placeObject(&r, t, depths->ids[t]);
+       }
         int i;
         for(i=0; i<r.clips_waiting[t]; i++) {
             output->endclip(output);
         }
-       if(depths->ids[t]) {
-           placeObject(&r, t, depths->ids[t]);
-       }
     }
     free(r.clips_waiting);
 }
@@ -612,7 +630,7 @@ void swf_doc_destroy(gfxdocument_t*gfx)
     free(gfx);gfx=0;
 }
 
-void swf_doc_set_parameter(gfxdocument_t*gfx, const char*name, const char*value)
+void swf_doc_setparameter(gfxdocument_t*gfx, const char*name, const char*value)
 {
     swf_doc_internal_t*i= (swf_doc_internal_t*)gfx->internal;
 }
@@ -640,7 +658,7 @@ gfxpage_t* swf_doc_getpage(gfxdocument_t*doc, int page)
     return swf_page;
 }
 
-void swf_set_parameter(gfxsource_t*src, const char*name, const char*value)
+void swf_setparameter(gfxsource_t*src, const char*name, const char*value)
 {
     msg("<verbose> setting parameter %s to \"%s\"", name, value);
 }
@@ -685,17 +703,26 @@ gfxdocument_t*swf_open(gfxsource_t*src, const char*filename)
     swf_doc->internal = i;
     swf_doc->get = 0;
     swf_doc->destroy = swf_doc_destroy;
-    swf_doc->set_parameter = swf_doc_set_parameter;
+    swf_doc->setparameter = swf_doc_setparameter;
     swf_doc->getpage = swf_doc_getpage;
 
     return swf_doc;
 }
 
+static void swf_destroy(gfxsource_t*src)
+{
+    memset(src, 0, sizeof(*src));
+    free(src);
+}
+
+
 gfxsource_t*gfxsource_swf_create()
 {
     gfxsource_t*src = (gfxsource_t*)malloc(sizeof(gfxsource_t));
     memset(src, 0, sizeof(gfxsource_t));
-    src->set_parameter = swf_set_parameter;
+    src->setparameter = swf_setparameter;
     src->open = swf_open;
+    src->destroy = swf_destroy;
     return src;
 }
+