Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/d0da09a7ca5a2b7878c0af4aab86efaf38d628ac
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/d0da09a7ca5a2b7878c0af4aab86efaf38d628ac
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/d0da09a7ca5a2b7878c0af4aab86efaf38d628ac

The branch, master has been updated
       via  d0da09a7ca5a2b7878c0af4aab86efaf38d628ac (commit)
       via  bbfc0ca353bb6a0b6a5ec50044c5c3f8bd714c12 (commit)
       via  d33af429113159b1a1d7cf62f5d8894a015c6efb (commit)
       via  41995c3999521ea4486326fba27460d0f17c8f68 (commit)
       via  fba7a349c073287418587b8892dfb9bd8b29490a (commit)
       via  694a3b4c989d9628a3dd5b7e1f3723d15f432891 (commit)
       via  b0e7de8bff424757a577625d96cd759e774a56e9 (commit)
       via  cde6a10ef43cc4f43562fe55997934e9a52d9fb8 (commit)
       via  c69bc8ba9ceeb5096a2312fb74176f49e8d3a5f8 (commit)
       via  05a0a6997eca876230e9230375ef8601c5cdcfa3 (commit)
       via  aeead57677cbeaeaef5b73c5b02e6b2144a2bae2 (commit)
       via  d00c049d0221c5b63a6a423d5adc7933ac1e758d (commit)
       via  1bbb499f88ef324a4526a74230851dd9a5325e19 (commit)
       via  df6ff85305a87e1b6e6fc6271c5ae3366577cedb (commit)
       via  052acc752cd31d907f134deebfeb584259e3f7ed (commit)
       via  7bf6a88c9c9ffe92602201b1073cb2daea73867f (commit)
       via  2f0fbbcaa0625fee09ee150f5d28512f19d6bedc (commit)
       via  c7dce05437d572d6417702c07221b856c88c9d7d (commit)
       via  60b12cd9fe2b543aca4359ff0ba3f27ad27ae6ce (commit)
       via  e7a355bf8dafc4bb0b0b6c9d85dcef4b21ae5fe0 (commit)
       via  27a89439a2d7b5e42a749c7750f193ad9dbce607 (commit)
       via  976f54bf48338a8b96ab6fc329bc7b00e9ef5e08 (commit)
       via  f27db5f80b074148aa9b8dd593dc2eefbc9e36ad (commit)
       via  e9d1a1fa9d698c0f6507f1b2ab719ce0fc5a0550 (commit)
       via  6011da798ff305ddee7ef36829f4c8c451cab600 (commit)
       via  725d1c99112c2882708e44930393225d1b534bf4 (commit)
      from  7f6a00ad2b9bacf42860a5074faa756c705683f1 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=d0da09a7ca5a2b7878c0af4aab86efaf38d628ac
commit d0da09a7ca5a2b7878c0af4aab86efaf38d628ac
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: JPEG: Decode to client bitmap format where possible.

diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 7d635f9..e07fb47 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -161,6 +161,94 @@ static void nsjpeg_error_exit(j_common_ptr cinfo)
 }
 
 /**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_cmyk(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       int width = cinfo->output_width * 4;
+
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+
+               for (int i = width - 4; 0 <= i; i -= 4) {
+                       /* Trivial inverse CMYK -> RGBA */
+                       const int c = scanlines[0][i + 0];
+                       const int m = scanlines[0][i + 1];
+                       const int y = scanlines[0][i + 2];
+                       const int k = scanlines[0][i + 3];
+
+                       const int ck = c * k;
+                       const int mk = m * k;
+                       const int yk = y * k;
+
+#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
+                       scanlines[0][i + bitmap_layout.r] = DIV255(ck);
+                       scanlines[0][i + bitmap_layout.g] = DIV255(mk);
+                       scanlines[0][i + bitmap_layout.b] = DIV255(yk);
+                       scanlines[0][i + bitmap_layout.a] = 0xff;
+#undef DIV255
+               }
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_rgb(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       int width = cinfo->output_width;
+
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+               /* Missmatch between configured libjpeg pixel format and
+                * NetSurf pixel format.  Convert to RGBA */
+               for (int i = width - 1; 0 <= i; i--) {
+                       int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED];
+                       int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN];
+                       int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE];
+                       scanlines[0][i * 4 + bitmap_layout.r] = r;
+                       scanlines[0][i * 4 + bitmap_layout.g] = g;
+                       scanlines[0][i * 4 + bitmap_layout.b] = b;
+                       scanlines[0][i * 4 + bitmap_layout.a] = 0xff;
+               }
+#endif
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_client_fmt(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
  * create a bitmap from jpeg content.
  */
 static struct bitmap *
@@ -171,8 +259,6 @@ jpeg_cache_convert(struct content *c)
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr jerr;
        jmp_buf setjmp_buffer;
-       unsigned int height;
-       unsigned int width;
        struct bitmap * volatile bitmap = NULL;
        uint8_t * volatile pixels = NULL;
        size_t rowstride;
@@ -217,21 +303,42 @@ jpeg_cache_convert(struct content *c)
 
        /* set output processing parameters */
        if (cinfo.jpeg_color_space == JCS_CMYK ||
-                       cinfo.jpeg_color_space == JCS_YCCK) {
+           cinfo.jpeg_color_space == JCS_YCCK) {
                cinfo.out_color_space = JCS_CMYK;
        } else {
+#ifdef JCS_ALPHA_EXTENSIONS
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_R8G8B8A8:
+                       cinfo.out_color_space = JCS_EXT_RGBA;
+                       break;
+               case BITMAP_LAYOUT_B8G8R8A8:
+                       cinfo.out_color_space = JCS_EXT_BGRA;
+                       break;
+               case BITMAP_LAYOUT_A8R8G8B8:
+                       cinfo.out_color_space = JCS_EXT_ARGB;
+                       break;
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       cinfo.out_color_space = JCS_EXT_ABGR;
+                       break;
+               default:
+                       NSLOG(netsurf, ERROR, "Unexpected bitmap format: %u",
+                                       bitmap_fmt.layout);
+                       jpeg_destroy_decompress(&cinfo);
+                       return NULL;
+               }
+#else
                cinfo.out_color_space = JCS_RGB;
+#endif
        }
        cinfo.dct_method = JDCT_ISLOW;
 
        /* commence the decompression, output parameters now valid */
        jpeg_start_decompress(&cinfo);
 
-       width = cinfo.output_width;
-       height = cinfo.output_height;
-
        /* create opaque bitmap (jpegs cannot be transparent) */
-       bitmap = guit->bitmap->create(width, height, BITMAP_OPAQUE);
+       bitmap = guit->bitmap->create(
+                       cinfo.output_width,
+                       cinfo.output_height, BITMAP_OPAQUE);
        if (bitmap == NULL) {
                /* empty bitmap could not be created */
                jpeg_destroy_decompress(&cinfo);
@@ -248,54 +355,21 @@ jpeg_cache_convert(struct content *c)
 
        /* Convert scanlines from jpeg into bitmap */
        rowstride = guit->bitmap->get_rowstride(bitmap);
-       do {
-               JSAMPROW scanlines[1];
-
-               scanlines[0] = (JSAMPROW) (pixels +
-                                          rowstride * cinfo.output_scanline);
-               jpeg_read_scanlines(&cinfo, scanlines, 1);
 
-               if (cinfo.out_color_space == JCS_CMYK) {
-                       int i;
-                       for (i = width - 1; 0 <= i; i--) {
-                               /* Trivial inverse CMYK -> RGBA */
-                               const int c = scanlines[0][i * 4 + 0];
-                               const int m = scanlines[0][i * 4 + 1];
-                               const int y = scanlines[0][i * 4 + 2];
-                               const int k = scanlines[0][i * 4 + 3];
+       switch (cinfo.out_color_space) {
+       case JCS_CMYK:
+               nsjpeg__decode_cmyk(&cinfo, pixels, rowstride);
+               break;
 
-                               const int ck = c * k;
-                               const int mk = m * k;
-                               const int yk = y * k;
+       case JCS_RGB:
+               nsjpeg__decode_rgb(&cinfo, pixels, rowstride);
+               break;
 
-#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
-                               scanlines[0][i * 4 + 0] = DIV255(ck);
-                               scanlines[0][i * 4 + 1] = DIV255(mk);
-                               scanlines[0][i * 4 + 2] = DIV255(yk);
-                               scanlines[0][i * 4 + 3] = 0xff;
-#undef DIV255
-                       }
-               } else {
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
-                       /* Missmatch between configured libjpeg pixel format and
-                        * NetSurf pixel format.  Convert to RGBA */
-                       int i;
-                       for (i = width - 1; 0 <= i; i--) {
-                               int r = scanlines[0][i * RGB_PIXELSIZE + 
RGB_RED];
-                               int g = scanlines[0][i * RGB_PIXELSIZE + 
RGB_GREEN];
-                               int b = scanlines[0][i * RGB_PIXELSIZE + 
RGB_BLUE];
-                               scanlines[0][i * 4 + 0] = r;
-                               scanlines[0][i * 4 + 1] = g;
-                               scanlines[0][i * 4 + 2] = b;
-                               scanlines[0][i * 4 + 3] = 0xff;
-                       }
-#endif
-               }
-       } while (cinfo.output_scanline != cinfo.output_height);
+       default:
+               nsjpeg__decode_client_fmt(&cinfo, pixels, rowstride);
+               break;
+       }
 
-       bitmap_format_to_client(bitmap, &(bitmap_fmt_t) {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
-       });
        guit->bitmap->modified(bitmap);
 
        jpeg_finish_decompress(&cinfo);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=bbfc0ca353bb6a0b6a5ec50044c5c3f8bd714c12
commit bbfc0ca353bb6a0b6a5ec50044c5c3f8bd714c12
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: JPEG: Warn if not using libjpeg-turbo.
    
    Replaces RISC OS warning with a more general and relevant one.

diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 940f239..7d635f9 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -50,13 +50,8 @@
  */
 #define MIN_JPEG_SIZE 20
 
-#ifdef riscos
-/* We prefer the library to be configured with these options to save
- * copying data during decoding. */
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
-#warning JPEG library not optimally configured. Decoding will be slower.
-#endif
-/* but we don't care if we're not on RISC OS */
+#ifndef LIBJPEG_TURBO_VERSION
+#warning Using libjpeg (libjpeg-turbo is recommended)
 #endif
 
 static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=d33af429113159b1a1d7cf62f5d8894a015c6efb
commit d33af429113159b1a1d7cf62f5d8894a015c6efb
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: WebP: Decode to client bitmap format where possible.

diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index b874859..4087f4c 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -98,6 +98,9 @@ webp_cache_convert(struct content *c)
        uint8_t *decoded;
        size_t rowstride;
        struct bitmap *bitmap = NULL;
+       bitmap_fmt_t webp_fmt = {
+               .layout = bitmap_fmt.layout,
+       };
 
        source_data = content__get_source_data(c, &source_size);
 
@@ -131,20 +134,33 @@ webp_cache_convert(struct content *c)
 
        rowstride = guit->bitmap->get_rowstride(bitmap);
 
-       decoded = WebPDecodeRGBAInto(source_data,
-                                    source_size,
-                                    pixels,
-                                    rowstride * webpfeatures.height,
-                                    rowstride);
+       switch (webp_fmt.layout) {
+       default:
+               /* WebP has no ABGR function, fall back to default. */
+               webp_fmt.layout = BITMAP_LAYOUT_R8G8B8A8;
+               /* Fall through. */
+       case BITMAP_LAYOUT_R8G8B8A8:
+               decoded = WebPDecodeRGBAInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+
+       case BITMAP_LAYOUT_B8G8R8A8:
+               decoded = WebPDecodeBGRAInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+
+       case BITMAP_LAYOUT_A8R8G8B8:
+               decoded = WebPDecodeARGBInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+       }
        if (decoded == NULL) {
                /* decode failed */
                guit->bitmap->destroy(bitmap);
                return NULL;
        }
 
-       bitmap_format_to_client(bitmap, &(bitmap_fmt_t) {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
-       });
+       bitmap_format_to_client(bitmap, &webp_fmt);
        guit->bitmap->modified(bitmap);
 
        return bitmap;


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=41995c3999521ea4486326fba27460d0f17c8f68
commit 41995c3999521ea4486326fba27460d0f17c8f68
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: WebP: Correct output buffer size for rowstride.

diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index 14f9532..b874859 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -134,7 +134,7 @@ webp_cache_convert(struct content *c)
        decoded = WebPDecodeRGBAInto(source_data,
                                     source_size,
                                     pixels,
-                                    webpfeatures.width * webpfeatures.height * 
4,
+                                    rowstride * webpfeatures.height,
                                     rowstride);
        if (decoded == NULL) {
                /* decode failed */


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=fba7a349c073287418587b8892dfb9bd8b29490a
commit fba7a349c073287418587b8892dfb9bd8b29490a
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: Sprite: Avoid multiple bitmap format conversions.

diff --git a/content/handlers/image/nssprite.c 
b/content/handlers/image/nssprite.c
index c9284f4..a98c48a 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -23,6 +23,8 @@
 
 #include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
+
 #include <librosprite.h>
 
 #include "utils/utils.h"
@@ -129,19 +131,7 @@ static bool nssprite_convert(struct content *c)
        }
        unsigned char *spritebuf = (unsigned char *)sprite->image;
 
-       /* reverse byte order of each word */
-       for (uint32_t y = 0; y < sprite->height; y++) {
-               for (uint32_t x = 0; x < sprite->width; x++) {
-                       int offset = 4 * (y * sprite->width + x);
-
-                       *imagebuf = (spritebuf[offset] << 24) |
-                                       (spritebuf[offset + 1] << 16) |
-                                       (spritebuf[offset + 2] << 8) |
-                                       (spritebuf[offset + 3]);
-
-                       imagebuf++;
-               }
-       }
+       memcpy(imagebuf, spritebuf, sprite->width * sprite->height * 4);
 
        c->width = sprite->width;
        c->height = sprite->height;
@@ -156,7 +146,7 @@ static bool nssprite_convert(struct content *c)
        }
 
        bitmap_format_to_client(nssprite->bitmap, &(bitmap_fmt_t) {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
+               .layout = BITMAP_LAYOUT_A8B8G8R8,
        });
        guit->bitmap->modified(nssprite->bitmap);
 


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=694a3b4c989d9628a3dd5b7e1f3723d15f432891
commit 694a3b4c989d9628a3dd5b7e1f3723d15f432891
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: RSVG: Just use bitmap to client for conversion.

diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 90e4c12..24fc1a4 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -129,41 +129,6 @@ static bool rsvg_process_data(struct content *c, const 
char *data,
        return true;
 }
 
-/** Convert Cairo's ARGB output to NetSurf's favoured ABGR format.  It converts
- * the data in-place. 
- *
- * \param pixels       Pixel data, in the form of ARGB.  This will
- *                     be overwritten with new data in the form of ABGR.
- * \param width                Width of the bitmap
- * \param height       Height of the bitmap
- * \param rowstride    Number of bytes to skip after each row (this
- *                     implementation requires this to be a multiple of 4.)
- */
-static inline void rsvg_argb_to_abgr(uint8_t *pixels, 
-               int width, int height, size_t rowstride)
-{
-       uint8_t *p = pixels;
-       int boff = 0, roff = 2;
-
-       if (endian_host_is_le() == false) {
-               boff = 1;
-               roff = 3;
-       }
-
-       for (int y = 0; y < height; y++) {
-               for (int x = 0; x < width; x++) {
-                       /* Swap R and B */
-                       const uint8_t r = p[4*x+roff];
-
-                       p[4*x+roff] = p[4*x+boff];
-
-                       p[4*x+boff] = r;
-               }
-
-               p += rowstride;
-       }
-}
-
 static bool rsvg_convert(struct content *c)
 {
        rsvg_content *d = (rsvg_content *) c;
@@ -214,12 +179,9 @@ static bool rsvg_convert(struct content *c)
        }
 
        rsvg_handle_render_cairo(d->rsvgh, d->ct);
-       rsvg_argb_to_abgr(guit->bitmap->get_buffer(d->bitmap),
-                               c->width, c->height,
-                               guit->bitmap->get_rowstride(d->bitmap));
 
        bitmap_format_to_client(d->bitmap, &(bitmap_fmt_t) {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
+               .layout = BITMAP_LAYOUT_ARGB8888,
        });
        guit->bitmap->modified(d->bitmap);
        content_set_ready(c);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=b0e7de8bff424757a577625d96cd759e774a56e9
commit b0e7de8bff424757a577625d96cd759e774a56e9
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: PNG: Decode to client bitmap format.

diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index e5d64c5..30ff3be 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -119,8 +119,37 @@ static void nspng_setup_transforms(png_structp png_ptr, 
png_infop info_ptr)
                png_set_gray_to_rgb(png_ptr);
        }
 
+       switch (bitmap_fmt.layout) {
+       case BITMAP_LAYOUT_B8G8R8A8: /* Fall through. */
+       case BITMAP_LAYOUT_A8B8G8R8:
+               png_set_bgr(png_ptr);
+               break;
+       default:
+               /* RGB is the default. */
+               break;
+       }
+
        if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
-               png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+                       break;
+
+               default:
+                       png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+                       break;
+               }
+       } else {
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       png_set_swap_alpha(png_ptr);
+                       break;
+               default:
+                       /* Alpha as final component is the default. */
+                       break;
+               }
        }
 
        /* gamma correction - we use 2.2 as our screen gamma
@@ -509,11 +538,7 @@ png_cache_convert_error:
        }
 
        if (bitmap != NULL) {
-               bitmap_fmt_t png_fmt = {
-                       .layout = BITMAP_LAYOUT_R8G8B8A8,
-               };
-
-               bitmap_format_to_client((struct bitmap *)bitmap, &png_fmt);
+               bitmap_format_to_client((struct bitmap *)bitmap, &bitmap_fmt);
                guit->bitmap->modified((struct bitmap *)bitmap);
        }
 
@@ -542,11 +567,7 @@ static bool nspng_convert(struct content *c)
 
        if (png_c->bitmap != NULL) {
                guit->bitmap->set_opaque(png_c->bitmap, 
guit->bitmap->test_opaque(png_c->bitmap));
-               bitmap_fmt_t png_fmt = {
-                       .layout = BITMAP_LAYOUT_R8G8B8A8,
-               };
-
-               bitmap_format_to_client(png_c->bitmap, &png_fmt);
+               bitmap_format_to_client(png_c->bitmap, &bitmap_fmt);
                guit->bitmap->modified(png_c->bitmap);
        }
 


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=cde6a10ef43cc4f43562fe55997934e9a52d9fb8
commit cde6a10ef43cc4f43562fe55997934e9a52d9fb8
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: GIF: Decode directly to client bitmap format.

diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index 03f6ca5..0dc7cb3 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -35,6 +35,8 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
+#include <nsutils/assert.h>
+
 #include <nsgif.h>
 
 #include "utils/log.h"
@@ -81,39 +83,6 @@ static inline nserror gif__nsgif_error_to_ns(nsgif_error 
gif_res)
 }
 
 /**
- * Get the image buffer from a bitmap
- *
- * Note that all pixels must be 4-byte aligned.
- *
- * \param bitmap The bitmap to get the buffer from.
- * \return The image buffer or NULL if there is none.
- */
-static unsigned char *nsgif__get_buffer(void *bitmap)
-{
-       bitmap_fmt_t gif_fmt = {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
-       };
-
-       bitmap_format_from_client(bitmap, &gif_fmt);
-       return guit->bitmap->get_buffer(bitmap);
-}
-
-/**
- * Marks a bitmap as modified.
- *
- * \param bitmap The bitmap set as modified.
- */
-static void nsgif__modified(void *bitmap)
-{
-       bitmap_fmt_t gif_fmt = {
-               .layout = BITMAP_LAYOUT_R8G8B8A8,
-       };
-
-       bitmap_format_to_client(bitmap, &gif_fmt);
-       guit->bitmap->modified(bitmap);
-}
-
-/**
  * Callback for libnsgif; forwards the call to bitmap_create()
  *
  * \param  width   width of image in pixels
@@ -125,20 +94,37 @@ static void *gif_bitmap_create(int width, int height)
        return guit->bitmap->create(width, height, BITMAP_NONE);
 }
 
+/**
+ * Convert client bitmap format to a LibNSGIF format specifier.
+ */
+static nsgif_bitmap_fmt_t nsgif__get_bitmap_format(void)
+{
+       ns_static_assert((int)BITMAP_LAYOUT_R8G8B8A8 == 
(int)NSGIF_BITMAP_FMT_R8G8B8A8);
+       ns_static_assert((int)BITMAP_LAYOUT_B8G8R8A8 == 
(int)NSGIF_BITMAP_FMT_B8G8R8A8);
+       ns_static_assert((int)BITMAP_LAYOUT_A8R8G8B8 == 
(int)NSGIF_BITMAP_FMT_A8R8G8B8);
+       ns_static_assert((int)BITMAP_LAYOUT_A8B8G8R8 == 
(int)NSGIF_BITMAP_FMT_A8B8G8R8);
+       ns_static_assert((int)BITMAP_LAYOUT_RGBA8888 == 
(int)NSGIF_BITMAP_FMT_RGBA8888);
+       ns_static_assert((int)BITMAP_LAYOUT_BGRA8888 == 
(int)NSGIF_BITMAP_FMT_BGRA8888);
+       ns_static_assert((int)BITMAP_LAYOUT_ARGB8888 == 
(int)NSGIF_BITMAP_FMT_ARGB8888);
+       ns_static_assert((int)BITMAP_LAYOUT_ABGR8888 == 
(int)NSGIF_BITMAP_FMT_ABGR8888);
+
+       return (nsgif_bitmap_fmt_t)bitmap_fmt.layout;
+}
+
 static nserror gif_create_gif_data(gif_content *c)
 {
        nsgif_error gif_res;
        const nsgif_bitmap_cb_vt gif_bitmap_callbacks = {
                .create = gif_bitmap_create,
                .destroy = guit->bitmap->destroy,
-               .get_buffer = nsgif__get_buffer,
+               .get_buffer = guit->bitmap->get_buffer,
                .set_opaque = guit->bitmap->set_opaque,
                .test_opaque = guit->bitmap->test_opaque,
-               .modified = nsgif__modified
+               .modified = guit->bitmap->modified,
        };
 
        gif_res = nsgif_create(&gif_bitmap_callbacks,
-                       NSGIF_BITMAP_FMT_R8G8B8A8, &c->gif);
+                       nsgif__get_bitmap_format(), &c->gif);
        if (gif_res != NSGIF_OK) {
                nserror err = gif__nsgif_error_to_ns(gif_res);
                content_broadcast_error(&c->base, err, NULL);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=c69bc8ba9ceeb5096a2312fb74176f49e8d3a5f8
commit c69bc8ba9ceeb5096a2312fb74176f49e8d3a5f8
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Bitmap: Colour layout converter doesn't need to be exposed.

diff --git a/desktop/bitmap.c b/desktop/bitmap.c
index 4977f7a..a780576 100644
--- a/desktop/bitmap.c
+++ b/desktop/bitmap.c
@@ -41,6 +41,52 @@ struct bitmap_colour_layout bitmap_layout = {
        .a = 3,
 };
 
+/**
+ * Get the colour layout for the given bitmap format.
+ *
+ * \param[in] fmt  Pixel format to get channel layout for,
+ * \return channel layout structure.
+ */
+static struct bitmap_colour_layout bitmap__get_colour_layout(
+               const bitmap_fmt_t *fmt)
+{
+       switch (fmt->layout) {
+       default:
+               /* Fall through. */
+       case BITMAP_LAYOUT_R8G8B8A8:
+               return (struct bitmap_colour_layout) {
+                       .r = 0,
+                       .g = 1,
+                       .b = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_B8G8R8A8:
+               return (struct bitmap_colour_layout) {
+                       .b = 0,
+                       .g = 1,
+                       .r = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_A8R8G8B8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .r = 1,
+                       .g = 2,
+                       .b = 3,
+               };
+
+       case BITMAP_LAYOUT_A8B8G8R8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .b = 1,
+                       .g = 2,
+                       .r = 3,
+               };
+       }
+}
+
 /* Exported function, documented in include/netsurf/bitmap.h */
 void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
 {
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
index 107089f..574f8fb 100644
--- a/desktop/bitmap.h
+++ b/desktop/bitmap.h
@@ -43,52 +43,6 @@ extern bitmap_fmt_t bitmap_fmt;
 extern struct bitmap_colour_layout bitmap_layout;
 
 /**
- * Get the colour layout for the given bitmap format.
- *
- * \param[in] fmt  Pixel format to get channel layout for,
- * \return channel layout structure.
- */
-static inline struct bitmap_colour_layout bitmap__get_colour_layout(
-               const bitmap_fmt_t *fmt)
-{
-       switch (fmt->layout) {
-       default:
-               /* Fall through. */
-       case BITMAP_LAYOUT_R8G8B8A8:
-               return (struct bitmap_colour_layout) {
-                       .r = 0,
-                       .g = 1,
-                       .b = 2,
-                       .a = 3,
-               };
-
-       case BITMAP_LAYOUT_B8G8R8A8:
-               return (struct bitmap_colour_layout) {
-                       .b = 0,
-                       .g = 1,
-                       .r = 2,
-                       .a = 3,
-               };
-
-       case BITMAP_LAYOUT_A8R8G8B8:
-               return (struct bitmap_colour_layout) {
-                       .a = 0,
-                       .r = 1,
-                       .g = 2,
-                       .b = 3,
-               };
-
-       case BITMAP_LAYOUT_A8B8G8R8:
-               return (struct bitmap_colour_layout) {
-                       .a = 0,
-                       .b = 1,
-                       .g = 2,
-                       .r = 3,
-               };
-       }
-}
-
-/**
  * Convert a bitmap pixel to a NetSurf colour (0xAARRGGBB).
  *
  * The bitmap must be in the client format.


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=05a0a6997eca876230e9230375ef8601c5cdcfa3
commit 05a0a6997eca876230e9230375ef8601c5cdcfa3
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Treeview: Use bitmap layout for bitmap generation.

diff --git a/desktop/treeview.c b/desktop/treeview.c
index 4f6a58b..a65a37e 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -41,6 +41,7 @@
 #include "content/hlcache.h"
 #include "css/utils.h"
 
+#include "desktop/bitmap.h"
 #include "desktop/knockout.h"
 #include "desktop/textarea.h"
 #include "desktop/treeview.h"
@@ -5091,67 +5092,67 @@ treeview_generate_triangle_bitmap(colour bg, colour fg, 
int size)
                if (y < size / 2) {
                        /* Top half */
                        for (x = 0; x < y * 2; x++) {
-                               pos[0] = red_from_colour(colour4);
-                               pos[1] = green_from_colour(colour4);
-                               pos[2] = blue_from_colour(colour4);
-                               pos[3] = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
                                pos += 4;
                        }
-                       pos[0] = red_from_colour(colour3);
-                       pos[1] = green_from_colour(colour3);
-                       pos[2] = blue_from_colour(colour3);
-                       pos[3] = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour3);
+                       pos[bitmap_layout.g] = green_from_colour(colour3);
+                       pos[bitmap_layout.b] = blue_from_colour(colour3);
+                       pos[bitmap_layout.a] = 0xff;
                        pos += 4;
-                       pos[0] = red_from_colour(colour1);
-                       pos[1] = green_from_colour(colour1);
-                       pos[2] = blue_from_colour(colour1);
-                       pos[3] = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour1);
+                       pos[bitmap_layout.g] = green_from_colour(colour1);
+                       pos[bitmap_layout.b] = blue_from_colour(colour1);
+                       pos[bitmap_layout.a] = 0xff;
                        pos += 4;
                        for (x = y * 2 + 2; x < size ; x++) {
-                               pos[0] = red_from_colour(colour0);
-                               pos[1] = green_from_colour(colour0);
-                               pos[2] = blue_from_colour(colour0);
-                               pos[3] = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour0);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour0);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour0);
+                               pos[bitmap_layout.a] = 0xff;
                                pos += 4;
                        }
                } else if ((y == size / 2) && (size & 0x1)) {
                        /* Middle row */
                        for (x = 0; x < size - 1; x++) {
-                               pos[0] = red_from_colour(colour4);
-                               pos[1] = green_from_colour(colour4);
-                               pos[2] = blue_from_colour(colour4);
-                               pos[3] = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
                                pos += 4;
                        }
-                       pos[0] = red_from_colour(colour2);
-                       pos[1] = green_from_colour(colour2);
-                       pos[2] = blue_from_colour(colour2);
-                       pos[3] = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour2);
+                       pos[bitmap_layout.g] = green_from_colour(colour2);
+                       pos[bitmap_layout.b] = blue_from_colour(colour2);
+                       pos[bitmap_layout.a] = 0xff;
                        pos += 4;
                } else {
                        /* Bottom half */
                        for (x = 0; x < (size - y - 1) * 2; x++) {
-                               pos[0] = red_from_colour(colour4);
-                               pos[1] = green_from_colour(colour4);
-                               pos[2] = blue_from_colour(colour4);
-                               pos[3] = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
                                pos += 4;
                        }
-                       pos[0] = red_from_colour(colour3);
-                       pos[1] = green_from_colour(colour3);
-                       pos[2] = blue_from_colour(colour3);
-                       pos[3] = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour3);
+                       pos[bitmap_layout.g] = green_from_colour(colour3);
+                       pos[bitmap_layout.b] = blue_from_colour(colour3);
+                       pos[bitmap_layout.a] = 0xff;
                        pos += 4;
