Update RISC OS frontend to use bitmap operation table

This commit is contained in:
Vincent Sanders 2015-04-15 23:57:39 +01:00
parent 5c7e8618d5
commit ad18ef5db9
8 changed files with 199 additions and 172 deletions

View File

@ -30,22 +30,24 @@
#include <string.h>
#include <swis.h>
#include <unixlib/local.h>
#include "oslib/osfile.h"
#include "oslib/osfind.h"
#include "oslib/osgbpb.h"
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "content/content.h"
#include "image/bitmap.h"
#include "riscos/bitmap.h"
#include "riscos/image.h"
#include <oslib/osfile.h>
#include <oslib/osfind.h>
#include <oslib/osgbpb.h>
#include <oslib/osspriteop.h>
#include <oslib/wimp.h>
#include "utils/nsoption.h"
#include "riscos/palettes.h"
#include "riscos/content-handlers/sprite.h"
#include "riscos/tinct.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/utils.h"
#include "content/content.h"
#include "image/bitmap.h"
#include "riscos/image.h"
#include "riscos/palettes.h"
#include "riscos/content-handlers/sprite.h"
#include "riscos/tinct.h"
#include "riscos/bitmap.h"
/** Colour in the overlay sprite that allows the bitmap to show through */
#define OVERLAY_INDEX 0xfe
@ -109,8 +111,7 @@ static bool bitmap_initialise(struct bitmap *bitmap)
* \param state the state to create the bitmap in.
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
void *bitmap_create(int width, int height, unsigned int state)
void *riscos_bitmap_create(int width, int height, unsigned int state)
{
struct bitmap *bitmap;
@ -129,91 +130,30 @@ void *bitmap_create(int width, int height, unsigned int state)
/**
* Overlay a sprite onto the given bitmap
* Return a pointer to the pixel data in a bitmap.
*
* \param bitmap bitmap object
* \param s 8bpp sprite to be overlayed onto bitmap
* The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
* of rows. The width of a row in bytes is given by bitmap_get_rowstride().
*
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return pointer to the pixel buffer
*/
void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s)
unsigned char *riscos_bitmap_get_buffer(void *vbitmap)
{
const os_colour *palette;
const byte *sp, *mp;
bool masked = false;
bool alpha = false;
os_error *error;
int dp_offset;
int sp_offset;
unsigned *dp;
int x, y;
int w, h;
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
assert(sprite_bpp(s) == 8);
if ((unsigned)s->mode & 0x80000000U)
alpha = true;
error = xosspriteop_read_sprite_info(osspriteop_PTR,
(osspriteop_area *)0x100,
(osspriteop_id)s,
&w, &h, NULL, NULL);
if (error) {
LOG(("xosspriteop_read_sprite_info: 0x%x:%s",
error->errnum, error->errmess));
return;
}
sp_offset = ((s->width + 1) * 4) - w;
if (w > bitmap->width)
w = bitmap->width;
if (h > bitmap->height)
h = bitmap->height;
dp_offset = bitmap_get_rowstride(bitmap) / 4;
dp = (void*)bitmap_get_buffer(bitmap);
if (!dp)
return;
sp = (byte*)s + s->image;
mp = (byte*)s + s->mask;
sp += s->left_bit / 8;
mp += s->left_bit / 8;
if (s->image > (int)sizeof(*s))
palette = (os_colour*)(s + 1);
else
palette = default_palette8;
if (s->mask != s->image) {
masked = true;
bitmap_set_opaque(bitmap, false);
/* dynamically create the buffer */
if (bitmap->sprite_area == NULL) {
if (!bitmap_initialise(bitmap))
return NULL;
}
/* (partially-)transparent pixels in the overlayed sprite retain
* their transparency in the output bitmap; opaque sprite pixels
* are also propagated to the bitmap, except those which are the
* OVERLAY_INDEX colour which allow the original bitmap contents to
* show through */
for (y = 0; y < h; y++) {
unsigned *sdp = dp;
for(x = 0; x < w; x++) {
os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8;
if (*sp++ == OVERLAY_INDEX)
d = *dp;
if (masked) {
if (alpha)
d |= ((*mp << 24) ^ 0xff000000U);
else if (*mp)
d |= 0xff000000U;
}
*dp++ = d;
mp++;
}
dp = sdp + dp_offset;
sp += sp_offset;
mp += sp_offset;
}
/* image data area should exist */
if (bitmap->sprite_area)
return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44;
return NULL;
}
@ -223,7 +163,7 @@ void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s)
* \param vbitmap a bitmap, as returned by bitmap_create()
* \param opaque whether the bitmap should be plotted opaque
*/
void bitmap_set_opaque(void *vbitmap, bool opaque)
static void bitmap_set_opaque(void *vbitmap, bool opaque)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
@ -235,13 +175,26 @@ void bitmap_set_opaque(void *vbitmap, bool opaque)
}
/**
* Find the width of a pixel row in bytes.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return width of a pixel row in the bitmap
*/
size_t riscos_bitmap_get_rowstride(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->width * 4;
}
/**
* Tests whether a bitmap has an opaque alpha channel
*
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return whether the bitmap is opaque
*/
bool bitmap_test_opaque(void *vbitmap)
static bool bitmap_test_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
unsigned char *sprite;
@ -251,11 +204,11 @@ bool bitmap_test_opaque(void *vbitmap)
assert(bitmap);
sprite = bitmap_get_buffer(bitmap);
sprite = riscos_bitmap_get_buffer(bitmap);
if (!sprite)
return false;
width = bitmap_get_rowstride(bitmap);
width = riscos_bitmap_get_rowstride(bitmap);
sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1);
@ -289,7 +242,7 @@ bool bitmap_test_opaque(void *vbitmap)
*
* \param vbitmap a bitmap, as returned by bitmap_create()
*/
bool bitmap_get_opaque(void *vbitmap)
bool riscos_bitmap_get_opaque(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
@ -297,56 +250,12 @@ bool bitmap_get_opaque(void *vbitmap)
}
/**
* Return a pointer to the pixel data in a bitmap.
*
* The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
* of rows. The width of a row in bytes is given by bitmap_get_rowstride().
*
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return pointer to the pixel buffer
*/
unsigned char *bitmap_get_buffer(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
assert(bitmap);
/* dynamically create the buffer */
if (bitmap->sprite_area == NULL) {
if (!bitmap_initialise(bitmap))
return NULL;
}
/* image data area should exist */
if (bitmap->sprite_area)
return ((unsigned char *) (bitmap->sprite_area)) + 16 + 44;
return NULL;
}
/**
* Find the width of a pixel row in bytes.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return width of a pixel row in the bitmap
*/
size_t bitmap_get_rowstride(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->width * 4;
}
/**
* Free a bitmap.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_destroy(void *vbitmap)
void riscos_bitmap_destroy(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
@ -369,18 +278,18 @@ void bitmap_destroy(void *vbitmap)
* \param flags modify the behaviour of the save
* \return true on success, false on error and error reported
*/
bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
os_error *error;
if (!bitmap->sprite_area)
bitmap_get_buffer(bitmap);
if (!bitmap->sprite_area) {
riscos_bitmap_get_buffer(bitmap);
}
if (!bitmap->sprite_area)
return false;
if (bitmap_get_opaque(bitmap)) {
if (riscos_bitmap_get_opaque(bitmap)) {
error = xosspriteop_save_sprite_file(osspriteop_USER_AREA,
(bitmap->sprite_area), path);
if (error) {
@ -539,20 +448,21 @@ bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
*
* \param vbitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_modified(void *vbitmap) {
void riscos_bitmap_modified(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
bitmap->state |= BITMAP_MODIFIED;
}
int bitmap_get_width(void *vbitmap)
int riscos_bitmap_get_width(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->width;
}
int bitmap_get_height(void *vbitmap)
int riscos_bitmap_get_height(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *) vbitmap;
return bitmap->height;
@ -565,11 +475,113 @@ int bitmap_get_height(void *vbitmap)
* \param vbitmap a bitmap, as returned by bitmap_create()
* \return bytes per pixel
*/
size_t bitmap_get_bpp(void *vbitmap)
static size_t bitmap_get_bpp(void *vbitmap)
{
struct bitmap *bitmap = (struct bitmap *)vbitmap;
assert(bitmap);
return 4;
}
/**
* Overlay a sprite onto the given bitmap
*
* \param bitmap bitmap object
* \param s 8bpp sprite to be overlayed onto bitmap
*/
void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s)
{
const os_colour *palette;
const byte *sp, *mp;
bool masked = false;
bool alpha = false;
os_error *error;
int dp_offset;
int sp_offset;
unsigned *dp;
int x, y;
int w, h;
assert(sprite_bpp(s) == 8);
if ((unsigned)s->mode & 0x80000000U)
alpha = true;
error = xosspriteop_read_sprite_info(osspriteop_PTR,
(osspriteop_area *)0x100,
(osspriteop_id)s,
&w, &h, NULL, NULL);
if (error) {
LOG(("xosspriteop_read_sprite_info: 0x%x:%s",
error->errnum, error->errmess));
return;
}
sp_offset = ((s->width + 1) * 4) - w;
if (w > bitmap->width)
w = bitmap->width;
if (h > bitmap->height)
h = bitmap->height;
dp_offset = riscos_bitmap_get_rowstride(bitmap) / 4;
dp = (void*)riscos_bitmap_get_buffer(bitmap);
if (!dp)
return;
sp = (byte*)s + s->image;
mp = (byte*)s + s->mask;
sp += s->left_bit / 8;
mp += s->left_bit / 8;
if (s->image > (int)sizeof(*s))
palette = (os_colour*)(s + 1);
else
palette = default_palette8;
if (s->mask != s->image) {
masked = true;
bitmap_set_opaque(bitmap, false);
}
/* (partially-)transparent pixels in the overlayed sprite retain
* their transparency in the output bitmap; opaque sprite pixels
* are also propagated to the bitmap, except those which are the
* OVERLAY_INDEX colour which allow the original bitmap contents to
* show through */
for (y = 0; y < h; y++) {
unsigned *sdp = dp;
for(x = 0; x < w; x++) {
os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8;
if (*sp++ == OVERLAY_INDEX)
d = *dp;
if (masked) {
if (alpha)
d |= ((*mp << 24) ^ 0xff000000U);
else if (*mp)
d |= 0xff000000U;
}
*dp++ = d;
mp++;
}
dp = sdp + dp_offset;
sp += sp_offset;
mp += sp_offset;
}
}
static struct gui_bitmap_table bitmap_table = {
.create = riscos_bitmap_create,
.destroy = riscos_bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = riscos_bitmap_get_opaque,
.test_opaque = bitmap_test_opaque,
.get_buffer = riscos_bitmap_get_buffer,
.get_rowstride = riscos_bitmap_get_rowstride,
.get_width = riscos_bitmap_get_width,
.get_height = riscos_bitmap_get_height,
.get_bpp = bitmap_get_bpp,
.save = riscos_bitmap_save,
.modified = riscos_bitmap_modified,
};
struct gui_bitmap_table *riscos_bitmap_table = &bitmap_table;

View File

@ -19,11 +19,15 @@
#ifndef _NETSURF_RISCOS_BITMAP_H_
#define _NETSURF_RISCOS_BITMAP_H_
/** bitmap operations table */
struct gui_bitmap_table *riscos_bitmap_table;
#include <stdbool.h>
#include "oslib/osspriteop.h"
#include "image/bitmap.h"
#define BITMAP_SAVE_FULL_ALPHA (1 << 0) /** save with full alpha channel (if not opaque) */
/** save with full alpha channel (if not opaque) */
#define BITMAP_SAVE_FULL_ALPHA (1 << 0)
struct osspriteop_area;
@ -36,6 +40,15 @@ struct bitmap {
osspriteop_area *sprite_area; /** Uncompressed data, or NULL */
};
void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s);
void riscos_bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s);
void riscos_bitmap_destroy(void *vbitmap);
void *riscos_bitmap_create(int width, int height, unsigned int state);
unsigned char *riscos_bitmap_get_buffer(void *vbitmap);
void riscos_bitmap_modified(void *vbitmap);
int riscos_bitmap_get_width(void *vbitmap);
int riscos_bitmap_get_height(void *vbitmap);
size_t riscos_bitmap_get_rowstride(void *vbitmap);
bool riscos_bitmap_get_opaque(void *vbitmap);
bool riscos_bitmap_save(void *vbitmap, const char *path, unsigned flags);
#endif

View File

@ -58,6 +58,7 @@
#include "content/backing_store.h"
#include "riscos/gui.h"
#include "riscos/bitmap.h"
#include "riscos/wimputils.h"
#include "riscos/hotlist.h"
#include "riscos/buffer.h"
@ -2446,6 +2447,7 @@ int main(int argc, char** argv)
.utf8 = riscos_utf8_table,
.search = riscos_search_table,
.llcache = filesystem_llcache_table,
.bitmap = riscos_bitmap_table,
};
ret = netsurf_register(&riscos_table);

