summaryrefslogtreecommitdiff
path: root/riscos/content-handlers
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2011-05-09 09:57:40 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2011-05-09 09:57:40 +0000
commit2ec96e508c0c1a0b47ea2cfb89a50e5831567cd1 (patch)
tree172bd3bb1d859f8cb61cf12156ea5e4c60778422 /riscos/content-handlers
parent044018739bafc655f400039c84b7e912ae721c8a (diff)
downloadnetsurf-2ec96e508c0c1a0b47ea2cfb89a50e5831567cd1.tar.gz
netsurf-2ec96e508c0c1a0b47ea2cfb89a50e5831567cd1.tar.bz2
Put RISC OS filetype content handlers in their own directory.
svn path=/trunk/netsurf/; revision=12336
Diffstat (limited to 'riscos/content-handlers')
-rw-r--r--riscos/content-handlers/artworks.c485
-rw-r--r--riscos/content-handlers/artworks.h41
-rw-r--r--riscos/content-handlers/awrender.s390
-rw-r--r--riscos/content-handlers/draw.c300
-rw-r--r--riscos/content-handlers/draw.h41
-rw-r--r--riscos/content-handlers/sprite.c311
-rw-r--r--riscos/content-handlers/sprite.h43
7 files changed, 1611 insertions, 0 deletions
diff --git a/riscos/content-handlers/artworks.c b/riscos/content-handlers/artworks.c
new file mode 100644
index 000000000..a46a03010
--- /dev/null
+++ b/riscos/content-handlers/artworks.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * 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
+ * Content for image/x-artworks (RISC OS implementation).
+ *
+ * Uses the ArtworksRenderer module
+ */
+
+#include "utils/config.h"
+#ifdef WITH_ARTWORKS
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "swis.h"
+#include "oslib/os.h"
+#include "oslib/wimp.h"
+#include "utils/config.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "riscos/content-handlers/artworks.h"
+#include "riscos/gui.h"
+#include "riscos/wimputils.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/utils.h"
+
+#define AWRender_FileInitAddress 0x46080
+#define AWRender_RenderAddress 0x46081
+#define AWRender_DocBounds 0x46082
+#define AWRender_SendDefs 0x46083
+#define AWRender_ClaimVectors 0x46084
+#define AWRender_ReleaseVectors 0x46085
+#define AWRender_FindFirstFont 0x46086
+#define AWRender_FindNextFont 0x46087
+
+
+#define INITIAL_BLOCK_SIZE 0x1000
+
+typedef struct artworks_content {
+ struct content base;
+
+ int x0, y0, x1, y1;
+
+ void *render_routine;
+ void *render_workspace;
+
+ /* dynamically-resizable block required by
+ ArtWorksRenderer rendering routine */
+
+ void *block;
+ size_t size;
+} artworks_content;
+
+struct awinfo_block {
+ int ditherx;
+ int dithery;
+ int clip_x0;
+ int clip_y0;
+ int clip_x1;
+ int clip_y1;
+ int print_lowx;
+ int print_lowy;
+ int print_handle;
+ int print_x1;
+ int print_y1;
+ int bgcolour;
+};
+
+
+/* Assembler routines for interfacing with the ArtworksRenderer module */
+
+extern os_error *awrender_init(const char **doc,
+ unsigned long *doc_size,
+ void *routine,
+ void *workspace);
+
+extern os_error *awrender_render(const char *doc,
+ const struct awinfo_block *info,
+ const os_trfm *trans,
+ const int *vdu_vars,
+ void **rsz_block,
+ size_t *rsz_size,
+ int wysiwyg_setting,
+ int output_dest,
+ size_t doc_size,
+ void *routine,
+ void *workspace);
+
+static nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool artworks_convert(struct content *c);
+static void artworks_destroy(struct content *c);
+static bool artworks_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror artworks_clone(const struct content *old, struct content **newc);
+static content_type artworks_content_type(lwc_string *mime_type);
+
+static const content_handler artworks_content_handler = {
+ artworks_create,
+ NULL,
+ artworks_convert,
+ NULL,
+ artworks_destroy,
+ NULL,
+ NULL,
+ NULL,
+ artworks_redraw,
+ NULL,
+ NULL,
+ artworks_clone,
+ NULL,
+ artworks_content_type,
+ false
+};
+
+static const char *artworks_types[] = {
+ "image/x-artworks"
+};
+
+static lwc_string *artworks_mime_types[NOF_ELEMENTS(artworks_types)];
+
+nserror artworks_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(artworks_mime_types); i++) {
+ lerror = lwc_intern_string(artworks_types[i],
+ strlen(artworks_types[i]),
+ &artworks_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(artworks_mime_types[i],
+ &artworks_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ artworks_fini();
+
+ return error;
+}
+
+void artworks_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(artworks_mime_types); i++) {
+ if (artworks_mime_types[i] != NULL)
+ lwc_string_unref(artworks_mime_types[i]);
+ }
+}
+
+nserror artworks_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ artworks_content *aw;
+ nserror error;
+
+ aw = talloc_zero(0, artworks_content);
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&aw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(aw);
+ return error;
+ }
+
+ *c = (struct content *) aw;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_ARTWORKS for display.
+ *
+ * No conversion is necessary. We merely read the ArtWorks
+ * bounding box bottom-left.
+ */
+
+bool artworks_convert(struct content *c)
+{
+ artworks_content *aw = (artworks_content *) c;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ void *init_workspace;
+ void *init_routine;
+ os_error *error;
+ int used = -1; /* slightly better with older OSLib versions */
+ char title[100];
+
+ /* check whether AWViewer has been seen and we can therefore
+ locate the ArtWorks rendering modules */
+ xos_read_var_val_size("Alias$LoadArtWorksModules", 0, os_VARTYPE_STRING,
+ &used, NULL, NULL);
+ if (used >= 0) {
+ LOG(("Alias$LoadArtWorksModules not defined"));
+ msg_data.error = messages_get("AWNotSeen");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ /* load the modules, or do nothing if they're already loaded */
+ error = xos_cli("LoadArtWorksModules");
+ if (error) {
+ LOG(("xos_cli: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ /* lookup the addresses of the init and render routines */
+ error = (os_error*)_swix(AWRender_FileInitAddress, _OUT(0) | _OUT(1),
+ &init_routine, &init_workspace);
+ if (error) {
+ LOG(("AWRender_FileInitAddress: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = (os_error*)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
+ &aw->render_routine,
+ &aw->render_workspace);
+ if (error) {
+ LOG(("AWRender_RenderAddress: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ source_data = content__get_source_data(c, &source_size);
+
+ /* initialise (convert file to new format if required) */
+ error = awrender_init(&source_data, &source_size,
+ init_routine, init_workspace);
+ if (error) {
+ LOG(("awrender_init: 0x%x : %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = (os_error*)_swix(AWRender_DocBounds,
+ _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5),
+ source_data,
+ &aw->x0,
+ &aw->y0,
+ &aw->x1,
+ &aw->y1);
+
+ if (error) {
+ LOG(("AWRender_DocBounds: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ LOG(("bounding box: %d,%d,%d,%d", aw->x0, aw->y0, aw->x1, aw->y1));
+
+ /* create the resizable workspace required by the
+ ArtWorksRenderer rendering routine */
+
+ aw->size = INITIAL_BLOCK_SIZE;
+ aw->block = malloc(INITIAL_BLOCK_SIZE);
+ if (!aw->block) {
+ LOG(("failed to create block for ArtworksRenderer"));
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ c->width = (aw->x1 - aw->x0) / 512;
+ c->height = (aw->y1 - aw->y0) / 512;
+
+ snprintf(title, sizeof(title), messages_get("ArtWorksTitle"),
+ c->width, c->height, source_size);
+ content__set_title(c, title);
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_ARTWORKS and free all resources it owns.
+ */
+
+void artworks_destroy(struct content *c)
+{
+ artworks_content *aw = (artworks_content *) c;
+
+ free(aw->block);
+}
+
+
+/**
+ * Redraw a CONTENT_ARTWORKS.
+ */
+
+bool artworks_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y)
+{
+ static const ns_os_vdu_var_list vars = {
+ os_MODEVAR_XEIG_FACTOR,
+ {
+ os_MODEVAR_YEIG_FACTOR,
+ os_MODEVAR_LOG2_BPP,
+ os_VDUVAR_END_LIST
+ }
+ };
+ artworks_content *aw = (artworks_content *) c;
+ struct awinfo_block info;
+ const char *source_data;
+ unsigned long source_size;
+ os_error *error;
+ os_trfm matrix;
+ int vals[24];
+
+ int clip_x0 = clip->x0;
+ int clip_y0 = clip->y0;
+ int clip_x1 = clip->x1;
+ int clip_y1 = clip->y1;
+
+ if (plot.flush && !plot.flush())
+ return false;
+
+ /* pick up render addresses again in case they've changed
+ (eg. newer AWRender module loaded since we first loaded this file) */
+ (void)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
+ &aw->render_routine,
+ &aw->render_workspace);
+
+ /* Scaled image. Transform units (65536*OS units) */
+ matrix.entries[0][0] = width * 65536 / c->width;
+ matrix.entries[0][1] = 0;
+ matrix.entries[1][0] = 0;
+ matrix.entries[1][1] = height * 65536 / c->height;
+ /* Draw units. (x,y) = bottom left */
+ matrix.entries[2][0] = ro_plot_origin_x * 256 + x * 512 -
+ aw->x0 * width / c->width;
+ matrix.entries[2][1] = ro_plot_origin_y * 256 - (y + height) * 512 -
+ aw->y0 * height / c->height;
+
+ info.ditherx = ro_plot_origin_x;
+ info.dithery = ro_plot_origin_y;
+
+ clip_x0 -= x;
+ clip_y0 -= y;
+ clip_x1 -= x;
+ clip_y1 -= y;
+
+ if (scale == 1.0) {
+ info.clip_x0 = (clip_x0 * 512) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - clip_y1) * 512) + aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - clip_y0) * 512) + aw->y0 + 511;
+ }
+ else {
+ info.clip_x0 = (clip_x0 * 512 / scale) + aw->x0 - 511;
+ info.clip_y0 = ((c->height - (clip_y1 / scale)) * 512) + aw->y0 - 511;
+ info.clip_x1 = (clip_x1 * 512 / scale) + aw->x0 + 511;
+ info.clip_y1 = ((c->height - (clip_y0 / scale)) * 512) + aw->y0 + 511;
+ }
+
+ info.print_lowx = 0;
+ info.print_lowy = 0;
+ info.print_handle = 0;
+ info.bgcolour = 0x20000000 | background_colour;
+
+ error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
+ if (error) {
+ LOG(("xos_read_vdu_variables: 0x%x: %s",
+ error->errnum, error->errmess));
+ return false;
+ }
+
+ error = xwimp_read_palette((os_palette*)&vals[3]);
+ if (error) {
+ LOG(("xwimp_read_palette: 0x%x: %s",
+ error->errnum, error->errmess));
+ return false;
+ }
+
+ source_data = content__get_source_data(c, &source_size);
+
+ error = awrender_render(source_data,
+ &info,
+ &matrix,
+ vals,
+ &aw->block,
+ &aw->size,
+ 110, /* fully anti-aliased */
+ 0,
+ source_size,
+ aw->render_routine,
+ aw->render_workspace);
+
+ if (error) {
+ LOG(("awrender_render: 0x%x: %s",
+ error->errnum, error->errmess));
+ return false;
+ }
+
+ return true;
+}
+
+nserror artworks_clone(const struct content *old, struct content **newc)
+{
+ artworks_content *aw;
+ nserror error;
+
+ aw = talloc_zero(0, artworks_content);
+ if (aw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &aw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&aw->base);
+ return error;
+ }
+
+ /* Simply re-run convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (artworks_convert(&aw->base) == false) {
+ content_destroy(&aw->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) aw;
+
+ return NSERROR_OK;
+}
+
+content_type artworks_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
diff --git a/riscos/content-handlers/artworks.h b/riscos/content-handlers/artworks.h
new file mode 100644
index 000000000..4a339cc84
--- /dev/null
+++ b/riscos/content-handlers/artworks.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
+ *
+ * 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
+ * Content for image/x-artworks (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_ARTWORKS_H_
+#define _NETSURF_RISCOS_ARTWORKS_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_ARTWORKS
+
+nserror artworks_init(void);
+void artworks_fini(void);
+
+#else
+
+#define artworks_init() NSERROR_OK
+#define artworks_fini() ((void) 0)
+
+#endif
+
+#endif
diff --git a/riscos/content-handlers/awrender.s b/riscos/content-handlers/awrender.s
new file mode 100644
index 000000000..5bcafe520
--- /dev/null
+++ b/riscos/content-handlers/awrender.s
@@ -0,0 +1,390 @@
+#if defined(__aof__)
+ AREA |ARM$$code|,CODE,READONLY
+
+ IMPORT messages_get
+ IMPORT realloc
+ IMPORT strcpy
+ IMPORT |__rt_stkovf_split_big|
+
+ EXPORT awrender_init
+ EXPORT awrender_render
+
+
+aw_rsz_block * 0
+aw_rsz_size * 4
+aw_fixed_block * 8
+aw_fixed_size * 12
+aw_sl * 16
+aw_fp * 20
+sizeof_aw * 24
+
+
+; os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace);
+
+awrender_init MOV ip,sp
+ STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI |__rt_stkovf_split_big|
+
+ LDR v2,=aw_temp
+ LDR a1,[a1]
+ MOV v1,a3
+ LDR a3,[a2]
+ MOV ip,a4
+ STR a1,[v2,#aw_rsz_block]
+ STR a3,[v2,#aw_rsz_size]
+ MOV a2,#-1
+ STR a2,[v2,#aw_fixed_block]
+ STR a3,[v2,#aw_fixed_size]
+ STR sl,[v2,#aw_sl]
+ STR fp,[v2,#aw_fp]
+ ADR a2,aw_callback
+ MOV lr,pc
+ MOV pc,v1
+ MOVVC a1,#0
+
+ ;return updated block ptr & size to caller
+
+ LDR a2,[fp,#-28]
+ LDR a3,[fp,#-24]
+ LDR ip,[v2,#aw_rsz_block]
+ LDR lr,[v2,#aw_rsz_size]
+ STR ip,[a2]
+ STR lr,[a3]
+
+ LDMEA fp,{v1,v2,fp,sp,pc}
+
+
+; os_error *awrender_render(const char *doc,
+; const struct awinfo_block *info,
+; const os_trfm *trans,
+; const int *vdu_vars,
+; char **rsz_block,
+; size_t *rsz_size,
+; int wysiwyg_setting,
+; int output_dest,
+; size_t doc_size,
+; void *routine,
+; void *workspace);
+
+awrender_render MOV ip,sp
+ STMFD sp!,{v1-v4,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI |__rt_stkovf_split_big|
+
+ LDR R12,[fp,#20]
+ LDR R14,=aw_temp
+ LDR R5,[fp,#4]
+ LDR R6,[fp,#12]
+ LDR R4,[R5] ;resizable block
+ LDR R7,[fp,#16]
+ STR R4,[R14,#aw_rsz_block]
+ STR R0,[R14,#aw_fixed_block] ;document ptr
+ STR R12,[R14,#aw_fixed_size] ;document size
+ LDR R12,[fp,#8]
+
+ STR R5,[sp,#-4]! ;ptr to receive block
+ STR R12,[sp,#-4]! ;ptr to receive size
+
+ LDR R12,[R12]
+ ADR R5,aw_callback
+ STR R12,[R14,#aw_rsz_size]
+
+ STR sl,[R14,#aw_sl]
+ STR fp,[R14,#aw_fp]
+
+ LDR R12,[fp,#28]
+ MOV lr,pc
+ LDR pc,[fp,#24]
+ MOVVC a1,#0
+
+ ;return updated block ptr & size to caller
+
+ LDR R7,=aw_temp
+ LDR R12,[sp],#4
+ LDR R4,[sp],#4
+ LDR R5,[R7,#aw_rsz_size]
+ LDR R6,[R7,#aw_rsz_block]
+ STR R5,[R12]
+ STR R6,[R4]
+
+ LDMEA fp,{v1-v4,fp,sp,pc}
+
+
+; Callback routine for block resizing
+; (passed to AWRender init and render routines)
+;
+; entry R11 = reason code
+; 0 = CallBackReason_Memory
+; 3 = CallBackReason_Interface
+; (0 => return capabilities)
+; exit R0 => base of resizable block
+; R1 = size of resizable block
+; R2 => base of fixed block (or -1 if no fixed block)
+; R3 = size of fixed block (or document in resizable block)
+; VC if resize successful, VS and R0 => error otherwise
+
+aw_callback TEQ R11,#3
+ TEQEQ R0,#0
+ MOVEQ R0,#1<<10 ;background colour supplied
+ TEQ R11,#0
+ LDREQ R11,=aw_temp
+ MOVNE PC,R14
+
+ CMP R0,#-1 ;read block size?
+ LDRNE R2,[R11,#aw_rsz_size]
+ MOVNE R1,R0 ;new block size
+ LDR R0,[R11,#aw_rsz_block]
+ BEQ aw_read
+
+ ; Note: because ArtworksRenderer seems to call
+ ; this routine for every scanline rendered
+ ; we never call realloc unless we have to in
+ ; order to expand the block. Also it calls
+ ; us with a size request of 0 which we must
+ ; safely ignore otherwise rendering will stop.
+
+ CMP R1,R2
+ BLS aw_read
+
+ STMFD R13!,{R1,R10-R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ BL realloc
+ LDMFD R13!,{R1,R10-R12,R14}
+
+ CMP R0,#0 ;did it work?
+ BEQ aw_nomem
+
+ STR R0,[R11]
+ STR R1,[R11,#aw_rsz_size]
+
+aw_read ; return details of fixed block
+
+ LDR R2,[R11,#aw_fixed_block]
+ LDR R3,[R11,#aw_fixed_size]
+ SUBS R11,R11,R11 ;clear V
+ MOV PC,R14
+
+aw_nomem STMFD R13!,{R10,R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ ADR R0,tok_nomem
+ BL messages_get
+ MOV a2,a1
+ LDR a1,=errblk + 4
+ BL strcpy
+ SUB R0,R0,#4 ;error number already 0
+ MOV R11,#0 ;restore reason code
+ CMP PC,#1<<31 ;set V
+ LDMFD R13!,{R10,R12,PC}
+
+tok_nomem = "NoMemory",0
+ ALIGN
+
+
+ AREA |ARM$$zidata|,DATA,NOINIT
+
+aw_temp % sizeof_aw
+errblk % 256
+
+ END
+
+#elif defined(__ELF__)
+
+ .text
+
+.set aw_rsz_block, 0
+.set aw_rsz_size, 4
+.set aw_fixed_block, 8
+.set aw_fixed_size, 12
+.set aw_sl, 16
+.set aw_fp, 20
+.set sizeof_aw, 24
+
+@ os_error *awrender_init(byte **doc, size_t *doc_size, void *init_routine, void *init_workspace);
+
+ .global awrender_init
+awrender_init: MOV ip,sp
+ STMFD sp!,{a1,a2,v1,v2,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI __rt_stkovf_split_big
+
+ LDR v2,=aw_temp
+ LDR a1,[a1]
+ MOV v1,a3
+ LDR a3,[a2]
+ MOV ip,a4
+ STR a1,[v2,#aw_rsz_block]
+ STR a3,[v2,#aw_rsz_size]
+ MOV a2,#-1
+ STR a2,[v2,#aw_fixed_block]
+ STR a3,[v2,#aw_fixed_size]
+ STR sl,[v2,#aw_sl]
+ STR fp,[v2,#aw_fp]
+ ADR a2,aw_callback
+ MOV lr,pc
+ MOV pc,v1
+ MOVVC a1,#0
+
+ @ return updated block ptr & size to caller
+
+ LDR a2,[fp,#-28]
+ LDR a3,[fp,#-24]
+ LDR ip,[v2,#aw_rsz_block]
+ LDR lr,[v2,#aw_rsz_size]
+ STR ip,[a2]
+ STR lr,[a3]
+
+ LDMEA fp,{v1,v2,fp,sp,pc}
+
+
+@ os_error *awrender_render(const char *doc,
+@ const struct awinfo_block *info,
+@ const os_trfm *trans,
+@ const int *vdu_vars,
+@ char **rsz_block,
+@ size_t *rsz_size,
+@ int wysiwyg_setting,
+@ int output_dest,
+@ size_t doc_size,
+@ void *routine,
+@ void *workspace);
+
+ .global awrender_render
+awrender_render: MOV ip,sp
+ STMFD sp!,{v1-v4,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ SUB ip,sp,#512
+ CMP ip,sl
+ BLMI __rt_stkovf_split_big
+
+ LDR R12,[fp,#20]
+ LDR R14,=aw_temp
+ LDR R5,[fp,#4]
+ LDR R6,[fp,#12]
+ LDR R4,[R5] @ resizable block
+ LDR R7,[fp,#16]
+ STR R4,[R14,#aw_rsz_block]
+ STR R0,[R14,#aw_fixed_block] @ document ptr
+ STR R12,[R14,#aw_fixed_size] @ document size
+ LDR R12,[fp,#8]
+
+ STR R5,[sp,#-4]! @ ptr to receive block
+ STR R12,[sp,#-4]! @ ptr to receive size
+
+ LDR R12,[R12]
+ ADR R5,aw_callback
+ STR R12,[R14,#aw_rsz_size]
+
+ STR sl,[R14,#aw_sl]
+ STR fp,[R14,#aw_fp]
+
+ LDR R12,[fp,#28]
+ MOV lr,pc
+ LDR pc,[fp,#24]
+ MOVVC a1,#0
+
+ @ return updated block ptr & size to caller
+
+ LDR R7,=aw_temp
+ LDR R12,[sp],#4
+ LDR R4,[sp],#4
+ LDR R5,[R7,#aw_rsz_size]
+ LDR R6,[R7,#aw_rsz_block]
+ STR R5,[R12]
+ STR R6,[R4]
+
+ LDMEA fp,{v1-v4,fp,sp,pc}
+
+
+@ Callback routine for block resizing
+@ (passed to AWRender init and render routines)
+@
+@ entry R11 = reason code
+@ 0 = CallBackReason_Memory
+@ 3 = CallBackReason_Interface
+@ (0 => return capabilities)
+@ exit R0 => base of resizable block
+@ R1 = size of resizable block
+@ R2 => base of fixed block (or -1 if no fixed block)
+@ R3 = size of fixed block (or document in resizable block)
+@ VC if resize successful, VS and R0 => error otherwise
+
+aw_callback: TEQ R11,#3
+ TEQEQ R0,#0
+ MOVEQ R0,#1<<10 @ background colour supplied
+ TEQ R11,#0
+ LDREQ R11,=aw_temp
+ MOVNE PC,R14
+
+ CMP R0,#-1 @ read block size?
+ LDRNE R2,[R11,#aw_rsz_size]
+ MOVNE R1,R0 @ new block size
+ LDR R0,[R11,#aw_rsz_block]
+ BEQ aw_read
+
+ @ Note: because ArtworksRenderer seems to call
+ @ this routine for every scanline rendered
+ @ we never call realloc unless we have to in
+ @ order to expand the block. Also it calls
+ @ us with a size request of 0 which we must
+ @ safely ignore otherwise rendering will stop.
+
+ CMP R1,R2
+ BLS aw_read
+
+ STMFD R13!,{R1,R10-R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ BL realloc
+ LDMFD R13!,{R1,R10-R12,R14}
+
+ CMP R0,#0 @ did it work?
+ BEQ aw_nomem
+
+ STR R0,[R11]
+ STR R1,[R11,#aw_rsz_size]
+
+aw_read: @ return details of fixed block
+
+ LDR R2,[R11,#aw_fixed_block]
+ LDR R3,[R11,#aw_fixed_size]
+ SUBS R11,R11,R11 @ clear V
+ MOV PC,R14
+
+aw_nomem: STMFD R13!,{R10,R12,R14}
+ LDR sl,[R11,#aw_sl]
+ LDR fp,[R11,#aw_fp]
+ ADR R0,tok_nomem
+ BL messages_get
+ MOV a2,a1
+ LDR a1,=errblk + 4
+ BL strcpy
+ SUB R0,R0,#4 @ error number already 0
+ MOV R11,#0 @ restore reason code
+ CMP PC,#1<<31 @ set V
+ LDMFD R13!,{R10,R12,PC}
+
+tok_nomem: .asciz "NoMemory"
+ .align
+
+ .bss
+
+aw_temp: .space sizeof_aw
+ .type aw_temp, %object
+ .size aw_temp, . - aw_temp
+
+errblk: .space 256
+ .type errblk, %object
+ .size errblk, . - errblk
+
+ .end
+#endif
+
diff --git a/riscos/content-handlers/draw.c b/riscos/content-handlers/draw.c
new file mode 100644
index 000000000..ccb9353cd
--- /dev/null
+++ b/riscos/content-handlers/draw.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * 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
+ * Content for image/x-drawfile (RISC OS implementation).
+ *
+ * The DrawFile module is used to plot the DrawFile.
+ */
+
+#include "utils/config.h"
+#ifdef WITH_DRAW
+
+#include <string.h>
+#include <stdlib.h>
+#include "oslib/drawfile.h"
+#include "utils/config.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "riscos/content-handlers/draw.h"
+#include "riscos/gui.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/utils.h"
+
+typedef struct draw_content {
+ struct content base;
+
+ int x0, y0;
+} draw_content;
+
+static nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool draw_convert(struct content *c);
+static void draw_destroy(struct content *c);
+static bool draw_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror draw_clone(const struct content *old, struct content **newc);
+static content_type draw_content_type(lwc_string *mime_type);
+
+static const content_handler draw_content_handler = {
+ draw_create,
+ NULL,
+ draw_convert,
+ NULL,
+ draw_destroy,
+ NULL,
+ NULL,
+ NULL,
+ draw_redraw,
+ NULL,
+ NULL,
+ draw_clone,
+ NULL,
+ draw_content_type,
+ false
+};
+
+static const char *draw_types[] = {
+ "application/drawfile",
+ "application/x-drawfile",
+ "image/drawfile",
+ "image/x-drawfile"
+};
+
+static lwc_string *draw_mime_types[NOF_ELEMENTS(draw_types)];
+
+nserror draw_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(draw_mime_types); i++) {
+ lerror = lwc_intern_string(draw_types[i],
+ strlen(draw_types[i]),
+ &draw_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(draw_mime_types[i],
+ &draw_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ draw_fini();
+
+ return error;
+}
+
+void draw_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(draw_mime_types); i++) {
+ if (draw_mime_types[i] != NULL)
+ lwc_string_unref(draw_mime_types[i]);
+ }
+}
+
+nserror draw_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ draw_content *draw;
+ nserror error;
+
+ draw = talloc_zero(0, draw_content);
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&draw->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(draw);
+ return error;
+ }
+
+ *c = (struct content *) draw;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_DRAW for display.
+ *
+ * No conversion is necessary. We merely read the DrawFile dimensions and
+ * bounding box bottom-left.
+ */
+
+bool draw_convert(struct content *c)
+{
+ draw_content *draw = (draw_content *) c;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ const void *data;
+ os_box bbox;
+ os_error *error;
+ char title[100];
+
+ source_data = content__get_source_data(c, &source_size);
+ data = source_data;
+
+ /* BBox contents in Draw units (256*OS unit) */
+ error = xdrawfile_bbox(0, (drawfile_diagram *) data,
+ (int) source_size, 0, &bbox);
+ if (error) {
+ LOG(("xdrawfile_bbox: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ if (bbox.x1 > bbox.x0 && bbox.y1 > bbox.y0) {
+ /* c->width & c->height stored as (OS units/2)
+ => divide by 512 to convert from draw units */
+ c->width = ((bbox.x1 - bbox.x0) / 512);
+ c->height = ((bbox.y1 - bbox.y0) / 512);
+ }
+ else
+ /* invalid/undefined bounding box */
+ c->height = c->width = 0;
+
+ draw->x0 = bbox.x0;
+ draw->y0 = bbox.y0;
+ snprintf(title, sizeof(title), messages_get("DrawTitle"), c->width,
+ c->height, source_size);
+ content__set_title(c, title);
+
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_DRAW and free all resources it owns.
+ */
+
+void draw_destroy(struct content *c)
+{
+}
+
+
+/**
+ * Redraw a CONTENT_DRAW.
+ */
+
+bool draw_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y)
+{
+ draw_content *draw = (draw_content *) c;
+ os_trfm matrix;
+ const char *source_data;
+ unsigned long source_size;
+ const void *data;
+ os_error *error;
+
+ if (plot.flush && !plot.flush())
+ return false;
+
+ if (!c->width || !c->height)
+ return false;
+
+ source_data = content__get_source_data(c, &source_size);
+ data = source_data;
+
+ /* Scaled image. Transform units (65536*OS units) */
+ matrix.entries[0][0] = width * 65536 / c->width;
+ matrix.entries[0][1] = 0;
+ matrix.entries[1][0] = 0;
+ matrix.entries[1][1] = height * 65536 / c->height;
+ /* Draw units. (x,y) = bottom left */
+ matrix.entries[2][0] = ro_plot_origin_x * 256 + x * 512 -
+ draw->x0 * width / c->width;
+ matrix.entries[2][1] = ro_plot_origin_y * 256 - (y + height) * 512 -
+ draw->y0 * height / c->height;
+
+ error = xdrawfile_render(0, (drawfile_diagram *) data,
+ (int) source_size, &matrix, 0, 0);
+ if (error) {
+ LOG(("xdrawfile_render: 0x%x: %s",
+ error->errnum, error->errmess));
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Clone a CONTENT_DRAW
+ */
+
+nserror draw_clone(const struct content *old, struct content **newc)
+{
+ draw_content *draw;
+ nserror error;
+
+ draw = talloc_zero(0, draw_content);
+ if (draw == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &draw->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&draw->base);
+ return error;
+ }
+
+ /* Simply rerun convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (draw_convert(&draw->base) == false) {
+ content_destroy(&draw->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) draw;
+
+ return NSERROR_OK;
+}
+
+content_type draw_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
diff --git a/riscos/content-handlers/draw.h b/riscos/content-handlers/draw.h
new file mode 100644
index 000000000..a0843202a
--- /dev/null
+++ b/riscos/content-handlers/draw.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * 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
+ * Content for image/x-drawfile (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_DRAW_H_
+#define _NETSURF_RISCOS_DRAW_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_DRAW
+
+nserror draw_init(void);
+void draw_fini(void);
+
+#else
+
+#define draw_init() NSERROR_OK
+#define draw_fini() ((void) 0)
+
+#endif /* WITH_DRAW */
+
+#endif
diff --git a/riscos/content-handlers/sprite.c b/riscos/content-handlers/sprite.c
new file mode 100644
index 000000000..de65faca6
--- /dev/null
+++ b/riscos/content-handlers/sprite.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * 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
+ * Content for image/x-riscos-sprite (RISC OS implementation).
+ *
+ * No conversion is necessary: we can render RISC OS sprites directly under
+ * RISC OS.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "oslib/osspriteop.h"
+#include "utils/config.h"
+#include "content/content_protected.h"
+#include "desktop/plotters.h"
+#include "riscos/gui.h"
+#include "riscos/image.h"
+#include "riscos/content-handlers/sprite.h"
+#include "utils/config.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/utils.h"
+
+#ifdef WITH_SPRITE
+
+typedef struct sprite_content {
+ struct content base;
+
+ void *data;
+} sprite_content;
+
+static nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool sprite_convert(struct content *c);
+static void sprite_destroy(struct content *c);
+static bool sprite_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror sprite_clone(const struct content *old, struct content **newc);
+static content_type sprite_content_type(lwc_string *mime_type);
+
+static const content_handler sprite_content_handler = {
+ sprite_create,
+ NULL,
+ sprite_convert,
+ NULL,
+ sprite_destroy,
+ NULL,
+ NULL,
+ NULL,
+ sprite_redraw,
+ NULL,
+ NULL,
+ sprite_clone,
+ NULL,
+ sprite_content_type,
+ false
+};
+
+static const char *sprite_types[] = {
+ "image/x-riscos-sprite"
+};
+
+static lwc_string *sprite_mime_types[NOF_ELEMENTS(sprite_types)];
+
+nserror sprite_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(sprite_mime_types); i++) {
+ lerror = lwc_intern_string(sprite_types[i],
+ strlen(sprite_types[i]),
+ &sprite_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(sprite_mime_types[i],
+ &sprite_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ sprite_fini();
+
+ return error;
+}
+
+void sprite_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(sprite_mime_types); i++) {
+ if (sprite_mime_types[i] != NULL)
+ lwc_string_unref(sprite_mime_types[i]);
+ }
+}
+
+nserror sprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, sprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&sprite->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(sprite);
+ return error;
+ }
+
+ *c = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Convert a CONTENT_SPRITE for display.
+ *
+ * No conversion is necessary. We merely read the sprite dimensions.
+ */
+
+bool sprite_convert(struct content *c)
+{
+ sprite_content *sprite = (sprite_content *) c;
+ os_error *error;
+ int w, h;
+ union content_msg_data msg_data;
+ const char *source_data;
+ unsigned long source_size;
+ const void *sprite_data;
+ char title[100];
+
+ source_data = content__get_source_data(c, &source_size);
+
+ sprite_data = source_data - 4;
+ osspriteop_area *area = (osspriteop_area*) sprite_data;
+ sprite->data = area;
+
+ /* check for bad data */
+ if ((int)source_size + 4 != area->used) {
+ msg_data.error = messages_get("BadSprite");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id) ((char *) area + area->first),
+ &w, &h, NULL, NULL);
+ if (error) {
+ LOG(("xosspriteop_read_sprite_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ msg_data.error = error->errmess;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ c->width = w;
+ c->height = h;
+ snprintf(title, sizeof(title), messages_get("SpriteTitle"), c->width,
+ c->height, source_size);
+ content__set_title(c, title);
+ content_set_ready(c);
+ content_set_done(c);
+ /* Done: update status bar */
+ content_set_status(c, "");
+ return true;
+}
+
+
+/**
+ * Destroy a CONTENT_SPRITE and free all resources it owns.
+ */
+
+void sprite_destroy(struct content *c)
+{
+ /* do not free c->data.sprite.data at it is simply a pointer to
+ * 4 bytes beforec->source_data. */
+}
+
+
+/**
+ * Redraw a CONTENT_SPRITE.
+ */
+
+bool sprite_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y)
+{
+ sprite_content *sprite = (sprite_content *) c;
+
+ if (plot.flush && !plot.flush())
+ return false;
+
+ return image_redraw(sprite->data,
+ ro_plot_origin_x + x * 2,
+ ro_plot_origin_y - y * 2,
+ width, height,
+ c->width,
+ c->height,
+ background_colour,
+ false, false, false,
+ IMAGE_PLOT_OS);
+}
+
+nserror sprite_clone(const struct content *old, struct content **newc)
+{
+ sprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, sprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &sprite->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&sprite->base);
+ return error;
+ }
+
+ /* Simply rerun convert */
+ if (old->status == CONTENT_STATUS_READY ||
+ old->status == CONTENT_STATUS_DONE) {
+ if (sprite_convert(&sprite->base) == false) {
+ content_destroy(&sprite->base);
+ return NSERROR_CLONE_FAILED;
+ }
+ }
+
+ *newc = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
+content_type sprite_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
+
+#endif
+
+
+/**
+ * Returns the bit depth of a sprite
+ *
+ * \param s sprite
+ * \return depth in bpp
+ */
+
+byte sprite_bpp(const osspriteop_header *s)
+{
+ /* bit 31 indicates the presence of a full alpha channel
+ * rather than a binary mask */
+ int type = ((unsigned)s->mode >> osspriteop_TYPE_SHIFT) & 15;
+ byte bpp = 0;
+
+ switch (type) {
+ case osspriteop_TYPE_OLD:
+ {
+ bits psr;
+ int val;
+ if (!xos_read_mode_variable(s->mode,
+ os_MODEVAR_LOG2_BPP, &val, &psr) &&
+ !(psr & _C))
+ bpp = 1 << val;
+ }
+ break;
+ case osspriteop_TYPE1BPP: bpp = 1; break;
+ case osspriteop_TYPE2BPP: bpp = 2; break;
+ case osspriteop_TYPE4BPP: bpp = 4; break;
+ case osspriteop_TYPE8BPP: bpp = 8; break;
+ case osspriteop_TYPE16BPP: bpp = 16; break;
+ case osspriteop_TYPE32BPP: bpp = 32; break;
+ case osspriteop_TYPE_CMYK: bpp = 32; break;
+ }
+ return bpp;
+}
diff --git a/riscos/content-handlers/sprite.h b/riscos/content-handlers/sprite.h
new file mode 100644
index 000000000..79e02f44b
--- /dev/null
+++ b/riscos/content-handlers/sprite.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ *
+ * 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
+ * Content for image/x-riscos-sprite (RISC OS interface).
+ */
+
+#ifndef _NETSURF_RISCOS_SPRITE_H_
+#define _NETSURF_RISCOS_SPRITE_H_
+
+#include "utils/config.h"
+#include "utils/errors.h"
+
+#ifdef WITH_SPRITE
+
+nserror sprite_init(void);
+void sprite_fini(void);
+
+#else
+
+#define sprite_init() NSERROR_OK
+#define sprite_fini() ((void) 0)
+
+#endif
+
+byte sprite_bpp(const osspriteop_header *s);
+
+#endif