-                       pos[0] = red_from_colour(colour1);
-                       pos[1] = green_from_colour(colour1);
-                       pos[2] = blue_from_colour(colour1);
-                       pos[3] = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour1);
+                       pos[bitmap_layout.g] = green_from_colour(colour1);
+                       pos[bitmap_layout.b] = blue_from_colour(colour1);
+                       pos[bitmap_layout.a] = 0xff;
                        pos += 4;
                        for (x = (size - y) * 2; x < size ; x++) {
-                               pos[0] = red_from_colour(colour0);
-                               pos[1] = green_from_colour(colour0);
-                               pos[2] = blue_from_colour(colour0);
-                               pos[3] = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour0);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour0);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour0);
+                               pos[bitmap_layout.a] = 0xff;
                                pos += 4;
                        }
                }


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=aeead57677cbeaeaef5b73c5b02e6b2144a2bae2
commit aeead57677cbeaeaef5b73c5b02e6b2144a2bae2
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Bitmap: Convert pixel_to_colour to layout-aware function.

diff --git a/desktop/bitmap.h b/desktop/bitmap.h
index 8756c50..107089f 100644
--- a/desktop/bitmap.h
+++ b/desktop/bitmap.h
@@ -25,11 +25,9 @@
 
 #include <nsutils/endian.h>
 
+#include "netsurf/types.h"
 #include "netsurf/bitmap.h"
 
-/** The client bitmap format. */
-extern bitmap_fmt_t bitmap_fmt;
-
 /** Pixel format: colour component order. */
 struct bitmap_colour_layout {
        uint8_t r; /**< Byte offset within pixel to red component. */
@@ -38,6 +36,12 @@ struct bitmap_colour_layout {
        uint8_t a; /**< Byte offset within pixel to alpha component. */
 };
 
+/** The client bitmap format. */
+extern bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+extern struct bitmap_colour_layout bitmap_layout;
+
 /**
  * Get the colour layout for the given bitmap format.
  *
@@ -84,9 +88,21 @@ static inline struct bitmap_colour_layout 
bitmap__get_colour_layout(
        }
 }
 
-/* get a bitmap pixel (image/bitmap.h) into a plot colour */
-#define bitmap_pixel_to_colour(b) \
-       b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
+/**
+ * Convert a bitmap pixel to a NetSurf colour (0xAARRGGBB).
+ *
+ * The bitmap must be in the client format.
+ *
+ * \param[in]  Pointer to a pixel in the bitmap's pixel data.
+ * \return The corresponding NetSurf colour.
+ */
+static inline colour bitmap_pixel_to_colour(const uint8_t *pixel)
+{
+       return (pixel[bitmap_layout.r] <<  0) |
+              (pixel[bitmap_layout.g] <<  8) |
+              (pixel[bitmap_layout.b] << 16) |
+              (pixel[bitmap_layout.a] << 24);
+}
 
 /**
  * Sanitise bitmap pixel component layout.


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=d00c049d0221c5b63a6a423d5adc7933ac1e758d
commit d00c049d0221c5b63a6a423d5adc7933ac1e758d
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Bitmap: Move bitmap pixel to colour macro to bitmap header.

diff --git a/content/handlers/image/image.c b/content/handlers/image/image.c
index 4eb366e..3107ee4 100644
--- a/content/handlers/image/image.c
+++ b/content/handlers/image/image.c
@@ -26,6 +26,7 @@
 #include "netsurf/bitmap.h"
 #include "netsurf/content.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/bmp.h"
 #include "image/gif.h"
@@ -124,7 +125,7 @@ bool image_bitmap_plot(struct bitmap *bitmap,
                if (height == 1) {
                        /* optimise 1x1 bitmap plot */
                        pixel = guit->bitmap->get_buffer(bitmap);
-                       fill_style.fill_colour = pixel_to_colour(pixel);
+                       fill_style.fill_colour = bitmap_pixel_to_colour(pixel);
 
                        if (guit->bitmap->get_opaque(bitmap) ||
                            ((fill_style.fill_colour & 0xff000000) == 
0xff000000)) {
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
index af7e904..8756c50 100644
--- a/desktop/bitmap.h
+++ b/desktop/bitmap.h
@@ -84,6 +84,10 @@ static inline struct bitmap_colour_layout 
bitmap__get_colour_layout(
        }
 }
 
+/* get a bitmap pixel (image/bitmap.h) into a plot colour */
+#define bitmap_pixel_to_colour(b) \
+       b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
+
 /**
  * Sanitise bitmap pixel component layout.
  *
diff --git a/include/netsurf/plot_style.h b/include/netsurf/plot_style.h
index bfc0805..875020c 100644
--- a/include/netsurf/plot_style.h
+++ b/include/netsurf/plot_style.h
@@ -201,10 +201,6 @@ typedef struct plot_font_style {
         (((((c1 & 0x00ff00) * (255 - p)) +                             \
            ((c0 & 0x00ff00) * (      p))   ) >> 8) & 0x00ff00))
 
-/* get a bitmap pixel (image/bitmap.h) into a plot colour */
-#define pixel_to_colour(b)                                             \
-       b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
-
 /* Get the red channel from a colour */
 #define red_from_colour(c)                                             \
        ((c      ) & 0xff)


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=1bbb499f88ef324a4526a74230851dd9a5325e19
commit 1bbb499f88ef324a4526a74230851dd9a5325e19
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: WebP: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index 59667a8..14f9532 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -38,6 +38,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 
@@ -141,6 +142,9 @@ webp_cache_convert(struct content *c)
                return NULL;
        }
 
+       bitmap_format_to_client(bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       });
        guit->bitmap->modified(bitmap);
 
        return bitmap;


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=df6ff85305a87e1b6e6fc6271c5ae3366577cedb
commit df6ff85305a87e1b6e6fc6271c5ae3366577cedb
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: RSVG: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 4617998..90e4c12 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -51,6 +51,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/rsvg.h"
 
@@ -217,6 +218,9 @@ static bool rsvg_convert(struct content *c)
                                c->width, c->height,
                                guit->bitmap->get_rowstride(d->bitmap));
 
+       bitmap_format_to_client(d->bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       });
        guit->bitmap->modified(d->bitmap);
        content_set_ready(c);
        content_set_done(c);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=052acc752cd31d907f134deebfeb584259e3f7ed
commit 052acc752cd31d907f134deebfeb584259e3f7ed
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: PNG: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index d4c2ae0..e5d64c5 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -32,6 +32,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 #include "image/png.h"
@@ -508,6 +509,11 @@ png_cache_convert_error:
        }
 
        if (bitmap != NULL) {
+               bitmap_fmt_t png_fmt = {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               };
+
+               bitmap_format_to_client((struct bitmap *)bitmap, &png_fmt);
                guit->bitmap->modified((struct bitmap *)bitmap);
        }
 
@@ -536,6 +542,11 @@ static bool nspng_convert(struct content *c)
 
        if (png_c->bitmap != NULL) {
                guit->bitmap->set_opaque(png_c->bitmap, 
guit->bitmap->test_opaque(png_c->bitmap));
+               bitmap_fmt_t png_fmt = {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               };
+
+               bitmap_format_to_client(png_c->bitmap, &png_fmt);
                guit->bitmap->modified(png_c->bitmap);
        }
 


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=7bf6a88c9c9ffe92602201b1073cb2daea73867f
commit 7bf6a88c9c9ffe92602201b1073cb2daea73867f
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: Sprite: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/nssprite.c 
b/content/handlers/image/nssprite.c
index a6c2909..c9284f4 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -35,6 +35,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/nssprite.h"
 
@@ -154,6 +155,9 @@ static bool nssprite_convert(struct content *c)
                free(title);
        }
 
+       bitmap_format_to_client(nssprite->bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       });
        guit->bitmap->modified(nssprite->bitmap);
 
        content_set_ready(c);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=2f0fbbcaa0625fee09ee150f5d28512f19d6bedc
