[gdk-pixbuf] tga: Wrap TGAColormap struct in its own API



commit edf6fb8d856574bc3bb3a703037f56533229267c
Author: Benjamin Otte <otte redhat com>
Date:   Sun Sep 20 00:22:42 2015 +0200

    tga: Wrap TGAColormap struct in its own API
    
    Instead of poking into it directly.

 gdk-pixbuf/io-tga.c |  124 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 82 insertions(+), 42 deletions(-)
---
diff --git a/gdk-pixbuf/io-tga.c b/gdk-pixbuf/io-tga.c
index e382459..70d1892 100644
--- a/gdk-pixbuf/io-tga.c
+++ b/gdk-pixbuf/io-tga.c
@@ -63,8 +63,8 @@ typedef struct _IOBuffer IOBuffer;
 typedef struct _TGAHeader TGAHeader;
 typedef struct _TGAFooter TGAFooter;
 
-typedef struct _TGAColormap TGAColormap;
 typedef struct _TGAColor TGAColor;
+typedef struct _TGAColormap TGAColormap;
 
 typedef struct _TGAContext TGAContext;
 
@@ -101,15 +101,15 @@ struct _TGAFooter {
        } sig;
 };
 
-struct _TGAColormap {
-       gint size;
-       TGAColor *cols;
-};
-
 struct _TGAColor {
        guchar r, g, b, a;
 };
 
+struct _TGAColormap {
+       guint n_colors;
+       TGAColor colors[1];
+};
+
 struct _TGAContext {
        TGAHeader *hdr;
        guint rowstride;
@@ -234,6 +234,51 @@ static void free_buffer(guchar *pixels, gpointer data)
        g_free(pixels);
 }
 
+static TGAColormap *
+colormap_new (guint n_colors)
+{
+  TGAColormap *cmap;
+
+  g_assert (n_colors <= G_MAXUINT16);
+
+  cmap = g_try_malloc0 (sizeof (TGAColormap) + (MAX (n_colors, 1) - 1) * sizeof (TGAColor));
+  if (cmap == NULL)
+    return NULL;
+
+  cmap->n_colors = n_colors;
+
+  return cmap;
+}
+
+static const TGAColor *
+colormap_get_color (TGAColormap *cmap,
+                    guint        id)
+{
+  static const TGAColor transparent_black = { 0, 0, 0, 0 };
+
+  if (id >= cmap->n_colors)
+    return &transparent_black;
+
+  return &cmap->colors[id];
+}
+
+static void
+colormap_set_color (TGAColormap    *cmap,
+                    guint           id,
+                    const TGAColor *color)
+{
+  if (id >= cmap->n_colors)
+    return;
+
+  cmap->colors[id] = *color;
+}
+
+static void
+colormap_free (TGAColormap *cmap)
+{
+  g_free (cmap);
+}
+
 static GdkPixbuf *get_contiguous_pixbuf (guint width, 
                                         guint height, 
                                         gboolean has_alpha)
@@ -364,11 +409,12 @@ static void parse_data_for_row_pseudocolor(TGAContext *ctx)
        guchar *p = ctx->pptr;
 
        for (; upper_bound; upper_bound--, s++) {
-               *p++ = ctx->cmap->cols[*s].r;
-               *p++ = ctx->cmap->cols[*s].g;
-               *p++ = ctx->cmap->cols[*s].b;
+                const TGAColor *color = colormap_get_color (ctx->cmap, *s);
+               *p++ = color->r;
+               *p++ = color->g;
+               *p++ = color->b;
                if (ctx->hdr->cmap_bpp == 32)
-                       *p++ = ctx->cmap->cols[*s].a;
+                       *p++ = color->a;
        }
 }
 
@@ -435,7 +481,7 @@ static gboolean parse_data_for_row(TGAContext *ctx, GError **err)
        return TRUE;
 }
 
