diff --git a/unix/image.c b/unix/image.c index eecdec18..cf21900d 100644 --- a/unix/image.c +++ b/unix/image.c @@ -10,11 +10,8 @@ struct uiImage { static void freeImageRep(gpointer item) { cairo_surface_t *cs = (cairo_surface_t *) item; - unsigned char *buf; - buf = cairo_image_surface_get_data(cs); cairo_surface_destroy(cs); - uiprivFree(buf); } uiImage *uiNewImage(double width, double height) @@ -37,26 +34,41 @@ void uiFreeImage(uiImage *i) void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int byteStride) { cairo_surface_t *cs; - unsigned char *buf, *p; - uint8_t *src = (uint8_t *) pixels; - int cByteStride; - int n; + uint8_t *data, *pix; + int realStride; + int x, y; - // unfortunately for optimal performance cairo expects its own stride values and we will have to reconcile them if they differ - cByteStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pixelWidth); - buf = (unsigned char *) uiprivAlloc((cByteStride * pixelHeight) * sizeof (unsigned char), "unsigned char[]"); - p = buf; - for (n = 0; n < byteStride * pixelHeight; n += byteStride) { - memmove(p, src + n, cByteStride); - p += cByteStride; - } - // also note that stride here is also in bytes - cs = cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32, - pixelWidth, pixelHeight, - cByteStride); + // note that this is native-endian + cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + pixelWidth, pixelHeight); if (cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) /* TODO */; cairo_surface_flush(cs); + + pix = (uint8_t *) pixels; + data = (uint8_t *) cairo_image_surface_get_data(cs); + realStride = cairo_image_surface_get_stride(cs); + for (y = 0; y < pixelHeight; y++) { + for (x = 0; x < pixelWidth * 4; x += 4) { + union { + uint32_t v32; + uint8_t v8[4]; + } v; + + v.v32 = ((uint32_t) (pix[x + 3])) << 24; + v.v32 |= ((uint32_t) (pix[x])) << 16; + v.v32 |= ((uint32_t) (pix[x + 1])) << 8; + v.v32 |= ((uint32_t) (pix[x + 2])); + data[x] = v.v8[0]; + data[x + 1] = v.v8[1]; + data[x + 2] = v.v8[2]; + data[x + 3] = v.v8[3]; + } + pix += byteStride; + data += realStride; + } + + cairo_surface_mark_dirty(cs); g_ptr_array_add(i->images, cs); }