commit 2f0fbbcaa0625fee09ee150f5d28512f19d6bedc
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: JPEG: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 9daf06b..940f239 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -37,6 +37,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 
@@ -296,6 +297,10 @@ jpeg_cache_convert(struct content *c)
 #endif
                }
        } while (cinfo.output_scanline != cinfo.output_height);
+
+       bitmap_format_to_client(bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       });
        guit->bitmap->modified(bitmap);
 
        jpeg_finish_decompress(&cinfo);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=c7dce05437d572d6417702c07221b856c88c9d7d
commit c7dce05437d572d6417702c07221b856c88c9d7d
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: ICO: Abstract image decode into helper.

diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index 6f3e67e..871da41 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -173,6 +173,23 @@ static bool nsico_convert(struct content *c)
        return true;
 }
 
+static bool nsico__decode(struct bmp_image *ico)
+{
+       if (ico->decoded == false) {
+               NSLOG(netsurf, DEBUG, "Decoding ICO %p", ico);
+               if (bmp_decode(ico) != BMP_OK) {
+                       return false;
+               }
+
+               bitmap_format_to_client(ico->bitmap, &(bitmap_fmt_t) {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               });
+               guit->bitmap->modified(ico->bitmap);
+
+       }
+
+       return true;
+}
 
 static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
                const struct rect *clip, const struct redraw_context *ctx)
@@ -189,17 +206,8 @@ static bool nsico_redraw(struct content *c, struct 
content_redraw_data *data,
        }
 
        /* ensure its decided */
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return false;
-               } else {
-                       NSLOG(netsurf, INFO, "Decoding bitmap");
-                       bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
-                               .layout = BITMAP_LAYOUT_R8G8B8A8,
-                       });
-                       guit->bitmap->modified(bmp->bitmap);
-               }
-
+       if (!nsico__decode(bmp)) {
+               return false;
        }
 
        return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
@@ -263,15 +271,8 @@ static void *nsico_get_internal(const struct content *c, 
void *context)
                return NULL;
        }
 
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return NULL;
-               } else {
-                       bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
-                               .layout = BITMAP_LAYOUT_R8G8B8A8,
-                       });
-                       guit->bitmap->modified(bmp->bitmap);
-               }
+       if (!nsico__decode(bmp)) {
+               return NULL;
        }
 
        return bmp->bitmap;
@@ -298,15 +299,8 @@ static bool nsico_is_opaque(struct content *c)
                return false;
        }
 
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return false;
-               }
-
-               bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
-                       .layout = BITMAP_LAYOUT_R8G8B8A8,
-               });
-               guit->bitmap->modified(bmp->bitmap);
+       if (!nsico__decode(bmp)) {
+               return false;
        }
 
        return guit->bitmap->get_opaque(bmp->bitmap);


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=60b12cd9fe2b543aca4359ff0ba3f27ad27ae6ce
commit 60b12cd9fe2b543aca4359ff0ba3f27ad27ae6ce
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: ICO: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index ac617f7..6f3e67e 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -34,6 +34,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image.h"
 #include "image/ico.h"
@@ -193,6 +194,9 @@ static bool nsico_redraw(struct content *c, struct 
content_redraw_data *data,
                        return false;
                } else {
                        NSLOG(netsurf, INFO, "Decoding bitmap");
+                       bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+                               .layout = BITMAP_LAYOUT_R8G8B8A8,
+                       });
                        guit->bitmap->modified(bmp->bitmap);
                }
 
@@ -263,6 +267,9 @@ static void *nsico_get_internal(const struct content *c, 
void *context)
                if (bmp_decode(bmp) != BMP_OK) {
                        return NULL;
                } else {
+                       bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+                               .layout = BITMAP_LAYOUT_R8G8B8A8,
+                       });
                        guit->bitmap->modified(bmp->bitmap);
                }
        }
@@ -296,6 +303,9 @@ static bool nsico_is_opaque(struct content *c)
                        return false;
                }
 
+               bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               });
                guit->bitmap->modified(bmp->bitmap);
        }
 


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=e7a355bf8dafc4bb0b0b6c9d85dcef4b21ae5fe0
commit e7a355bf8dafc4bb0b0b6c9d85dcef4b21ae5fe0
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: GIF: Call bitmap format conversion before/after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index f06805d..03f6ca5 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -49,6 +49,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image.h"
 #include "image/gif.h"
@@ -80,6 +81,39 @@ static inline nserror gif__nsgif_error_to_ns(nsgif_error 
gif_res)
 }
 
 /**
+ * Get the image buffer from a bitmap
+ *
+ * Note that all pixels must be 4-byte aligned.
+ *
+ * \param bitmap The bitmap to get the buffer from.
+ * \return The image buffer or NULL if there is none.
+ */
+static unsigned char *nsgif__get_buffer(void *bitmap)
+{
+       bitmap_fmt_t gif_fmt = {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       };
+
+       bitmap_format_from_client(bitmap, &gif_fmt);
+       return guit->bitmap->get_buffer(bitmap);
+}
+
+/**
+ * Marks a bitmap as modified.
+ *
+ * \param bitmap The bitmap set as modified.
+ */
+static void nsgif__modified(void *bitmap)
+{
+       bitmap_fmt_t gif_fmt = {
+               .layout = BITMAP_LAYOUT_R8G8B8A8,
+       };
+
+       bitmap_format_to_client(bitmap, &gif_fmt);
+       guit->bitmap->modified(bitmap);
+}
+
+/**
  * Callback for libnsgif; forwards the call to bitmap_create()
  *
  * \param  width   width of image in pixels
@@ -97,10 +131,10 @@ static nserror gif_create_gif_data(gif_content *c)
        const nsgif_bitmap_cb_vt gif_bitmap_callbacks = {
                .create = gif_bitmap_create,
                .destroy = guit->bitmap->destroy,
-               .get_buffer = guit->bitmap->get_buffer,
+               .get_buffer = nsgif__get_buffer,
                .set_opaque = guit->bitmap->set_opaque,
                .test_opaque = guit->bitmap->test_opaque,
-               .modified = guit->bitmap->modified
+               .modified = nsgif__modified
        };
 
        gif_res = nsgif_create(&gif_bitmap_callbacks,


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=27a89439a2d7b5e42a749c7750f193ad9dbce607
commit 27a89439a2d7b5e42a749c7750f193ad9dbce607
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Image: BMP: Call bitmap format conversion after decode.
    
    Currently a no-op, because we decode to the default format
    and no front end requests anything but the default format.

diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index 5f9708b..3fec2cc 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -35,6 +35,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/bmp.h"
 
@@ -189,6 +190,9 @@ static bool nsbmp_redraw(struct content *c, struct 
content_redraw_data *data,
                        return false;
                }
 
+               bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               });
                guit->bitmap->modified(bmp->bitmap);
        }
 


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=976f54bf48338a8b96ab6fc329bc7b00e9ef5e08
commit 976f54bf48338a8b96ab6fc329bc7b00e9ef5e08
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Bitmap: Initialise layout for default pixel format.

diff --git a/desktop/bitmap.c b/desktop/bitmap.c
index 3e8529a..4977f7a 100644
--- a/desktop/bitmap.c
+++ b/desktop/bitmap.c
@@ -34,7 +34,12 @@
 bitmap_fmt_t bitmap_fmt;
 
 /** The client bitmap colour channel layout. */
-struct bitmap_colour_layout bitmap_layout;
+struct bitmap_colour_layout bitmap_layout = {
+       .r = 0,
+       .g = 1,
+       .b = 2,
+       .a = 3,
+};
 
 /* Exported function, documented in include/netsurf/bitmap.h */
 void bitmap_set_format(const bitmap_fmt_t *bitmap_format)


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=f27db5f80b074148aa9b8dd593dc2eefbc9e36ad
commit f27db5f80b074148aa9b8dd593dc2eefbc9e36ad
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Bitmap: Add format conversion routines.

diff --git a/desktop/bitmap.c b/desktop/bitmap.c
index 48065d0..3e8529a 100644
--- a/desktop/bitmap.c
+++ b/desktop/bitmap.c
@@ -44,3 +44,36 @@ void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
        bitmap_fmt.layout = bitmap_sanitise_bitmap_layout(bitmap_fmt.layout);
        bitmap_layout = bitmap__get_colour_layout(&bitmap_fmt);
 }
+
+/* Exported function, documented in desktop/bitmap.h */
+void bitmap_format_convert(void *bitmap,
+               const bitmap_fmt_t *fmt_from,
+               const bitmap_fmt_t *fmt_to)
+{
+       int width = guit->bitmap->get_width(bitmap);
+       int height = guit->bitmap->get_height(bitmap);
+       uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
+       size_t rowstride = guit->bitmap->get_rowstride(bitmap);
+       struct bitmap_colour_layout to = bitmap__get_colour_layout(fmt_to);
+       struct bitmap_colour_layout from = bitmap__get_colour_layout(fmt_from);
+
+       NSLOG(netsurf, DEEPDEBUG, "Bitmap format conversion (%u --> %u)",
+                       fmt_from->layout, fmt_to->layout);
+
+       for (int y = 0; y < height; y++) {
+               uint8_t *row = buffer;
+
+               for (int x = 0; x < width; x++) {
+                       const uint32_t px = *((uint32_t *)(void *) row);
+
+                       row[to.r] = ((const uint8_t *) &px)[from.r];
+                       row[to.g] = ((const uint8_t *) &px)[from.g];
+                       row[to.b] = ((const uint8_t *) &px)[from.b];
+                       row[to.a] = ((const uint8_t *) &px)[from.a];
+
+                       row += sizeof(uint32_t);
+               }
+
+               buffer += rowstride;
+       }
+}
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
index 4909289..af7e904 100644
--- a/desktop/bitmap.h
+++ b/desktop/bitmap.h
@@ -121,4 +121,53 @@ static inline enum bitmap_layout 
bitmap_sanitise_bitmap_layout(
        return layout;
 }
 
+/**
+ * Convert bitmap from one format to another.
+ *
+ * Note that both formats should be sanitised.
+ *
+ * \param[in]  bitmap  The bitmap to convert.
+ * \param[in]  from    The current bitmap format specifier.
+ * \param[in]  to      The bitmap format to convert to.
+ */
+void bitmap_format_convert(void *bitmap,
+               const bitmap_fmt_t *from,
+               const bitmap_fmt_t *to);
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in]  bitmap       The bitmap to convert.
+ * \param[in]  current_fmt  The current bitmap format specifier.
+ */
+static inline void bitmap_format_to_client(
+               void *bitmap,
+               const bitmap_fmt_t *current_fmt)
+{
+       bitmap_fmt_t from = *current_fmt;
+
+       from.layout = bitmap_sanitise_bitmap_layout(from.layout);
+       if (from.layout != bitmap_fmt.layout) {
+               bitmap_format_convert(bitmap, &from, &bitmap_fmt);
+       }
+}
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in]  bitmap      The bitmap to convert.
+ * \param[in]  target_fmt  The target bitmap format specifier.
+ */
+static inline void bitmap_format_from_client(
+               void *bitmap,
+               const bitmap_fmt_t *target_fmt)
+{
+       bitmap_fmt_t to = *target_fmt;
+
+       to.layout = bitmap_sanitise_bitmap_layout(to.layout);
+       if (to.layout != bitmap_fmt.layout) {
+               bitmap_format_convert(bitmap, &bitmap_fmt, &to);
+       }
+}
+
 #endif


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=e9d1a1fa9d698c0f6507f1b2ab719ce0fc5a0550
commit e9d1a1fa9d698c0f6507f1b2ab719ce0fc5a0550
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Include: Bitmap: Add API for setting core bitmap format.

diff --git a/desktop/Makefile b/desktop/Makefile
index 63749a6..5e19027 100644
--- a/desktop/Makefile
+++ b/desktop/Makefile
@@ -12,7 +12,7 @@ desktop/version.c: testament $(OBJROOT)/testament.h
 
 # S_BROWSER are sources related to full browsers but are common
 # between RISC OS, GTK, BeOS and AmigaOS builds
-S_BROWSER := browser.c browser_window.c browser_history.c \
+S_BROWSER := bitmap.c browser.c browser_window.c browser_history.c \
        download.c frames.c netsurf.c cw_helper.c \
        save_complete.c save_text.c selection.c textinput.c gui_factory.c \
        save_pdf.c font_haru.c