-static void write_rle_data(TGAContext *ctx, TGAColor *color, guint *rle_count)
+static void write_rle_data(TGAContext *ctx, const TGAColor *color, guint *rle_count)
 {
        for (; *rle_count; (*rle_count)--) {
                g_memmove(ctx->pptr, (guchar *) color, ctx->pbuf->n_channels);
@@ -463,7 +509,7 @@ static guint parse_rle_data_pseudocolor(TGAContext *ctx)
                                return --n;
                        } else {
                                rle_num = (tag & 0x7f) + 1;
-                               write_rle_data(ctx, &ctx->cmap->cols[*s], &rle_num);
+                               write_rle_data(ctx, colormap_get_color (ctx->cmap, *s), &rle_num);
                                s++, n++;
                                if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
                                        ctx->done = TRUE;
@@ -476,14 +522,12 @@ static guint parse_rle_data_pseudocolor(TGAContext *ctx)
                                return --n;
                        } else {
                                for (; raw_num; raw_num--) {
-                                       *ctx->pptr++ =
-                                               ctx->cmap->cols[*s].r;
-                                       *ctx->pptr++ =
-                                               ctx->cmap->cols[*s].g;
-                                       *ctx->pptr++ =
-                                               ctx->cmap->cols[*s].b;
+                                        const TGAColor *color = colormap_get_color (ctx->cmap, *s);
+                                       *ctx->pptr++ = color->r;
+                                       *ctx->pptr++ = color->g;
+                                       *ctx->pptr++ = color->b;
                                        if (ctx->pbuf->n_channels == 4)
-                                               *ctx->pptr++ = ctx->cmap->cols[*s].a;
+                                               *ctx->pptr++ = color->a;
                                        s++, n++;
                                        ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
                                        if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
@@ -667,8 +711,9 @@ static gboolean parse_rle_data(TGAContext *ctx, GError **err)
 
 static gboolean try_colormap(TGAContext *ctx, GError **err)
 {
-       static guchar *p;
-       static guint n;
+        TGAColor color;
+       guchar *p;
+       guint i, n_colors;
 
        g_return_val_if_fail(ctx != NULL, FALSE);
 
@@ -679,41 +724,38 @@ static gboolean try_colormap(TGAContext *ctx, GError **err)
                        return FALSE;
         }
 
-       ctx->cmap = g_try_malloc(sizeof(TGAColormap));
+        n_colors = LE16(ctx->hdr->cmap_n_colors);
+        ctx->cmap = colormap_new (n_colors);
        if (!ctx->cmap) {
                g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                                    _("Cannot allocate colormap structure"));
-               return FALSE;
-       }
-       ctx->cmap->size = LE16(ctx->hdr->cmap_n_colors);
-       ctx->cmap->cols = g_try_malloc(sizeof(TGAColor) * ctx->cmap->size);
-       if (!ctx->cmap->cols) {
-               g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                                    _("Cannot allocate colormap entries"));
+                                    _("Cannot allocate colormap"));
                return FALSE;
        }
 
        p = ctx->in->data;
-       for (n = 0; n < ctx->cmap->size; n++) {
+        color.a = 255;
+
+       for (i = 0; i < n_colors; i++) {
                if ((ctx->hdr->cmap_bpp == 15) || (ctx->hdr->cmap_bpp == 16)) {
                        guint16 col = p[0] + (p[1] << 8);
-                       ctx->cmap->cols[n].b = (col >> 7) & 0xf8;
-                       ctx->cmap->cols[n].g = (col >> 2) & 0xf8;
-                       ctx->cmap->cols[n].r = col << 3;
+                       color.b = (col >> 7) & 0xf8;
+                       color.g = (col >> 2) & 0xf8;
+                       color.r = col << 3;
                        p += 2;
                }
                else if ((ctx->hdr->cmap_bpp == 24) || (ctx->hdr->cmap_bpp == 32)) {
-                       ctx->cmap->cols[n].b = *p++;
-                       ctx->cmap->cols[n].g = *p++;
-                       ctx->cmap->cols[n].r = *p++;
+                       color.b = *p++;
+                       color.g = *p++;
+                       color.r = *p++;
                        if (ctx->hdr->cmap_bpp == 32)
-                               ctx->cmap->cols[n].a = *p++;
+                               color.a = *p++;
                } else {
                        g_set_error_literal(err, GDK_PIXBUF_ERROR, 
                                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                             _("Unexpected bitdepth for colormap entries"));
                        return FALSE;
                }
+                colormap_set_color (ctx->cmap, i, &color);
        }
        ctx->in = io_buffer_free_segment(ctx->in, ctx->cmap_size, err);
        if (!ctx->in)
@@ -944,10 +986,8 @@ static gboolean gdk_pixbuf__tga_stop_load(gpointer data, GError **err)
                                       ctx->udata);
        }
        g_free (ctx->hdr);
-       if (ctx->cmap) {
-         g_free (ctx->cmap->cols);
-         g_free (ctx->cmap);
-       }
+       if (ctx->cmap)
+          colormap_free (ctx->cmap);
        if (ctx->pbuf)
                g_object_unref (ctx->pbuf);
        if (ctx->in && ctx->in->size)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]