+static gfximage_t* findimage(render_t*r, U16 id)
+{
+ character_t*c = (character_t*)map16_get_id(r->id2char, id);
+ assert(c && c->type == TYPE_BITMAP);
+ gfximage_t*img = (gfximage_t*)c->data;
+
+ /*char filename[80];
+ sprintf(filename, "bitmap%d.png", id);
+ writePNG(filename, (unsigned char*)img->data, img->width, img->height);
+ printf("saving bitmap %d to %s\n", id, filename);*/
+
+ return c->data;
+}
+//---- shape handling ----
+
+static void renderFilled(render_t*r, gfxline_t*line, FILLSTYLE*f, CXFORM*cx, MATRIX*po_m)
+{
+ if(f->type == FILL_SOLID) {
+ gfxcolor_t c = *(gfxcolor_t*)&f->color;
+ r->device->fill(r->device, line, &c);
+ } else if(f->type == FILL_TILED || f->type == FILL_CLIPPED) {
+ gfximage_t* img = findimage(r, f->id_bitmap);
+ gfxmatrix_t m;
+ gfxcxform_t gfxcx;
+ convertCXForm(cx, &gfxcx);
+ MATRIX m2;
+ swf_MatrixJoin(&m2, po_m, &f->m);
+ convertMatrix(&m2, &m);
+ m.m00/=20.0; m.m10/=20.0;
+ m.m01/=20.0; m.m11/=20.0;
+ /* TODO: handle clipped */
+ r->device->fillbitmap(r->device, line, img, &m, &gfxcx);
+ } else if(f->type == FILL_LINEAR || f->type == FILL_RADIAL) {
+ gfxmatrix_t m;
+ gfxgradient_t* g;
+ convertMatrix(&f->m, &m);
+ g = convertGradient(&f->gradient);
+ r->device->fillgradient(r->device, line, g, f->type == FILL_LINEAR ? gfxgradient_linear : gfxgradient_radial, &m);
+ free(g);
+ }
+}
+
+//---- font handling ----
+
+typedef struct
+{
+ int numchars;
+ gfxline_t**glyphs;
+} font_t;
+
+typedef struct textcallbackblock
+{
+ render_t*r;
+ MATRIX m;
+} textcallbackblock_t;
+
+static void textcallback(void*self, int*chars, int*xpos, int nr, int fontid, int fontsize,
+ int xstart, int ystart, RGBA* color)
+{
+ textcallbackblock_t * info = (textcallbackblock_t*)self;
+ font_t*font = 0;
+ int t;
+ character_t*cfont = map16_get_id(info->r->id2char, fontid);
+ if(!cfont) {
+ fprintf(stderr, "Font %d unknown\n", fontid);
+ return;
+ }
+ if(cfont->type != TYPE_FONT) {
+ fprintf(stderr, "ID %d is not a font\n", fontid);
+ return;
+ }
+ font = cfont->data;
+
+ for(t=0;t<nr;t++) {
+ int x = xstart + xpos[t];
+ int y = ystart;
+ MATRIX m = info->m;
+ SPOINT p;
+
+ p.x = x; p.y = y;
+ p = swf_TurnPoint(p, &m);
+
+ m.sx = (m.sx * fontsize) / 1024;
+ m.sy = (m.sy * fontsize) / 1024;
+ m.r0 = (m.r0 * fontsize) / 1024;
+ m.r1 = (m.r1 * fontsize) / 1024;
+ m.tx = p.x;
+ m.ty = p.y;
+
+ gfxmatrix_t gm;
+ convertMatrix(&m, &gm);
+
+ if(chars[t]<0 || chars[t]>= font->numchars) {
+ fprintf(stderr, "Character out of range: %d\n", chars[t]);
+ } else {
+ gfxline_t*line = gfxline_clone(font->glyphs[chars[t]]);
+ gfxline_transform(line, &gm);
+ FILLSTYLE f;
+ f.type = FILL_SOLID;
+ f.color = *color;
+ renderFilled(info->r, line, &f, 0, 0);
+ gfxline_free(line);
+ }
+ }
+}
+
+
+//---- tag handling ----