NetSurf
artworks.c
Go to the documentation of this file.
1/*
2 * Copyright 2005 Adrian Lees <adrianl@users.sourceforge.net>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/** \file
20 * Content for image/x-artworks (RISC OS implementation).
21 *
22 * Uses the ArtworksRenderer module
23 */
24
25#include "utils/config.h"
26#ifdef WITH_ARTWORKS
27
28#include <assert.h>
29#include <limits.h>
30#include <stdlib.h>
31#include "swis.h"
32#include "oslib/os.h"
33#include "oslib/wimp.h"
34
35#include "utils/config.h"
36#include "utils/log.h"
37#include "utils/messages.h"
38#include "utils/utils.h"
39#include "netsurf/plotters.h"
40#include "netsurf/content.h"
41#include "content/content.h"
44#include "content/llcache.h"
45
47#include "riscos/gui.h"
48#include "riscos/wimputils.h"
49
50#define AWRender_FileInitAddress 0x46080
51#define AWRender_RenderAddress 0x46081
52#define AWRender_DocBounds 0x46082
53#define AWRender_SendDefs 0x46083
54#define AWRender_ClaimVectors 0x46084
55#define AWRender_ReleaseVectors 0x46085
56#define AWRender_FindFirstFont 0x46086
57#define AWRender_FindNextFont 0x46087
58
59
60#define INITIAL_BLOCK_SIZE 0x1000
61
62typedef struct artworks_content {
63 struct content base;
64
65 int x0, y0, x1, y1;
66
67 void *render_routine;
68 void *render_workspace;
69
70 /* dynamically-resizable block required by
71 ArtWorksRenderer rendering routine */
72
73 void *block;
74 size_t size;
75} artworks_content;
76
77struct awinfo_block {
78 int ditherx;
79 int dithery;
80 int clip_x0;
81 int clip_y0;
82 int clip_x1;
83 int clip_y1;
84 int print_lowx;
85 int print_lowy;
86 int print_handle;
87 int print_x1;
88 int print_y1;
89 int bgcolour;
90};
91
92
93/* Assembler routines for interfacing with the ArtworksRenderer module */
94
95extern os_error *awrender_init(const char **doc,
96 size_t *doc_size,
97 void *routine,
98 void *workspace);
99
100extern os_error *awrender_render(const char *doc,
101 const struct awinfo_block *info,
102 const os_trfm *trans,
103 const int *vdu_vars,
104 void **rsz_block,
105 size_t *rsz_size,
106 int wysiwyg_setting,
107 int output_dest,
108 size_t doc_size,
109 void *routine,
110 void *workspace);
111
112static nserror artworks_create(const content_handler *handler,
113 lwc_string *imime_type, const struct http_parameter *params,
114 llcache_handle *llcache, const char *fallback_charset,
115 bool quirks, struct content **c);
116static bool artworks_convert(struct content *c);
117static void artworks_destroy(struct content *c);
118static bool artworks_redraw(struct content *c, struct content_redraw_data *data,
119 const struct rect *clip, const struct redraw_context *ctx);
120static nserror artworks_clone(const struct content *old, struct content **newc);
121static content_type artworks_content_type(void);
122
123static const content_handler artworks_content_handler = {
124 .create = artworks_create,
125 .data_complete = artworks_convert,
126 .destroy = artworks_destroy,
127 .redraw = artworks_redraw,
128 .clone = artworks_clone,
129 .type = artworks_content_type,
130 .no_share = false,
131};
132
133static const char *artworks_types[] = {
134 "image/x-artworks"
135};
136
137CONTENT_FACTORY_REGISTER_TYPES(artworks, artworks_types,
138 artworks_content_handler)
139
140nserror artworks_create(const content_handler *handler,
141 lwc_string *imime_type, const struct http_parameter *params,
142 llcache_handle *llcache, const char *fallback_charset,
143 bool quirks, struct content **c)
144{
145 artworks_content *aw;
146 nserror error;
147
148 aw = calloc(1, sizeof(artworks_content));
149 if (aw == NULL)
150 return NSERROR_NOMEM;
151
152 error = content__init(&aw->base, handler, imime_type, params,
153 llcache, fallback_charset, quirks);
154 if (error != NSERROR_OK) {
155 free(aw);
156 return error;
157 }
158
159 *c = (struct content *) aw;
160
161 return NSERROR_OK;
162}
163
164/**
165 * Convert a CONTENT_ARTWORKS for display.
166 *
167 * No conversion is necessary. We merely read the ArtWorks
168 * bounding box bottom-left.
169 */
170
171bool artworks_convert(struct content *c)
172{
173 artworks_content *aw = (artworks_content *) c;
174 union content_msg_data msg_data;
175 const uint8_t *source_data;
176 size_t source_size;
177 void *init_workspace;
178 void *init_routine;
179 os_error *error;
180 int used = -1; /* slightly better with older OSLib versions */
181 char *title;
182
183 /* check whether AWViewer has been seen and we can therefore
184 locate the ArtWorks rendering modules */
185 xos_read_var_val_size("Alias$LoadArtWorksModules", 0, os_VARTYPE_STRING,
186 &used, NULL, NULL);
187 if (used >= 0) {
188 NSLOG(netsurf, INFO, "Alias$LoadArtWorksModules not defined");
189 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
190 msg_data.errordata.errormsg = messages_get("AWNotSeen");
192 return false;
193 }
194
195 /* load the modules, or do nothing if they're already loaded */
196 error = xos_cli("LoadArtWorksModules");
197 if (error) {
198 NSLOG(netsurf, INFO, "xos_cli: 0x%x: %s", error->errnum,
199 error->errmess);
200 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
201 msg_data.errordata.errormsg = error->errmess;
203 return false;
204 }
205
206 /* lookup the addresses of the init and render routines */
207 error = (os_error*)_swix(AWRender_FileInitAddress, _OUT(0) | _OUT(1),
208 &init_routine, &init_workspace);
209 if (error) {
210 NSLOG(netsurf, INFO, "AWRender_FileInitAddress: 0x%x: %s",
211 error->errnum, error->errmess);
212 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
213 msg_data.errordata.errormsg = error->errmess;
215 return false;
216 }
217
218 error = (os_error*)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
219 &aw->render_routine,
220 &aw->render_workspace);
221 if (error) {
222 NSLOG(netsurf, INFO, "AWRender_RenderAddress: 0x%x: %s",
223 error->errnum, error->errmess);
224 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
225 msg_data.errordata.errormsg = error->errmess;
227 return false;
228 }
229
230 source_data = content__get_source_data(c, &source_size);
231
232 /* initialise (convert file to new format if required) */
233 error = awrender_init((const char **)&source_data, &source_size,
234 init_routine, init_workspace);
235 if (error) {
236 NSLOG(netsurf, INFO, "awrender_init: 0x%x : %s",
237 error->errnum, error->errmess);
238 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
239 msg_data.errordata.errormsg = error->errmess;
241 return false;
242 }
243
244 error = (os_error*)_swix(AWRender_DocBounds,
245 _IN(0) | _OUT(2) | _OUT(3) | _OUT(4) | _OUT(5),
246 source_data,
247 &aw->x0,
248 &aw->y0,
249 &aw->x1,
250 &aw->y1);
251
252 if (error) {
253 NSLOG(netsurf, INFO, "AWRender_DocBounds: 0x%x: %s",
254 error->errnum, error->errmess);
255 msg_data.errordata.errorcode = NSERROR_UNKNOWN;
256 msg_data.errordata.errormsg = error->errmess;
258 return false;
259 }
260
261 NSLOG(netsurf, INFO, "bounding box: %d,%d,%d,%d", aw->x0, aw->y0,
262 aw->x1, aw->y1);
263
264 /* create the resizable workspace required by the
265 ArtWorksRenderer rendering routine */
266
267 aw->size = INITIAL_BLOCK_SIZE;
268 aw->block = malloc(INITIAL_BLOCK_SIZE);
269 if (!aw->block) {
270 NSLOG(netsurf, INFO,
271 "failed to create block for ArtworksRenderer");
272 msg_data.errordata.errorcode = NSERROR_NOMEM;
273 msg_data.errordata.errormsg = messages_get("NoMemory");
275 return false;
276 }
277
278 c->width = (aw->x1 - aw->x0) / 512;
279 c->height = (aw->y1 - aw->y0) / 512;
280
281 title = messages_get_buff("ArtWorksTitle",
283 c->width, c->height);
284 if (title != NULL) {
286 free(title);
287 }
290 /* Done: update status bar */
291 content_set_status(c, "");
292 return true;
293}
294
295
296/**
297 * Destroy a CONTENT_ARTWORKS and free all resources it owns.
298 */
299
300void artworks_destroy(struct content *c)
301{
302 artworks_content *aw = (artworks_content *) c;
303
304 free(aw->block);
305}
306
307
308/**
309 * Redraw a CONTENT_ARTWORKS.
310 */
311
312bool artworks_redraw(struct content *c, struct content_redraw_data *data,
313 const struct rect *clip, const struct redraw_context *ctx)
314{
315 static const ns_os_vdu_var_list vars = {
316 os_MODEVAR_XEIG_FACTOR,
317 {
318 os_MODEVAR_YEIG_FACTOR,
319 os_MODEVAR_LOG2_BPP,
320 os_VDUVAR_END_LIST
321 }
322 };
323 artworks_content *aw = (artworks_content *) c;
324 struct awinfo_block info;
325 const uint8_t *source_data;
326 size_t source_size;
327 os_error *error;
328 os_trfm matrix;
329 int vals[24];
330
331 int clip_x0 = clip->x0;
332 int clip_y0 = clip->y0;
333 int clip_x1 = clip->x1;
334 int clip_y1 = clip->y1;
335
336 if (ctx->plot->flush && (ctx->plot->flush(ctx) != NSERROR_OK))
337 return false;
338
339 /* pick up render addresses again in case they've changed
340 (eg. newer AWRender module loaded since we first loaded this file) */
341 (void)_swix(AWRender_RenderAddress, _OUT(0) | _OUT(1),
342 &aw->render_routine,
343 &aw->render_workspace);
344
345 /* Scaled image. Transform units (65536*OS units) */
346 matrix.entries[0][0] = data->width * 65536 / c->width;
347 matrix.entries[0][1] = 0;
348 matrix.entries[1][0] = 0;
349 matrix.entries[1][1] = data->height * 65536 / c->height;
350 /* Draw units. (x,y) = bottom left */
351 matrix.entries[2][0] = ro_plot_origin_x * 256 + data->x * 512 -
352 aw->x0 * data->width / c->width;
353 matrix.entries[2][1] = ro_plot_origin_y * 256 -
354 (data->y + data->height) * 512 -
355 aw->y0 * data->height / c->height;
356
357 info.ditherx = ro_plot_origin_x;
358 info.dithery = ro_plot_origin_y;
359
360 clip_x0 -= data->x;
361 clip_y0 -= data->y;
362 clip_x1 -= data->x;
363 clip_y1 -= data->y;
364
365 if (data->scale == 1.0) {
366 info.clip_x0 = (clip_x0 * 512) + aw->x0 - 511;
367 info.clip_y0 = ((c->height - clip_y1) * 512) + aw->y0 - 511;
368 info.clip_x1 = (clip_x1 * 512) + aw->x0 + 511;
369 info.clip_y1 = ((c->height - clip_y0) * 512) + aw->y0 + 511;
370 }
371 else {
372 info.clip_x0 = (clip_x0 * 512 / data->scale) + aw->x0 - 511;
373 info.clip_y0 = ((c->height - (clip_y1 / data->scale)) * 512) +
374 aw->y0 - 511;
375 info.clip_x1 = (clip_x1 * 512 / data->scale) + aw->x0 + 511;
376 info.clip_y1 = ((c->height - (clip_y0 / data->scale)) * 512) +
377 aw->y0 + 511;
378 }
379
380 info.print_lowx = 0;
381 info.print_lowy = 0;
382 info.print_handle = 0;
383 info.bgcolour = 0x20000000 | data->background_colour;
384
385 error = xos_read_vdu_variables(PTR_OS_VDU_VAR_LIST(&vars), vals);
386 if (error) {
387 NSLOG(netsurf, INFO, "xos_read_vdu_variables: 0x%x: %s",
388 error->errnum, error->errmess);
389 return false;
390 }
391
392 error = xwimp_read_palette((os_palette*)&vals[3]);
393 if (error) {
394 NSLOG(netsurf, INFO, "xwimp_read_palette: 0x%x: %s",
395 error->errnum, error->errmess);
396 return false;
397 }
398
399 source_data = content__get_source_data(c, &source_size);
400
401 error = awrender_render((const char *)source_data,
402 &info,
403 &matrix,
404 vals,
405 &aw->block,
406 &aw->size,
407 110, /* fully anti-aliased */
408 0,
409 source_size,
410 aw->render_routine,
411 aw->render_workspace);
412
413 if (error) {
414 NSLOG(netsurf, INFO, "awrender_render: 0x%x: %s",
415 error->errnum, error->errmess);
416 return false;
417 }
418
419 return true;
420}
421
422nserror artworks_clone(const struct content *old, struct content **newc)
423{
424 artworks_content *aw;
425 nserror error;
426
427 aw = calloc(1, sizeof(artworks_content));
428 if (aw == NULL)
429 return NSERROR_NOMEM;
430
431 error = content__clone(old, &aw->base);
432 if (error != NSERROR_OK) {
433 content_destroy(&aw->base);
434 return error;
435 }
436
437 /* Simply re-run convert */
438 if (old->status == CONTENT_STATUS_READY ||
439 old->status == CONTENT_STATUS_DONE) {
440 if (artworks_convert(&aw->base) == false) {
441 content_destroy(&aw->base);
443 }
444 }
445
446 *newc = (struct content *) aw;
447
448 return NSERROR_OK;
449}
450
451content_type artworks_content_type(void)
452{
453 return CONTENT_IMAGE;
454}
455
456#endif
Content for image/x-artworks (RISC OS interface).
Content handling interface.
void content_destroy(struct content *c)
Destroy and free a content.
Definition: content.c:354
void content_broadcast(struct content *c, content_msg msg, const union content_msg_data *data)
Send a message to all users.
Definition: content.c:752
void content_set_done(struct content *c)
Put a content in status CONTENT_STATUS_DONE.
Definition: content.c:299
bool content__set_title(struct content *c, const char *title)
Set title associated with content.
Definition: content.c:1090
nserror content__init(struct content *c, const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks)
Definition: content.c:190
const uint8_t * content__get_source_data(struct content *c, size_t *size)
Retrieve source of content.
Definition: content.c:1216
nserror content__clone(const struct content *c, struct content *nc)
Clone a content's data members.
Definition: content.c:1382
void content_set_ready(struct content *c)
Put a content in status CONTENT_STATUS_READY and unlock the content.
Definition: content.c:285
void content_set_status(struct content *c, const char *status_message)
Updates content with new status.
Definition: content.c:270
#define CONTENT_FACTORY_REGISTER_TYPES(HNAME, HTYPELIST, HHANDLER)
Protected interface to Content handling.
@ CONTENT_STATUS_READY
Some parts of content still being loaded, but can be displayed.
Definition: content_type.h:92
@ CONTENT_STATUS_DONE
Content has completed all processing.
Definition: content_type.h:95
content_type
The type of a content.
Definition: content_type.h:53
@ CONTENT_IMAGE
All images.
Definition: content_type.h:67
@ CONTENT_MSG_ERROR
error occurred
Definition: content_type.h:122
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_UNKNOWN
Unknown error - DO NOT USE.
Definition: errors.h:31
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
Public content interface.
Target independent plotting interface.
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
nsurl * llcache_handle_get_url(const llcache_handle *handle)
Retrieve the post-redirect URL of a low-level cache object.
Definition: llcache.c:4195
Low-level resource cache (interface)
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
char * messages_get_buff(const char *key,...)
Formatted message from a key in the global message hash.
Definition: messages.c:205
Localised message support (interface).
const char * nsurl_access_leaf(const nsurl *url)
Access a URL's path leaf as a string.
@ base
Definition: punycode.c:19
int ro_plot_origin_x
Definition: plotters.c:40
int ro_plot_origin_y
Definition: plotters.c:41
Content operation function table.
nserror(* create)(const struct content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, struct llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
parameters to content redraw
Definition: content.h:40
int height
vertical dimension
Definition: content.h:48
int y
coordinate for top-left of redraw
Definition: content.h:42
int x
coordinate for top-left of redraw
Definition: content.h:41
colour background_colour
The background colour.
Definition: content.h:51
int width
dimensions to render content at (for scaling contents with intrinsic dimensions)
Definition: content.h:47
float scale
Scale for redraw (for scaling contents without intrinsic dimensions)
Definition: content.h:56
Content which corresponds to a single URL.
int height
Height dimension, if applicable.
int width
Width dimension, if applicable.
struct llcache_handle * llcache
Low-level cache object.
content_status status
Current status.
unsigned int size
Estimated size of all data associated with this content.
Representation of an HTTP parameter.
Definition: parameter.c:31
Handle to low-level cache object.
Definition: llcache.c:76
nserror(* flush)(const struct redraw_context *ctx)
Only used internally by the knockout code.
Definition: plotters.h:317
Rectangle coordinates.
Definition: types.h:40
Redraw context.
Definition: plotters.h:51
const struct plotter_table * plot
Current plot operation table.
Definition: plotters.h:73
Extra data for some content_msg messages.
Definition: content.h:60
const char * title
Definition: content.h:186
void * ctx
context passed to browser_window_search()
Definition: content.h:277
Interface to a number of general purpose functionality.
A collection of grubby utilities for working with OSLib's wimp API.
#define PTR_OS_VDU_VAR_LIST(l)
Definition: wimputils.h:66
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357