View File

@ -519,7 +519,7 @@ bool ro_plot_bitmap(int x, int y, int width, int height,
{
const uint8_t *buffer;
buffer = bitmap_get_buffer(bitmap);
buffer = riscos_bitmap_get_buffer(bitmap);
if (!buffer) {
LOG(("bitmap_get_buffer failed"));
return false;
@ -534,6 +534,6 @@ bool ro_plot_bitmap(int x, int y, int width, int height,
bg,
flags & BITMAPF_REPEAT_X, flags & BITMAPF_REPEAT_Y,
flags & BITMAPF_REPEAT_X || flags & BITMAPF_REPEAT_Y,
bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
riscos_bitmap_get_opaque(bitmap) ? IMAGE_PLOT_TINCT_OPAQUE :
IMAGE_PLOT_TINCT_ALPHA);
}

View File

@ -1144,7 +1144,7 @@ bool ro_gui_save_object_native(hlcache_handle *h, char *path)
{
unsigned flags = (os_version == 0xA9) ?
BITMAP_SAVE_FULL_ALPHA : 0;
bitmap_save(content_get_bitmap(h), path, flags);
riscos_bitmap_save(content_get_bitmap(h), path, flags);
}
break;
case osfile_TYPE_DRAW:
@ -1370,14 +1370,14 @@ bool ro_gui_save_create_thumbnail(hlcache_handle *h, const char *name)
struct bitmap *bitmap;
osspriteop_area *area;
bitmap = bitmap_create(34, 34, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
bitmap = riscos_bitmap_create(34, 34, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
return false;
}
thumbnail_create(h, bitmap);
area = thumbnail_convert_8bpp(bitmap);
bitmap_destroy(bitmap);
riscos_bitmap_destroy(bitmap);
if (!area) {
LOG(("Thumbnail conversion failed."));
return false;

View File

@ -400,7 +400,7 @@ bool ro_save_draw_bitmap(int x, int y, int width, int height,
pencil_code code;
const uint8_t *buffer;
buffer = bitmap_get_buffer(bitmap);
buffer = riscos_bitmap_get_buffer(bitmap);
if (!buffer) {
warn_user("NoMemory", 0);
return false;

View File

@ -108,7 +108,7 @@ bool thumbnail_create(hlcache_handle *content, struct bitmap *bitmap)
return false;
sprite_header = (osspriteop_header *)(sprite_area + 1);
} else {
const uint8_t *pixbufp = bitmap_get_buffer(bitmap);
const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap);
if (!pixbufp || !bitmap->sprite_area)
return false;
sprite_area = bitmap->sprite_area;
@ -137,7 +137,7 @@ bool thumbnail_create(hlcache_handle *content, struct bitmap *bitmap)
/* if we changed to 8bpp then go back to 32bpp */
if (thumbnail_32bpp_available != 1) {
const uint8_t *pixbufp = bitmap_get_buffer(bitmap);
const uint8_t *pixbufp = riscos_bitmap_get_buffer(bitmap);
_kernel_oserror *error;
if (!pixbufp || !bitmap->sprite_area) {
@ -152,7 +152,7 @@ bool thumbnail_create(hlcache_handle *content, struct bitmap *bitmap)
return false;
}
bitmap_modified(bitmap);
riscos_bitmap_modified(bitmap);
return true;
}
@ -190,13 +190,13 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap)
if (sprite_header->image != sprite_header->mask) {
/* build the sprite mask from the alpha channel */
void *buf = bitmap_get_buffer(bitmap);
void *buf = riscos_bitmap_get_buffer(bitmap);
unsigned *dp = (unsigned *) buf;
if (!dp)
return sprite_area;
int w = bitmap_get_width(bitmap);
int h = bitmap_get_height(bitmap);
int dp_offset = bitmap_get_rowstride(bitmap) / 4 - w;
int w = riscos_bitmap_get_width(bitmap);
int h = riscos_bitmap_get_height(bitmap);
int dp_offset = riscos_bitmap_get_rowstride(bitmap) / 4 - w;
int mp_offset = ((sprite_header->width + 1) * 4) - w;
byte *mp = (byte*)sprite_header + sprite_header->mask;
bool alpha = ((unsigned)sprite_header->mode & 0x80000000U) != 0;
@ -228,7 +228,7 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap)
osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap)
{
unsigned image_size = ((bitmap->width + 3) & ~3) * bitmap->height;
bool opaque = bitmap_get_opaque(bitmap);
bool opaque = riscos_bitmap_get_opaque(bitmap);
osspriteop_header *sprite_header = NULL;
osspriteop_area *sprite_area = NULL;
unsigned area_size;

View File

@ -3411,7 +3411,7 @@ void ro_gui_window_iconise(struct gui_window *g,
}
/* create the thumbnail sprite */
bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE |
bitmap = riscos_bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE |
BITMAP_CLEAR_MEMORY);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
@ -3419,10 +3419,10 @@ void ro_gui_window_iconise(struct gui_window *g,
}
thumbnail_create(h, bitmap);
if (overlay) {
bitmap_overlay_sprite(bitmap, overlay);
riscos_bitmap_overlay_sprite(bitmap, overlay);
}
area = thumbnail_convert_8bpp(bitmap);
bitmap_destroy(bitmap);
riscos_bitmap_destroy(bitmap);
if (!area) {
LOG(("Thumbnail conversion failed."));
return;