diff --git a/desktop/bitmap.c b/desktop/bitmap.c
new file mode 100644
index 0000000..48065d0
--- /dev/null
+++ b/desktop/bitmap.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 Michael Drake <t...@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "utils/log.h"
+#include "utils/errors.h"
+
+#include "desktop/bitmap.h"
+#include "desktop/gui_internal.h"
+
+/** The client bitmap format. */
+bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+struct bitmap_colour_layout bitmap_layout;
+
+/* Exported function, documented in include/netsurf/bitmap.h */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
+{
+       bitmap_fmt = *bitmap_format;
+
+       bitmap_fmt.layout = bitmap_sanitise_bitmap_layout(bitmap_fmt.layout);
+       bitmap_layout = bitmap__get_colour_layout(&bitmap_fmt);
+}
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
new file mode 100644
index 0000000..4909289
--- /dev/null
+++ b/desktop/bitmap.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2022 Michael Drake <t...@nesturf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#ifndef _NETSURF_DESKTOP_BITMAP_H_
+#define _NETSURF_DESKTOP_BITMAP_H_
+
+#include <nsutils/endian.h>
+
+#include "netsurf/bitmap.h"
+
+/** The client bitmap format. */
+extern bitmap_fmt_t bitmap_fmt;
+
+/** Pixel format: colour component order. */
+struct bitmap_colour_layout {
+       uint8_t r; /**< Byte offset within pixel to red component. */
+       uint8_t g; /**< Byte offset within pixel to green component. */
+       uint8_t b; /**< Byte offset within pixel to blue component. */
+       uint8_t a; /**< Byte offset within pixel to alpha component. */
+};
+
+/**
+ * Get the colour layout for the given bitmap format.
+ *
+ * \param[in] fmt  Pixel format to get channel layout for,
+ * \return channel layout structure.
+ */
+static inline struct bitmap_colour_layout bitmap__get_colour_layout(
+               const bitmap_fmt_t *fmt)
+{
+       switch (fmt->layout) {
+       default:
+               /* Fall through. */
+       case BITMAP_LAYOUT_R8G8B8A8:
+               return (struct bitmap_colour_layout) {
+                       .r = 0,
+                       .g = 1,
+                       .b = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_B8G8R8A8:
+               return (struct bitmap_colour_layout) {
+                       .b = 0,
+                       .g = 1,
+                       .r = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_A8R8G8B8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .r = 1,
+                       .g = 2,
+                       .b = 3,
+               };
+
+       case BITMAP_LAYOUT_A8B8G8R8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .b = 1,
+                       .g = 2,
+                       .r = 3,
+               };
+       }
+}
+
+/**
+ * Sanitise bitmap pixel component layout.
+ *
+ * Map endian-dependant layouts to byte-wise layout for the host.
+ *
+ * \param[in]  layout  Layout to convert.
+ * \return sanitised layout.
+ */
+static inline enum bitmap_layout bitmap_sanitise_bitmap_layout(
+               enum bitmap_layout layout)
+{
+       bool le = endian_host_is_le();
+
+       switch (layout) {
+       case BITMAP_LAYOUT_RGBA8888:
+               layout = (le) ? BITMAP_LAYOUT_A8B8G8R8
+                             : BITMAP_LAYOUT_R8G8B8A8;
+               break;
+       case BITMAP_LAYOUT_BGRA8888:
+               layout = (le) ? BITMAP_LAYOUT_A8R8G8B8
+                             : BITMAP_LAYOUT_B8G8R8A8;
+               break;
+       case BITMAP_LAYOUT_ARGB8888:
+               layout = (le) ? BITMAP_LAYOUT_B8G8R8A8
+                             : BITMAP_LAYOUT_A8R8G8B8;
+               break;
+       case BITMAP_LAYOUT_ABGR8888:
+               layout = (le) ? BITMAP_LAYOUT_R8G8B8A8
+                             : BITMAP_LAYOUT_A8B8G8R8;
+               break;
+       default:
+               break;
+       }
+
+       return layout;
+}
+
+#endif
diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index a5be75d..da1c284 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -61,11 +61,78 @@ enum gui_bitmap_flags {
        BITMAP_CLEAR  = (1 << 1), /**< memory should be wiped to 0 */
 };
 
+/**
+ * NetSurf bitmap pixel layout.
+ *
+ * All pixels are 32 bits per pixel (bpp). The different layouts allow control
+ * over the ordering of colour channels. All colour channels are 8 bits wide.
+ */
+enum bitmap_layout {
+       /** Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA. */
+       BITMAP_LAYOUT_R8G8B8A8,
+
+       /** Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA. */
+       BITMAP_LAYOUT_B8G8R8A8,
+
+       /** Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB. */
+       BITMAP_LAYOUT_A8R8G8B8,
+
+       /** Bite-wise ABGR: Byte order: 0xAA, 0xBB, 0xGG, 0xRR. */
+       BITMAP_LAYOUT_A8B8G8R8,
+
+       /**
+        * 32-bit RGBA (0xRRGGBBAA).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+        */
+       BITMAP_LAYOUT_RGBA8888,
+
+       /**
+        * 32-bit BGRA (0xBBGGRRAA).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+        */
+       BITMAP_LAYOUT_BGRA8888,
+
+       /**
+        * 32-bit ARGB (0xAARRGGBB).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+        */
+       BITMAP_LAYOUT_ARGB8888,
+
+       /**
+        * 32-bit BGRA (0xAABBGGRR).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+        */
+       BITMAP_LAYOUT_ABGR8888,
+};
+
+/** Bitmap format specifier. */
+typedef struct bitmap_fmt {
+       enum bitmap_layout layout; /** Colour component layout. */
+} bitmap_fmt_t;
+
 struct content;
 struct bitmap;
 struct hlcache_handle;
 
 /**
+ * Set client bitmap format.
+ *
+ * Set this to ensure that the bitmaps decoded by the core are in the
+ * correct format for the front end.
+ *
+ * \param[in]  bitmap_format  The bitmap format specification to set.
+ */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format);
+
+/**
  * Bitmap operations.
  */
 struct gui_bitmap_table {


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=6011da798ff305ddee7ef36829f4c8c451cab600
commit 6011da798ff305ddee7ef36829f4c8c451cab600
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Include: Bitmap: Document bitmap pixel alignment requirement.

diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index dfd1188..a5be75d 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -115,6 +115,8 @@ struct gui_bitmap_table {
        /**
         * Get the image buffer from a bitmap
         *
+        * Note that all pixels must be 4-byte aligned.
+        *
         * \param bitmap The bitmap to get the buffer from.
         * \return The image buffer or NULL if there is none.
         */


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=725d1c99112c2882708e44930393225d1b534bf4
commit 725d1c99112c2882708e44930393225d1b534bf4
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    Treeview: Change bitmap generation to per-pixel channel indexing.
    
    This will be needed when the core bitmap layout is client controlled.

diff --git a/desktop/treeview.c b/desktop/treeview.c
index d49be0f..4f6a58b 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -5091,58 +5091,68 @@ treeview_generate_triangle_bitmap(colour bg, colour fg, 
int size)
                if (y < size / 2) {
                        /* Top half */
                        for (x = 0; x < y * 2; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[0] = red_from_colour(colour4);
+                               pos[1] = green_from_colour(colour4);
+                               pos[2] = blue_from_colour(colour4);
+                               pos[3] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour3);
-                       *(pos++) = green_from_colour(colour3);
-                       *(pos++) = blue_from_colour(colour3);
-                       *(pos++) = 0xff;
-                       *(pos++) = red_from_colour(colour1);
-                       *(pos++) = green_from_colour(colour1);
-                       *(pos++) = blue_from_colour(colour1);
-                       *(pos++) = 0xff;
+                       pos[0] = red_from_colour(colour3);
+                       pos[1] = green_from_colour(colour3);
+                       pos[2] = blue_from_colour(colour3);
+                       pos[3] = 0xff;
+                       pos += 4;
+                       pos[0] = red_from_colour(colour1);
+                       pos[1] = green_from_colour(colour1);
+                       pos[2] = blue_from_colour(colour1);
+                       pos[3] = 0xff;
+                       pos += 4;
                        for (x = y * 2 + 2; x < size ; x++) {
-                               *(pos++) = red_from_colour(colour0);
-                               *(pos++) = green_from_colour(colour0);
-                               *(pos++) = blue_from_colour(colour0);
-                               *(pos++) = 0xff;
+                               pos[0] = red_from_colour(colour0);
+                               pos[1] = green_from_colour(colour0);
+                               pos[2] = blue_from_colour(colour0);
+                               pos[3] = 0xff;
+                               pos += 4;
                        }
                } else if ((y == size / 2) && (size & 0x1)) {
                        /* Middle row */
                        for (x = 0; x < size - 1; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[0] = red_from_colour(colour4);
+                               pos[1] = green_from_colour(colour4);
+                               pos[2] = blue_from_colour(colour4);
+                               pos[3] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour2);
-                       *(pos++) = green_from_colour(colour2);
-                       *(pos++) = blue_from_colour(colour2);
-                       *(pos++) = 0xff;
+                       pos[0] = red_from_colour(colour2);
+                       pos[1] = green_from_colour(colour2);
+                       pos[2] = blue_from_colour(colour2);
+                       pos[3] = 0xff;
+                       pos += 4;
                } else {
                        /* Bottom half */
                        for (x = 0; x < (size - y - 1) * 2; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[0] = red_from_colour(colour4);
+                               pos[1] = green_from_colour(colour4);
+                               pos[2] = blue_from_colour(colour4);
+                               pos[3] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour3);
-                       *(pos++) = green_from_colour(colour3);
-                       *(pos++) = blue_from_colour(colour3);
-                       *(pos++) = 0xff;
-                       *(pos++) = red_from_colour(colour1);
-                       *(pos++) = green_from_colour(colour1);
-                       *(pos++) = blue_from_colour(colour1);
-                       *(pos++) = 0xff;
+                       pos[0] = red_from_colour(colour3);
+                       pos[1] = green_from_colour(colour3);
+                       pos[2] = blue_from_colour(colour3);
+                       pos[3] = 0xff;
+                       pos += 4;
+                       pos[0] = red_from_colour(colour1);
+                       pos[1] = green_from_colour(colour1);
+                       pos[2] = blue_from_colour(colour1);
+                       pos[3] = 0xff;
+                       pos += 4;
                        for (x = (size - y) * 2; x < size ; x++) {
-                               *(pos++) = red_from_colour(colour0);
-                               *(pos++) = green_from_colour(colour0);
-                               *(pos++) = blue_from_colour(colour0);
-                               *(pos++) = 0xff;
+                               pos[0] = red_from_colour(colour0);
+                               pos[1] = green_from_colour(colour0);
+                               pos[2] = blue_from_colour(colour0);
+                               pos[3] = 0xff;
+                               pos += 4;
                        }
                }
 


-----------------------------------------------------------------------

Summary of changes:
 content/handlers/image/bmp.c      |    4 +
 content/handlers/image/gif.c      |   24 ++++-
 content/handlers/image/ico.c      |   44 +++++----
 content/handlers/image/image.c    |    3 +-
 content/handlers/image/jpeg.c     |  182 ++++++++++++++++++++++++++-----------
 content/handlers/image/nssprite.c |   20 ++--
 content/handlers/image/png.c      |   34 ++++++-
 content/handlers/image/rsvg.c     |   42 +--------
 content/handlers/image/webp.c     |   30 +++++-
 desktop/Makefile                  |    2 +-
 desktop/bitmap.c                  |  130 ++++++++++++++++++++++++++
 desktop/bitmap.h                  |  147 ++++++++++++++++++++++++++++++
 desktop/treeview.c                |   91 +++++++++++--------
 include/netsurf/bitmap.h          |   69 ++++++++++++++
 include/netsurf/plot_style.h      |    4 -
 15 files changed, 647 insertions(+), 179 deletions(-)
 create mode 100644 desktop/bitmap.c
 create mode 100644 desktop/bitmap.h

diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c
index 5f9708b..3fec2cc 100644
--- a/content/handlers/image/bmp.c
+++ b/content/handlers/image/bmp.c
@@ -35,6 +35,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/bmp.h"
 
@@ -189,6 +190,9 @@ static bool nsbmp_redraw(struct content *c, struct 
content_redraw_data *data,
                        return false;
                }
 
+               bitmap_format_to_client(bmp->bitmap, &(bitmap_fmt_t) {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               });
                guit->bitmap->modified(bmp->bitmap);
        }
 
diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index f06805d..0dc7cb3 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -35,6 +35,8 @@
 #include <stdbool.h>
 #include <stdlib.h>
 
+#include <nsutils/assert.h>
+
 #include <nsgif.h>
 
 #include "utils/log.h"
@@ -49,6 +51,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image.h"
 #include "image/gif.h"
@@ -91,6 +94,23 @@ static void *gif_bitmap_create(int width, int height)
        return guit->bitmap->create(width, height, BITMAP_NONE);
 }
 
