#include #include #include "fimage.h" /* TODO: * * rename to fragment_list? * is the memory management too crackful? */ struct fimage_t { pixman_bool_t broken; int n_allocated_fragments; int n_fragments; fragment_t * fragments[1]; }; static const fimage_t broken_fimage = { TRUE, /* broken */ 0, /* n_allocated_fragments */ 0, /* n_fragments */ { NULL } /* fragments */ }; static fimage_t * fimage_ensure_space (fimage_t *fimage, int n_more) { int required_fragments = fimage->n_fragments + n_more; if (required_fragments > fimage->n_allocated_fragments) { fimage_t *new_image; size_t space; int pot; pot = 1; while (pot < required_fragments) pot *= 2; space = sizeof (fimage_t) + (pot - 1) * sizeof (fragment_t *); if (!(new_image = realloc (fimage, space))) { fimage_free (fimage); return (fimage_t *)&broken_fimage; } new_image->n_allocated_fragments = pot; fimage = new_image; } return fimage; } static fimage_t * fimage_append_fragment (fimage_t *fimage, fragment_t *fragment) { if (fimage->broken || fragment_is_broken (fragment)) { fimage_free (fimage); fragment_free (fragment); return (fimage_t *)&broken_fimage; } if (fragment_is_empty (fragment)) { fragment_free (fragment); return fimage; } fimage = fimage_ensure_space (fimage, 1); if (fimage->broken) return fimage; fimage->fragments[fimage->n_fragments++] = fragment; return fimage; } static fimage_t * fimage_new (void) { fimage_t *fimage; if (!(fimage = malloc (sizeof *fimage))) return (fimage_t *)&broken_fimage; fimage->broken = FALSE; fimage->n_allocated_fragments = 1; fimage->n_fragments = 0; return fimage; } static fimage_t * make_image (fragment_t *fragment) { return fimage_append_fragment (fimage_new(), fragment); } fimage_t * fimage_new_blank (int width, int height) { return make_image (fragment_new_blank (width, height)); } fimage_t * fimage_new_white (int width, int height) { return make_image (fragment_new_white (width, height)); } fimage_t * fimage_new_traps (int width, int height, int n_traps, pixman_trapezoid_t *traps) { return make_image ( fragment_new_traps (width, height, n_traps, traps)); } fimage_t * fimage_new_glyphs (int width, int height, pixman_glyph_cache_t *cache, int n_glyphs, pixman_glyph_t *glyphs) { return make_image ( fragment_new_glyphs (width, height, cache, n_glyphs, glyphs)); } /* Takes ownership of the image */ fimage_t * fimage_new_image (int width, int height, pixman_image_t *image) { return make_image (fragment_new_image (width, height, image)); } /* Makes a copy of the region; does not take ownership */ fimage_t * fimage_new_region (int width, int height, pixman_region32_t *region) { fragment_t *fragment1, *fragment2; fimage_t *image; fragment1 = fragment_new_region (region); fragment2 = fragment_new_blank (width, height); fragment2 = fragment_subtract (fragment1, fragment2); image = fimage_new (); image = fimage_append_fragment (image, fragment1); image = fimage_append_fragment (image, fragment2); return image; } fimage_t * fimage_composite (fimage_t *dest, pixman_op_t op, fimage_t *source) { fimage_t *new_image; int i, j; if (dest->broken || source->broken) { fimage_free (dest); return (fimage_t *)&broken_fimage; } new_image = fimage_new (); for (i = 0; dest->n_fragments; ++i) { for (j = 0; j < source->n_fragments; ++j) { fragment_t *new_frag, *dfrag, *sfrag; dfrag = dest->fragments[i]; sfrag = source->fragments[j]; new_frag = fragment_composite (dfrag, op, sfrag); new_image = fimage_append_fragment (new_image, new_frag); new_image = fimage_append_fragment (new_image, dfrag); } } dest->n_fragments = 0; fimage_free (dest); return new_image; } void fimage_paint (fimage_t *image, pixman_image_t *pimage) { int i; for (i = 0; i < image->n_fragments; ++i) { fragment_t *fragment = image->fragments[i]; fragment_apply (fragment, pimage); } } void fimage_free (fimage_t *image) { int i; for (i = 0; i < image->n_fragments; ++i) fragment_free (image->fragments[i]); free (image); }