diff options
author | Adrian Lees <adrian@aemulor.com> | 2005-12-10 14:31:33 +0000 |
---|---|---|
committer | Adrian Lees <adrian@aemulor.com> | 2005-12-10 14:31:33 +0000 |
commit | 1efd4796a26a034ac18428798794b2334633b524 (patch) | |
tree | c28655b59dcdf1d9d7f3cb2e8811cb9caba9ebc1 /riscos | |
parent | 32602f6ea90a2eb48b778dc5f6b8c170fc62b7c7 (diff) | |
download | netsurf-1efd4796a26a034ac18428798794b2334633b524.tar.gz netsurf-1efd4796a26a034ac18428798794b2334633b524.tar.bz2 |
[project @ 2005-12-10 14:31:32 by adrianl]
ArtWorks support
svn path=/import/netsurf/; revision=1891
Diffstat (limited to 'riscos')
-rw-r--r-- | riscos/artworks.c | 273 | ||||
-rw-r--r-- | riscos/artworks.h | 37 | ||||
-rw-r--r-- | riscos/awrender.s | 190 | ||||
-rw-r--r-- | riscos/filetype.c | 4 | ||||
-rw-r--r-- | riscos/gui.c | 11 |
5 files changed, 514 insertions, 1 deletions
diff --git a/riscos/artworks.c b/riscos/artworks.c new file mode 100644 index 000000000..ac698f69e --- /dev/null +++ b/riscos/artworks.c @@ -0,0 +1,273 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + */ + +/** \file + * Content for image/artworks (RISC OS implementation). + * + * Uses the ArtworksRenderer module + */ + +#include <assert.h> +#include <limits.h> +#include <stdlib.h> +#include "swis.h" +#include "oslib/os.h" +#include "oslib/wimp.h" +#include "netsurf/utils/config.h" +#include "netsurf/content/content.h" +#include "netsurf/riscos/artworks.h" +#include "netsurf/riscos/gui.h" +#include "netsurf/utils/utils.h" +#include "netsurf/utils/messages.h" +#include "netsurf/utils/log.h" + +#ifdef WITH_ARTWORKS + +#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 + + +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; +}; + + +/* Assembler routines for interfacing with the ArtworksRenderer module */ + +os_error *awrender_init(char **doc, + size_t *doc_size, + void *routine, + void *workspace); + +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); + + + +/** + * 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, int width, int height) +{ + union content_msg_data msg_data; + void *init_workspace; + void *init_routine; + os_error *error; + int used; + + /* check whether AWViewer has been seen and we can therefore + locate the ArtWorks rendering modules */ + if (xos_read_var_val_size("Alias$LoadArtWorksModules", 0, os_VARTYPE_STRING, + &used, NULL, NULL) || 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 = _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 = _swix(AWRender_RenderAddress, _OUT(0) | _OUT(1), + &c->data.artworks.render_routine, + &c->data.artworks.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; + } + + /* initialise (convert file to new format if required) */ + error = awrender_init(&c->source_data, &c->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 = _swix(AWRender_DocBounds, _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5), + c->source_data, + &c->data.artworks.x0, + &c->data.artworks.y0, + &c->data.artworks.x1, + &c->data.artworks.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", + c->data.artworks.x0, c->data.artworks.y0, + c->data.artworks.x1, c->data.artworks.y1)); + + /* create the resizable workspace required by the + ArtWorksRenderer rendering routine */ + + c->data.artworks.size = INITIAL_BLOCK_SIZE; + c->data.artworks.block = malloc(INITIAL_BLOCK_SIZE); + if (!c->data.artworks.block) { + LOG(("failed to create block for ArtworksRenderer")); + warn_user("NoMemory", 0); + return false; + } + + c->width = (c->data.artworks.x1 - c->data.artworks.x0) / 512; + c->height = (c->data.artworks.y1 - c->data.artworks.y0) / 512; + + c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("ArtWorksTitle"), c->width, + c->height, c->source_size); + c->status = CONTENT_STATUS_DONE; + return true; +} + + +/** + * Destroy a CONTENT_ARTWORKS and free all resources it owns. + */ + +void artworks_destroy(struct content *c) +{ + free(c->title); + free(c->data.artworks.block); +} + + +/** + * Redraw a CONTENT_ARTWORKS. + */ + +bool artworks_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, colour background_colour) +{ + const os_VDU_VAR_LIST(4) vars = { + { os_MODEVAR_XEIG_FACTOR, + os_MODEVAR_YEIG_FACTOR, + os_MODEVAR_LOG2_BPP, + os_VDUVAR_END_LIST } + }; + struct awinfo_block info; + os_error *error; + os_trfm matrix; + int vals[24]; + + /* 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 - + c->data.artworks.x0 * width / c->width; + matrix.entries[2][1] = ro_plot_origin_y * 256 - (y + height) * 512 - + c->data.artworks.y0 * height / c->height; + + info.ditherx = ro_plot_origin_x; + info.dithery = ro_plot_origin_y; + info.clip_x0 = INT_MIN; + info.clip_y0 = INT_MIN; + info.clip_x1 = INT_MAX; + info.clip_y1 = INT_MAX; + info.print_lowx = 0; + info.print_lowy = 0; + info.print_handle = 0; + + error = xos_read_vdu_variables((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; + } + + error = awrender_render(c->source_data, + &info, + &matrix, + vals, + &c->data.artworks.block, + &c->data.artworks.size, + 110, /* fully anti-aliased */ + 0, + c->source_size, + c->data.artworks.render_routine, + c->data.artworks.render_workspace); + + if (error) { + LOG(("awrender_render: 0x%x: %s", + error->errnum, error->errmess)); + return false; + } + + return true; +} + +#endif diff --git a/riscos/artworks.h b/riscos/artworks.h new file mode 100644 index 000000000..01686138d --- /dev/null +++ b/riscos/artworks.h @@ -0,0 +1,37 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net> + */ + +/** \file + * Content for image/artworks (RISC OS interface). + */ + +#ifndef _NETSURF_RISCOS_ARTWORKS_H_ +#define _NETSURF_RISCOS_ARTWORKS_H_ + +struct content; + +struct content_artworks_data { + int x0, y0, x1, y1; + + void *render_routine; + void *render_workspace; + + /* dunamically-resizable block required by + ArtWorksRenderer rendering routine */ + + void *block; + size_t size; +}; + +bool artworks_convert(struct content *c, int width, int height); +void artworks_destroy(struct content *c); +bool artworks_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, colour background_colour); + +#endif diff --git a/riscos/awrender.s b/riscos/awrender.s new file mode 100644 index 000000000..f42916a8b --- /dev/null +++ b/riscos/awrender.s @@ -0,0 +1,190 @@ + + 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 +; 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,#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 diff --git a/riscos/filetype.c b/riscos/filetype.c index b881bd3a2..41227bed9 100644 --- a/riscos/filetype.c +++ b/riscos/filetype.c @@ -28,6 +28,7 @@ static const struct type_entry type_map[] = { {0xaff, "image/x-drawfile"}, {0xb60, "image/png"}, {0xc85, "image/jpeg"}, + {0xd94, "image/artworks"}, {0xf78, "image/jng"}, {0xf79, "text/css"}, {0xf83, "image/mng"}, @@ -233,6 +234,9 @@ int ro_content_filetype(struct content *content) #ifdef WITH_DRAW case CONTENT_DRAW: return 0xaff; #endif +#ifdef WITH_ARTWORKS + case CONTENT_ARTWORKS: return 0xd94; +#endif default: break; } diff --git a/riscos/gui.c b/riscos/gui.c index 1d1845f03..ed46b86eb 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -108,6 +108,9 @@ #ifndef FILETYPE_JPEG #define FILETYPE_JPEG 0xc85 #endif +#ifndef FILETYPE_ARTWORKS +#define FILETYPE_ARTWORKS 0xd94 +#endif int os_version = 0; @@ -197,7 +200,9 @@ struct ro_gui_poll_block *ro_gui_poll_queued_blocks = 0; static void ro_gui_choose_language(void); static void ro_gui_sprites_init(void); +#ifndef ncos static void ro_gui_icon_bar_create(void); +#endif static void ro_gui_signal(int sig); static void ro_gui_cleanup(void); static void ro_gui_handle_event(wimp_event_no event, wimp_block *block); @@ -473,6 +478,7 @@ void ro_gui_sprites_init(void) } +#ifndef ncos /** * Create an iconbar icon. */ @@ -487,6 +493,7 @@ void ro_gui_icon_bar_create(void) { "!netsurf" } } }; wimp_create_icon(&icon); } +#endif /** @@ -1430,6 +1437,7 @@ void ro_msg_dataload(wimp_message *message) case FILETYPE_JPEG: case osfile_TYPE_SPRITE: case osfile_TYPE_TEXT: + case FILETYPE_ARTWORKS: /* display the actual file */ url = ro_path_to_url(message->data.data_xfer.file_name); break; @@ -1717,7 +1725,8 @@ void ro_msg_datasave(wimp_message *message) case FILETYPE_PNG: case FILETYPE_JPEG: case osfile_TYPE_SPRITE: - case osfile_TYPE_TEXT: { + case osfile_TYPE_TEXT: + case FILETYPE_ARTWORKS: { os_error *error; dataxfer->your_ref = dataxfer->my_ref; |