+/**
+ * Convert client bitmap format to a LibNSGIF format specifier.
+ */
+static nsgif_bitmap_fmt_t nsgif__get_bitmap_format(void)
+{
+       ns_static_assert((int)BITMAP_LAYOUT_R8G8B8A8 == 
(int)NSGIF_BITMAP_FMT_R8G8B8A8);
+       ns_static_assert((int)BITMAP_LAYOUT_B8G8R8A8 == 
(int)NSGIF_BITMAP_FMT_B8G8R8A8);
+       ns_static_assert((int)BITMAP_LAYOUT_A8R8G8B8 == 
(int)NSGIF_BITMAP_FMT_A8R8G8B8);
+       ns_static_assert((int)BITMAP_LAYOUT_A8B8G8R8 == 
(int)NSGIF_BITMAP_FMT_A8B8G8R8);
+       ns_static_assert((int)BITMAP_LAYOUT_RGBA8888 == 
(int)NSGIF_BITMAP_FMT_RGBA8888);
+       ns_static_assert((int)BITMAP_LAYOUT_BGRA8888 == 
(int)NSGIF_BITMAP_FMT_BGRA8888);
+       ns_static_assert((int)BITMAP_LAYOUT_ARGB8888 == 
(int)NSGIF_BITMAP_FMT_ARGB8888);
+       ns_static_assert((int)BITMAP_LAYOUT_ABGR8888 == 
(int)NSGIF_BITMAP_FMT_ABGR8888);
+
+       return (nsgif_bitmap_fmt_t)bitmap_fmt.layout;
+}
+
 static nserror gif_create_gif_data(gif_content *c)
 {
        nsgif_error gif_res;
@@ -100,11 +120,11 @@ static nserror gif_create_gif_data(gif_content *c)
                .get_buffer = guit->bitmap->get_buffer,
                .set_opaque = guit->bitmap->set_opaque,
                .test_opaque = guit->bitmap->test_opaque,
-               .modified = guit->bitmap->modified
+               .modified = guit->bitmap->modified,
        };
 
        gif_res = nsgif_create(&gif_bitmap_callbacks,
-                       NSGIF_BITMAP_FMT_R8G8B8A8, &c->gif);
+                       nsgif__get_bitmap_format(), &c->gif);
        if (gif_res != NSGIF_OK) {
                nserror err = gif__nsgif_error_to_ns(gif_res);
                content_broadcast_error(&c->base, err, NULL);
diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c
index ac617f7..871da41 100644
--- a/content/handlers/image/ico.c
+++ b/content/handlers/image/ico.c
@@ -34,6 +34,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image.h"
 #include "image/ico.h"
@@ -172,6 +173,23 @@ static bool nsico_convert(struct content *c)
        return true;
 }
 
+static bool nsico__decode(struct bmp_image *ico)
+{
+       if (ico->decoded == false) {
+               NSLOG(netsurf, DEBUG, "Decoding ICO %p", ico);
+               if (bmp_decode(ico) != BMP_OK) {
+                       return false;
+               }
+
+               bitmap_format_to_client(ico->bitmap, &(bitmap_fmt_t) {
+                       .layout = BITMAP_LAYOUT_R8G8B8A8,
+               });
+               guit->bitmap->modified(ico->bitmap);
+
+       }
+
+       return true;
+}
 
 static bool nsico_redraw(struct content *c, struct content_redraw_data *data,
                const struct rect *clip, const struct redraw_context *ctx)
@@ -188,14 +206,8 @@ static bool nsico_redraw(struct content *c, struct 
content_redraw_data *data,
        }
 
        /* ensure its decided */
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return false;
-               } else {
-                       NSLOG(netsurf, INFO, "Decoding bitmap");
-                       guit->bitmap->modified(bmp->bitmap);
-               }
-
+       if (!nsico__decode(bmp)) {
+               return false;
        }
 
        return image_bitmap_plot(bmp->bitmap, data, clip, ctx);
@@ -259,12 +271,8 @@ static void *nsico_get_internal(const struct content *c, 
void *context)
                return NULL;
        }
 
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return NULL;
-               } else {
-                       guit->bitmap->modified(bmp->bitmap);
-               }
+       if (!nsico__decode(bmp)) {
+               return NULL;
        }
 
        return bmp->bitmap;
@@ -291,12 +299,8 @@ static bool nsico_is_opaque(struct content *c)
                return false;
        }
 
-       if (bmp->decoded == false) {
-               if (bmp_decode(bmp) != BMP_OK) {
-                       return false;
-               }
-
-               guit->bitmap->modified(bmp->bitmap);
+       if (!nsico__decode(bmp)) {
+               return false;
        }
 
        return guit->bitmap->get_opaque(bmp->bitmap);
diff --git a/content/handlers/image/image.c b/content/handlers/image/image.c
index 4eb366e..3107ee4 100644
--- a/content/handlers/image/image.c
+++ b/content/handlers/image/image.c
@@ -26,6 +26,7 @@
 #include "netsurf/bitmap.h"
 #include "netsurf/content.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/bmp.h"
 #include "image/gif.h"
@@ -124,7 +125,7 @@ bool image_bitmap_plot(struct bitmap *bitmap,
                if (height == 1) {
                        /* optimise 1x1 bitmap plot */
                        pixel = guit->bitmap->get_buffer(bitmap);
-                       fill_style.fill_colour = pixel_to_colour(pixel);
+                       fill_style.fill_colour = bitmap_pixel_to_colour(pixel);
 
                        if (guit->bitmap->get_opaque(bitmap) ||
                            ((fill_style.fill_colour & 0xff000000) == 
0xff000000)) {
diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c
index 9daf06b..e07fb47 100644
--- a/content/handlers/image/jpeg.c
+++ b/content/handlers/image/jpeg.c
@@ -37,6 +37,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 
@@ -49,13 +50,8 @@
  */
 #define MIN_JPEG_SIZE 20
 
-#ifdef riscos
-/* We prefer the library to be configured with these options to save
- * copying data during decoding. */
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
-#warning JPEG library not optimally configured. Decoding will be slower.
-#endif
-/* but we don't care if we're not on RISC OS */
+#ifndef LIBJPEG_TURBO_VERSION
+#warning Using libjpeg (libjpeg-turbo is recommended)
 #endif
 
 static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
@@ -165,6 +161,94 @@ static void nsjpeg_error_exit(j_common_ptr cinfo)
 }
 
 /**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_cmyk(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       int width = cinfo->output_width * 4;
+
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+
+               for (int i = width - 4; 0 <= i; i -= 4) {
+                       /* Trivial inverse CMYK -> RGBA */
+                       const int c = scanlines[0][i + 0];
+                       const int m = scanlines[0][i + 1];
+                       const int y = scanlines[0][i + 2];
+                       const int k = scanlines[0][i + 3];
+
+                       const int ck = c * k;
+                       const int mk = m * k;
+                       const int yk = y * k;
+
+#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
+                       scanlines[0][i + bitmap_layout.r] = DIV255(ck);
+                       scanlines[0][i + bitmap_layout.g] = DIV255(mk);
+                       scanlines[0][i + bitmap_layout.b] = DIV255(yk);
+                       scanlines[0][i + bitmap_layout.a] = 0xff;
+#undef DIV255
+               }
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_rgb(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       int width = cinfo->output_width;
+
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+
+#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
+               /* Missmatch between configured libjpeg pixel format and
+                * NetSurf pixel format.  Convert to RGBA */
+               for (int i = width - 1; 0 <= i; i--) {
+                       int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED];
+                       int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN];
+                       int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE];
+                       scanlines[0][i * 4 + bitmap_layout.r] = r;
+                       scanlines[0][i * 4 + bitmap_layout.g] = g;
+                       scanlines[0][i * 4 + bitmap_layout.b] = b;
+                       scanlines[0][i * 4 + bitmap_layout.a] = 0xff;
+               }
+#endif
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
+ * Convert scan lines from CMYK to core client bitmap layout.
+ */
+static inline void nsjpeg__decode_client_fmt(
+               struct jpeg_decompress_struct *cinfo,
+               uint8_t * volatile pixels,
+               size_t rowstride)
+{
+       do {
+               JSAMPROW scanlines[1] = {
+                       [0] = (JSAMPROW)
+                               (pixels + rowstride * cinfo->output_scanline),
+               };
+               jpeg_read_scanlines(cinfo, scanlines, 1);
+       } while (cinfo->output_scanline != cinfo->output_height);
+}
+
+/**
  * create a bitmap from jpeg content.
  */
 static struct bitmap *
@@ -175,8 +259,6 @@ jpeg_cache_convert(struct content *c)
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr jerr;
        jmp_buf setjmp_buffer;
-       unsigned int height;
-       unsigned int width;
        struct bitmap * volatile bitmap = NULL;
        uint8_t * volatile pixels = NULL;
        size_t rowstride;
@@ -221,21 +303,42 @@ jpeg_cache_convert(struct content *c)
 
        /* set output processing parameters */
        if (cinfo.jpeg_color_space == JCS_CMYK ||
-                       cinfo.jpeg_color_space == JCS_YCCK) {
+           cinfo.jpeg_color_space == JCS_YCCK) {
                cinfo.out_color_space = JCS_CMYK;
        } else {
+#ifdef JCS_ALPHA_EXTENSIONS
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_R8G8B8A8:
+                       cinfo.out_color_space = JCS_EXT_RGBA;
+                       break;
+               case BITMAP_LAYOUT_B8G8R8A8:
+                       cinfo.out_color_space = JCS_EXT_BGRA;
+                       break;
+               case BITMAP_LAYOUT_A8R8G8B8:
+                       cinfo.out_color_space = JCS_EXT_ARGB;
+                       break;
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       cinfo.out_color_space = JCS_EXT_ABGR;
+                       break;
+               default:
+                       NSLOG(netsurf, ERROR, "Unexpected bitmap format: %u",
+                                       bitmap_fmt.layout);
+                       jpeg_destroy_decompress(&cinfo);
+                       return NULL;
+               }
+#else
                cinfo.out_color_space = JCS_RGB;
+#endif
        }
        cinfo.dct_method = JDCT_ISLOW;
 
        /* commence the decompression, output parameters now valid */
        jpeg_start_decompress(&cinfo);
 
-       width = cinfo.output_width;
-       height = cinfo.output_height;
-
        /* create opaque bitmap (jpegs cannot be transparent) */
-       bitmap = guit->bitmap->create(width, height, BITMAP_OPAQUE);
+       bitmap = guit->bitmap->create(
+                       cinfo.output_width,
+                       cinfo.output_height, BITMAP_OPAQUE);
        if (bitmap == NULL) {
                /* empty bitmap could not be created */
                jpeg_destroy_decompress(&cinfo);
@@ -252,50 +355,21 @@ jpeg_cache_convert(struct content *c)
 
        /* Convert scanlines from jpeg into bitmap */
        rowstride = guit->bitmap->get_rowstride(bitmap);
-       do {
-               JSAMPROW scanlines[1];
 
-               scanlines[0] = (JSAMPROW) (pixels +
-                                          rowstride * cinfo.output_scanline);
-               jpeg_read_scanlines(&cinfo, scanlines, 1);
+       switch (cinfo.out_color_space) {
+       case JCS_CMYK:
+               nsjpeg__decode_cmyk(&cinfo, pixels, rowstride);
+               break;
 
-               if (cinfo.out_color_space == JCS_CMYK) {
-                       int i;
-                       for (i = width - 1; 0 <= i; i--) {
-                               /* Trivial inverse CMYK -> RGBA */
-                               const int c = scanlines[0][i * 4 + 0];
-                               const int m = scanlines[0][i * 4 + 1];
-                               const int y = scanlines[0][i * 4 + 2];
-                               const int k = scanlines[0][i * 4 + 3];
+       case JCS_RGB:
+               nsjpeg__decode_rgb(&cinfo, pixels, rowstride);
+               break;
 
-                               const int ck = c * k;
-                               const int mk = m * k;
-                               const int yk = y * k;
+       default:
+               nsjpeg__decode_client_fmt(&cinfo, pixels, rowstride);
+               break;
+       }
 
-#define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8
-                               scanlines[0][i * 4 + 0] = DIV255(ck);
-                               scanlines[0][i * 4 + 1] = DIV255(mk);
-                               scanlines[0][i * 4 + 2] = DIV255(yk);
-                               scanlines[0][i * 4 + 3] = 0xff;
-#undef DIV255
-                       }
-               } else {
-#if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4
-                       /* Missmatch between configured libjpeg pixel format and
-                        * NetSurf pixel format.  Convert to RGBA */
-                       int i;
-                       for (i = width - 1; 0 <= i; i--) {
-                               int r = scanlines[0][i * RGB_PIXELSIZE + 
RGB_RED];
-                               int g = scanlines[0][i * RGB_PIXELSIZE + 
RGB_GREEN];
-                               int b = scanlines[0][i * RGB_PIXELSIZE + 
RGB_BLUE];
-                               scanlines[0][i * 4 + 0] = r;
-                               scanlines[0][i * 4 + 1] = g;
-                               scanlines[0][i * 4 + 2] = b;
-                               scanlines[0][i * 4 + 3] = 0xff;
-                       }
-#endif
-               }
-       } while (cinfo.output_scanline != cinfo.output_height);
        guit->bitmap->modified(bitmap);
 
        jpeg_finish_decompress(&cinfo);
diff --git a/content/handlers/image/nssprite.c 
b/content/handlers/image/nssprite.c
index a6c2909..a98c48a 100644
--- a/content/handlers/image/nssprite.c
+++ b/content/handlers/image/nssprite.c
@@ -23,6 +23,8 @@
 
 #include <stdbool.h>
 #include <stdlib.h>
+#include <string.h>
+
 #include <librosprite.h>
 
 #include "utils/utils.h"
@@ -35,6 +37,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/nssprite.h"
 
@@ -128,19 +131,7 @@ static bool nssprite_convert(struct content *c)
        }
        unsigned char *spritebuf = (unsigned char *)sprite->image;
 
-       /* reverse byte order of each word */
-       for (uint32_t y = 0; y < sprite->height; y++) {
-               for (uint32_t x = 0; x < sprite->width; x++) {
-                       int offset = 4 * (y * sprite->width + x);
-
-                       *imagebuf = (spritebuf[offset] << 24) |
-                                       (spritebuf[offset + 1] << 16) |
-                                       (spritebuf[offset + 2] << 8) |
-                                       (spritebuf[offset + 3]);
-
-                       imagebuf++;
-               }
-       }
+       memcpy(imagebuf, spritebuf, sprite->width * sprite->height * 4);
 
        c->width = sprite->width;
        c->height = sprite->height;
@@ -154,6 +145,9 @@ static bool nssprite_convert(struct content *c)
                free(title);
        }
 
+       bitmap_format_to_client(nssprite->bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_A8B8G8R8,
+       });
        guit->bitmap->modified(nssprite->bitmap);
 
        content_set_ready(c);
diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c
index d4c2ae0..30ff3be 100644
--- a/content/handlers/image/png.c
+++ b/content/handlers/image/png.c
@@ -32,6 +32,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 #include "image/png.h"
@@ -118,8 +119,37 @@ static void nspng_setup_transforms(png_structp png_ptr, 
png_infop info_ptr)
                png_set_gray_to_rgb(png_ptr);
        }
 
+       switch (bitmap_fmt.layout) {
+       case BITMAP_LAYOUT_B8G8R8A8: /* Fall through. */
+       case BITMAP_LAYOUT_A8B8G8R8:
+               png_set_bgr(png_ptr);
+               break;
+       default:
+               /* RGB is the default. */
+               break;
+       }
+
        if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
-               png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+                       break;
+
+               default:
+                       png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+                       break;
+               }
+       } else {
+               switch (bitmap_fmt.layout) {
+               case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */
+               case BITMAP_LAYOUT_A8B8G8R8:
+                       png_set_swap_alpha(png_ptr);
+                       break;
+               default:
+                       /* Alpha as final component is the default. */
+                       break;
+               }
        }
 
        /* gamma correction - we use 2.2 as our screen gamma
@@ -508,6 +538,7 @@ png_cache_convert_error:
        }
 
        if (bitmap != NULL) {
+               bitmap_format_to_client((struct bitmap *)bitmap, &bitmap_fmt);
                guit->bitmap->modified((struct bitmap *)bitmap);
        }
 
@@ -536,6 +567,7 @@ static bool nspng_convert(struct content *c)
 
        if (png_c->bitmap != NULL) {
                guit->bitmap->set_opaque(png_c->bitmap, 
guit->bitmap->test_opaque(png_c->bitmap));
+               bitmap_format_to_client(png_c->bitmap, &bitmap_fmt);
                guit->bitmap->modified(png_c->bitmap);
        }
 
diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c
index 4617998..24fc1a4 100644
--- a/content/handlers/image/rsvg.c
+++ b/content/handlers/image/rsvg.c
@@ -51,6 +51,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/rsvg.h"
 
@@ -128,41 +129,6 @@ static bool rsvg_process_data(struct content *c, const 
char *data,
        return true;
 }
 
-/** Convert Cairo's ARGB output to NetSurf's favoured ABGR format.  It converts
- * the data in-place. 
- *
- * \param pixels       Pixel data, in the form of ARGB.  This will
- *                     be overwritten with new data in the form of ABGR.
- * \param width                Width of the bitmap
- * \param height       Height of the bitmap
- * \param rowstride    Number of bytes to skip after each row (this
- *                     implementation requires this to be a multiple of 4.)
- */
-static inline void rsvg_argb_to_abgr(uint8_t *pixels, 
-               int width, int height, size_t rowstride)
-{
-       uint8_t *p = pixels;
-       int boff = 0, roff = 2;
-
-       if (endian_host_is_le() == false) {
-               boff = 1;
-               roff = 3;
-       }
-
-       for (int y = 0; y < height; y++) {
-               for (int x = 0; x < width; x++) {
-                       /* Swap R and B */
-                       const uint8_t r = p[4*x+roff];
-
-                       p[4*x+roff] = p[4*x+boff];
-
-                       p[4*x+boff] = r;
-               }
-
-               p += rowstride;
-       }
-}
-
 static bool rsvg_convert(struct content *c)
 {
        rsvg_content *d = (rsvg_content *) c;
@@ -213,10 +179,10 @@ static bool rsvg_convert(struct content *c)
        }
 
        rsvg_handle_render_cairo(d->rsvgh, d->ct);
-       rsvg_argb_to_abgr(guit->bitmap->get_buffer(d->bitmap),
-                               c->width, c->height,
-                               guit->bitmap->get_rowstride(d->bitmap));
 
+       bitmap_format_to_client(d->bitmap, &(bitmap_fmt_t) {
+               .layout = BITMAP_LAYOUT_ARGB8888,
+       });
        guit->bitmap->modified(d->bitmap);
        content_set_ready(c);
        content_set_done(c);
diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c
index 59667a8..4087f4c 100644
--- a/content/handlers/image/webp.c
+++ b/content/handlers/image/webp.c
@@ -38,6 +38,7 @@
 #include "content/content_protected.h"
 #include "content/content_factory.h"
 #include "desktop/gui_internal.h"
+#include "desktop/bitmap.h"
 
 #include "image/image_cache.h"
 
@@ -97,6 +98,9 @@ webp_cache_convert(struct content *c)
        uint8_t *decoded;
        size_t rowstride;
        struct bitmap *bitmap = NULL;
+       bitmap_fmt_t webp_fmt = {
+               .layout = bitmap_fmt.layout,
+       };
 
        source_data = content__get_source_data(c, &source_size);
 
@@ -130,17 +134,33 @@ webp_cache_convert(struct content *c)
 
        rowstride = guit->bitmap->get_rowstride(bitmap);
 
-       decoded = WebPDecodeRGBAInto(source_data,
-                                    source_size,
-                                    pixels,
-                                    webpfeatures.width * webpfeatures.height * 
4,
-                                    rowstride);
+       switch (webp_fmt.layout) {
+       default:
+               /* WebP has no ABGR function, fall back to default. */
+               webp_fmt.layout = BITMAP_LAYOUT_R8G8B8A8;
+               /* Fall through. */
+       case BITMAP_LAYOUT_R8G8B8A8:
+               decoded = WebPDecodeRGBAInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+
+       case BITMAP_LAYOUT_B8G8R8A8:
+               decoded = WebPDecodeBGRAInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+
+       case BITMAP_LAYOUT_A8R8G8B8:
+               decoded = WebPDecodeARGBInto(source_data, source_size, pixels,
+                               rowstride * webpfeatures.height, rowstride);
+               break;
+       }
        if (decoded == NULL) {
                /* decode failed */
                guit->bitmap->destroy(bitmap);
                return NULL;
        }
 
+       bitmap_format_to_client(bitmap, &webp_fmt);
        guit->bitmap->modified(bitmap);
 
        return bitmap;
diff --git a/desktop/Makefile b/desktop/Makefile
index 63749a6..5e19027 100644
--- a/desktop/Makefile
+++ b/desktop/Makefile
@@ -12,7 +12,7 @@ desktop/version.c: testament $(OBJROOT)/testament.h
 
 # S_BROWSER are sources related to full browsers but are common
 # between RISC OS, GTK, BeOS and AmigaOS builds
-S_BROWSER := browser.c browser_window.c browser_history.c \
+S_BROWSER := bitmap.c browser.c browser_window.c browser_history.c \
        download.c frames.c netsurf.c cw_helper.c \
        save_complete.c save_text.c selection.c textinput.c gui_factory.c \
        save_pdf.c font_haru.c
diff --git a/desktop/bitmap.c b/desktop/bitmap.c
new file mode 100644
index 0000000..a780576
--- /dev/null
+++ b/desktop/bitmap.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2022 Michael Drake <t...@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "utils/log.h"
+#include "utils/errors.h"
+
+#include "desktop/bitmap.h"
+#include "desktop/gui_internal.h"
+
+/** The client bitmap format. */
+bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+struct bitmap_colour_layout bitmap_layout = {
+       .r = 0,
+       .g = 1,
+       .b = 2,
+       .a = 3,
+};
+
+/**
+ * Get the colour layout for the given bitmap format.
+ *
+ * \param[in] fmt  Pixel format to get channel layout for,
+ * \return channel layout structure.
+ */
+static struct bitmap_colour_layout bitmap__get_colour_layout(
+               const bitmap_fmt_t *fmt)
+{
+       switch (fmt->layout) {
+       default:
+               /* Fall through. */
+       case BITMAP_LAYOUT_R8G8B8A8:
+               return (struct bitmap_colour_layout) {
+                       .r = 0,
+                       .g = 1,
+                       .b = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_B8G8R8A8:
+               return (struct bitmap_colour_layout) {
+                       .b = 0,
+                       .g = 1,
+                       .r = 2,
+                       .a = 3,
+               };
+
+       case BITMAP_LAYOUT_A8R8G8B8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .r = 1,
+                       .g = 2,
+                       .b = 3,
+               };
+
+       case BITMAP_LAYOUT_A8B8G8R8:
+               return (struct bitmap_colour_layout) {
+                       .a = 0,
+                       .b = 1,
+                       .g = 2,
+                       .r = 3,
+               };
+       }
+}
+
+/* Exported function, documented in include/netsurf/bitmap.h */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format)
+{
+       bitmap_fmt = *bitmap_format;
+
+       bitmap_fmt.layout = bitmap_sanitise_bitmap_layout(bitmap_fmt.layout);
+       bitmap_layout = bitmap__get_colour_layout(&bitmap_fmt);
+}
+
+/* Exported function, documented in desktop/bitmap.h */
+void bitmap_format_convert(void *bitmap,
+               const bitmap_fmt_t *fmt_from,
+               const bitmap_fmt_t *fmt_to)
+{
+       int width = guit->bitmap->get_width(bitmap);
+       int height = guit->bitmap->get_height(bitmap);
+       uint8_t *buffer = guit->bitmap->get_buffer(bitmap);
+       size_t rowstride = guit->bitmap->get_rowstride(bitmap);
+       struct bitmap_colour_layout to = bitmap__get_colour_layout(fmt_to);
+       struct bitmap_colour_layout from = bitmap__get_colour_layout(fmt_from);
+
+       NSLOG(netsurf, DEEPDEBUG, "Bitmap format conversion (%u --> %u)",
+                       fmt_from->layout, fmt_to->layout);
+
+       for (int y = 0; y < height; y++) {
+               uint8_t *row = buffer;
+
+               for (int x = 0; x < width; x++) {
+                       const uint32_t px = *((uint32_t *)(void *) row);
+
+                       row[to.r] = ((const uint8_t *) &px)[from.r];
+                       row[to.g] = ((const uint8_t *) &px)[from.g];
+                       row[to.b] = ((const uint8_t *) &px)[from.b];
+                       row[to.a] = ((const uint8_t *) &px)[from.a];
+
+                       row += sizeof(uint32_t);
+               }
+
+               buffer += rowstride;
+       }
+}
diff --git a/desktop/bitmap.h b/desktop/bitmap.h
new file mode 100644
index 0000000..574f8fb
--- /dev/null
+++ b/desktop/bitmap.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2022 Michael Drake <t...@nesturf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Internal core bitmap interface.
+ */
+
+#ifndef _NETSURF_DESKTOP_BITMAP_H_
+#define _NETSURF_DESKTOP_BITMAP_H_
+
+#include <nsutils/endian.h>
+
+#include "netsurf/types.h"
+#include "netsurf/bitmap.h"
+
+/** Pixel format: colour component order. */
+struct bitmap_colour_layout {
+       uint8_t r; /**< Byte offset within pixel to red component. */
+       uint8_t g; /**< Byte offset within pixel to green component. */
+       uint8_t b; /**< Byte offset within pixel to blue component. */
+       uint8_t a; /**< Byte offset within pixel to alpha component. */
+};
+
+/** The client bitmap format. */
+extern bitmap_fmt_t bitmap_fmt;
+
+/** The client bitmap colour channel layout. */
+extern struct bitmap_colour_layout bitmap_layout;
+
+/**
+ * Convert a bitmap pixel to a NetSurf colour (0xAARRGGBB).
+ *
+ * The bitmap must be in the client format.
+ *
+ * \param[in]  Pointer to a pixel in the bitmap's pixel data.
+ * \return The corresponding NetSurf colour.
+ */
+static inline colour bitmap_pixel_to_colour(const uint8_t *pixel)
+{
+       return (pixel[bitmap_layout.r] <<  0) |
+              (pixel[bitmap_layout.g] <<  8) |
+              (pixel[bitmap_layout.b] << 16) |
+              (pixel[bitmap_layout.a] << 24);
+}
+
+/**
+ * Sanitise bitmap pixel component layout.
+ *
+ * Map endian-dependant layouts to byte-wise layout for the host.
+ *
+ * \param[in]  layout  Layout to convert.
+ * \return sanitised layout.
+ */
+static inline enum bitmap_layout bitmap_sanitise_bitmap_layout(
+               enum bitmap_layout layout)
+{
+       bool le = endian_host_is_le();
+
+       switch (layout) {
+       case BITMAP_LAYOUT_RGBA8888:
+               layout = (le) ? BITMAP_LAYOUT_A8B8G8R8
+                             : BITMAP_LAYOUT_R8G8B8A8;
+               break;
+       case BITMAP_LAYOUT_BGRA8888:
+               layout = (le) ? BITMAP_LAYOUT_A8R8G8B8
+                             : BITMAP_LAYOUT_B8G8R8A8;
+               break;
+       case BITMAP_LAYOUT_ARGB8888:
+               layout = (le) ? BITMAP_LAYOUT_B8G8R8A8
+                             : BITMAP_LAYOUT_A8R8G8B8;
+               break;
+       case BITMAP_LAYOUT_ABGR8888:
+               layout = (le) ? BITMAP_LAYOUT_R8G8B8A8
+                             : BITMAP_LAYOUT_A8B8G8R8;
+               break;
+       default:
+               break;
+       }
+
+       return layout;
+}
+
+/**
+ * Convert bitmap from one format to another.
+ *
+ * Note that both formats should be sanitised.
+ *
+ * \param[in]  bitmap  The bitmap to convert.
+ * \param[in]  from    The current bitmap format specifier.
+ * \param[in]  to      The bitmap format to convert to.
+ */
+void bitmap_format_convert(void *bitmap,
+               const bitmap_fmt_t *from,
+               const bitmap_fmt_t *to);
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in]  bitmap       The bitmap to convert.
+ * \param[in]  current_fmt  The current bitmap format specifier.
+ */
+static inline void bitmap_format_to_client(
+               void *bitmap,
+               const bitmap_fmt_t *current_fmt)
+{
+       bitmap_fmt_t from = *current_fmt;
+
+       from.layout = bitmap_sanitise_bitmap_layout(from.layout);
+       if (from.layout != bitmap_fmt.layout) {
+               bitmap_format_convert(bitmap, &from, &bitmap_fmt);
+       }
+}
+
+/**
+ * Convert a bitmap to the client bitmap format.
+ *
+ * \param[in]  bitmap      The bitmap to convert.
+ * \param[in]  target_fmt  The target bitmap format specifier.
+ */
+static inline void bitmap_format_from_client(
+               void *bitmap,
+               const bitmap_fmt_t *target_fmt)
+{
+       bitmap_fmt_t to = *target_fmt;
+
+       to.layout = bitmap_sanitise_bitmap_layout(to.layout);
+       if (to.layout != bitmap_fmt.layout) {
+               bitmap_format_convert(bitmap, &bitmap_fmt, &to);
+       }
+}
+
+#endif
diff --git a/desktop/treeview.c b/desktop/treeview.c
index d49be0f..a65a37e 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -41,6 +41,7 @@
 #include "content/hlcache.h"
 #include "css/utils.h"
 
+#include "desktop/bitmap.h"
 #include "desktop/knockout.h"
 #include "desktop/textarea.h"
 #include "desktop/treeview.h"
@@ -5091,58 +5092,68 @@ treeview_generate_triangle_bitmap(colour bg, colour fg, 
int size)
                if (y < size / 2) {
                        /* Top half */
                        for (x = 0; x < y * 2; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour3);
-                       *(pos++) = green_from_colour(colour3);
-                       *(pos++) = blue_from_colour(colour3);
-                       *(pos++) = 0xff;
-                       *(pos++) = red_from_colour(colour1);
-                       *(pos++) = green_from_colour(colour1);
-                       *(pos++) = blue_from_colour(colour1);
-                       *(pos++) = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour3);
+                       pos[bitmap_layout.g] = green_from_colour(colour3);
+                       pos[bitmap_layout.b] = blue_from_colour(colour3);
+                       pos[bitmap_layout.a] = 0xff;
+                       pos += 4;
+                       pos[bitmap_layout.r] = red_from_colour(colour1);
+                       pos[bitmap_layout.g] = green_from_colour(colour1);
+                       pos[bitmap_layout.b] = blue_from_colour(colour1);
+                       pos[bitmap_layout.a] = 0xff;
+                       pos += 4;
                        for (x = y * 2 + 2; x < size ; x++) {
-                               *(pos++) = red_from_colour(colour0);
-                               *(pos++) = green_from_colour(colour0);
-                               *(pos++) = blue_from_colour(colour0);
-                               *(pos++) = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour0);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour0);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour0);
+                               pos[bitmap_layout.a] = 0xff;
+                               pos += 4;
                        }
                } else if ((y == size / 2) && (size & 0x1)) {
                        /* Middle row */
                        for (x = 0; x < size - 1; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour2);
-                       *(pos++) = green_from_colour(colour2);
-                       *(pos++) = blue_from_colour(colour2);
-                       *(pos++) = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour2);
+                       pos[bitmap_layout.g] = green_from_colour(colour2);
+                       pos[bitmap_layout.b] = blue_from_colour(colour2);
+                       pos[bitmap_layout.a] = 0xff;
+                       pos += 4;
                } else {
                        /* Bottom half */
                        for (x = 0; x < (size - y - 1) * 2; x++) {
-                               *(pos++) = red_from_colour(colour4);
-                               *(pos++) = green_from_colour(colour4);
-                               *(pos++) = blue_from_colour(colour4);
-                               *(pos++) = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour4);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour4);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour4);
+                               pos[bitmap_layout.a] = 0xff;
+                               pos += 4;
                        }
-                       *(pos++) = red_from_colour(colour3);
-                       *(pos++) = green_from_colour(colour3);
-                       *(pos++) = blue_from_colour(colour3);
-                       *(pos++) = 0xff;
-                       *(pos++) = red_from_colour(colour1);
-                       *(pos++) = green_from_colour(colour1);
-                       *(pos++) = blue_from_colour(colour1);
-                       *(pos++) = 0xff;
+                       pos[bitmap_layout.r] = red_from_colour(colour3);
+                       pos[bitmap_layout.g] = green_from_colour(colour3);
+                       pos[bitmap_layout.b] = blue_from_colour(colour3);
+                       pos[bitmap_layout.a] = 0xff;
+                       pos += 4;
+                       pos[bitmap_layout.r] = red_from_colour(colour1);
+                       pos[bitmap_layout.g] = green_from_colour(colour1);
+                       pos[bitmap_layout.b] = blue_from_colour(colour1);
+                       pos[bitmap_layout.a] = 0xff;
+                       pos += 4;
                        for (x = (size - y) * 2; x < size ; x++) {
-                               *(pos++) = red_from_colour(colour0);
-                               *(pos++) = green_from_colour(colour0);
-                               *(pos++) = blue_from_colour(colour0);
-                               *(pos++) = 0xff;
+                               pos[bitmap_layout.r] = red_from_colour(colour0);
+                               pos[bitmap_layout.g] = 
green_from_colour(colour0);
+                               pos[bitmap_layout.b] = 
blue_from_colour(colour0);
+                               pos[bitmap_layout.a] = 0xff;
+                               pos += 4;
                        }
                }
 
diff --git a/include/netsurf/bitmap.h b/include/netsurf/bitmap.h
index dfd1188..da1c284 100644
--- a/include/netsurf/bitmap.h
+++ b/include/netsurf/bitmap.h
@@ -61,11 +61,78 @@ enum gui_bitmap_flags {
        BITMAP_CLEAR  = (1 << 1), /**< memory should be wiped to 0 */
 };
 
+/**
+ * NetSurf bitmap pixel layout.
+ *
+ * All pixels are 32 bits per pixel (bpp). The different layouts allow control
+ * over the ordering of colour channels. All colour channels are 8 bits wide.
+ */
+enum bitmap_layout {
+       /** Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA. */
+       BITMAP_LAYOUT_R8G8B8A8,
+
+       /** Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA. */
+       BITMAP_LAYOUT_B8G8R8A8,
+
+       /** Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB. */
+       BITMAP_LAYOUT_A8R8G8B8,
+
+       /** Bite-wise ABGR: Byte order: 0xAA, 0xBB, 0xGG, 0xRR. */
+       BITMAP_LAYOUT_A8B8G8R8,
+
+       /**
+        * 32-bit RGBA (0xRRGGBBAA).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+        */
+       BITMAP_LAYOUT_RGBA8888,
+
+       /**
+        * 32-bit BGRA (0xBBGGRRAA).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+        */
+       BITMAP_LAYOUT_BGRA8888,
+
+       /**
+        * 32-bit ARGB (0xAARRGGBB).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_B8G8R8A8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_A8R8G8B8.
+        */
+       BITMAP_LAYOUT_ARGB8888,
+
+       /**
+        * 32-bit BGRA (0xAABBGGRR).
+        *
+        * * On little endian host, same as \ref BITMAP_LAYOUT_R8G8B8A8.
+        * * On big endian host, same as \ref BITMAP_LAYOUT_A8B8G8R8.
+        */
+       BITMAP_LAYOUT_ABGR8888,
+};
+
+/** Bitmap format specifier. */
+typedef struct bitmap_fmt {
+       enum bitmap_layout layout; /** Colour component layout. */
+} bitmap_fmt_t;
+
 struct content;
 struct bitmap;
 struct hlcache_handle;
 
 /**
+ * Set client bitmap format.
+ *
+ * Set this to ensure that the bitmaps decoded by the core are in the
+ * correct format for the front end.
+ *
+ * \param[in]  bitmap_format  The bitmap format specification to set.
+ */
+void bitmap_set_format(const bitmap_fmt_t *bitmap_format);
+
+/**
  * Bitmap operations.
  */
 struct gui_bitmap_table {
@@ -115,6 +182,8 @@ struct gui_bitmap_table {
        /**
         * Get the image buffer from a bitmap
         *
+        * Note that all pixels must be 4-byte aligned.
+        *
         * \param bitmap The bitmap to get the buffer from.
         * \return The image buffer or NULL if there is none.
         */
diff --git a/include/netsurf/plot_style.h b/include/netsurf/plot_style.h
index bfc0805..875020c 100644
--- a/include/netsurf/plot_style.h
+++ b/include/netsurf/plot_style.h
@@ -201,10 +201,6 @@ typedef struct plot_font_style {
         (((((c1 & 0x00ff00) * (255 - p)) +                             \
            ((c0 & 0x00ff00) * (      p))   ) >> 8) & 0x00ff00))
 
-/* get a bitmap pixel (image/bitmap.h) into a plot colour */
-#define pixel_to_colour(b)                                             \
-       b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
-
 /* Get the red channel from a colour */
 #define red_from_colour(c)                                             \
        ((c      ) & 0xff)


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- netsurf-commits@netsurf-browser.org
To unsubscribe send an email to netsurf-commits-le...@netsurf-browser.org

Reply via email to