summaryrefslogtreecommitdiff
path: root/riscos/thumbnail.c
diff options
context:
space:
mode:
authorRichard Wilson <rjw@netsurf-browser.org>2005-06-23 17:24:23 +0000
committerRichard Wilson <rjw@netsurf-browser.org>2005-06-23 17:24:23 +0000
commitf559054c1a1b0819e52e0f9d04fc55be484746c5 (patch)
tree2c6652666c751a1a368920679da0ba85b01854d8 /riscos/thumbnail.c
parentb88a81b9d9570c3219dc924c3dd2b424d99ee4c3 (diff)
downloadnetsurf-f559054c1a1b0819e52e0f9d04fc55be484746c5.tar.gz
netsurf-f559054c1a1b0819e52e0f9d04fc55be484746c5.tar.bz2
[project @ 2005-06-23 17:24:23 by rjw]
Allow images to be unloaded to disk or compressed in memory. Provide thumbnails in all tree windows (hotlist, history). Optimise the application initialisation times. Part 2 of 2. svn path=/import/netsurf/; revision=1762
Diffstat (limited to 'riscos/thumbnail.c')
-rw-r--r--riscos/thumbnail.c327
1 files changed, 142 insertions, 185 deletions
diff --git a/riscos/thumbnail.c b/riscos/thumbnail.c
index c0c667a1d..123e84d37 100644
--- a/riscos/thumbnail.c
+++ b/riscos/thumbnail.c
@@ -3,7 +3,7 @@
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* Copyright 2004 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
+ * Copyright 2005 Richard Wilson <info@tinct.net>
*/
/** \file
@@ -20,8 +20,11 @@
#include "oslib/osfile.h"
#include "oslib/osspriteop.h"
#include "netsurf/content/content.h"
+#include "netsurf/content/url_store.h"
#include "netsurf/desktop/plotters.h"
+#include "netsurf/image/bitmap.h"
#include "netsurf/render/font.h"
+#include "netsurf/riscos/bitmap.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/options.h"
#include "netsurf/riscos/thumbnail.h"
@@ -46,9 +49,11 @@ struct thumbnail_save_area {
/* Internal prototypes
*/
+static osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap);
static void thumbnail_test(void);
-static struct thumbnail_save_area* thumbnail_switch_output(osspriteop_area *sprite_area,
- osspriteop_header *sprite_header);
+static struct thumbnail_save_area* thumbnail_switch_output(
+ osspriteop_area *sprite_area,
+ osspriteop_header *sprite_header);
static void thumbnail_restore_output(struct thumbnail_save_area *save_area);
@@ -56,257 +61,213 @@ static void thumbnail_restore_output(struct thumbnail_save_area *save_area);
* Create a thumbnail of a page.
*
* \param content content structure to thumbnail
- * \param area sprite area containing thumbnail sprite
- * \param sprite pointer to sprite
- * \param width sprite width / pixels
- * \param height sprite height / pixels
- *
- * The thumbnail is rendered in the given sprite.
+ * \param bitmap the bitmap to draw to
+ * \param url the URL the thumnail belongs to, or NULL
*/
-void thumbnail_create(struct content *content, osspriteop_area *area,
- osspriteop_header *sprite, int width, int height) {
+bool thumbnail_create(struct content *content, struct bitmap *bitmap,
+ const char *url) {
float scale = 1.0;
- osspriteop_area *temp_area = NULL;
struct thumbnail_save_area *save_area;
- osspriteop_area *render_area = NULL;
- osspriteop_header *render_sprite = sprite;
-
- /* Check for 32bpp support in case we've been called for a sprite
- we didn't set up.
- */
- if (thumbnail_32bpp_available == -1) thumbnail_test();
-
- /* Get a secondary holder for non-32bpp sprites as we get a better quality by
- going to a 32bpp sprite and then down to an [n]bpp one.
- */
- if ((thumbnail_32bpp_available == 1) &&
- (sprite->mode != (os_mode)tinct_SPRITE_MODE)) {
- temp_area = thumbnail_initialise(
- width, height,
- (os_mode)0x301680b5);
- render_area = temp_area;
- }
- if (temp_area == NULL) {
- render_area = area;
+ osspriteop_area *sprite_area = NULL;
+ osspriteop_header *sprite_header = NULL;
+ _kernel_oserror *error;
+
+ /* check if we have access to 32bpp sprites natively */
+ if (thumbnail_32bpp_available == -1)
+ thumbnail_test();
+
+ /* if we don't support 32bpp sprites then we redirect to an 8bpp
+ * image and then convert back. */
+ if (thumbnail_32bpp_available != 1) {
+ sprite_area = thumbnail_create_8bpp(bitmap);
+ if (!sprite_area)
+ return false;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
} else {
- render_sprite = (osspriteop_header *)(temp_area + 1);
+ bitmap_get_buffer(bitmap);
+ sprite_area = bitmap->sprite_area;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
}
- /* Calculate the scale
- */
- if (content->width) scale = (float) width / (float) content->width;
-
- /* Set up plotters
- */
+ /* set up the plotters */
plot = ro_plotters;
ro_plot_origin_x = 0;
- ro_plot_origin_y = height * 2;
+ ro_plot_origin_y = bitmap->height * 2;
+ if (content->width)
+ scale = (float)bitmap->width / (float)content->width;
ro_plot_set_scale(scale);
-
current_redraw_browser = NULL; /* no selection */
- /* Switch output and redraw
- */
- save_area = thumbnail_switch_output(render_area, render_sprite);
+ /* switch output and redraw */
+ save_area = thumbnail_switch_output(sprite_area, sprite_header);
if (save_area == NULL) {
- if (temp_area) free(temp_area);
- return;
+ if (thumbnail_32bpp_available != 1)
+ free(sprite_area);
+ return false;
}
+ rufl_invalidate_cache();
colourtrans_set_gcol(os_COLOUR_WHITE, colourtrans_SET_BG,
os_ACTION_OVERWRITE, 0);
os_clg();
- rufl_invalidate_cache();
- content_redraw(content, 0, 0, width, height,
- 0, 0, width, height, scale, 0xFFFFFF);
+ content_redraw(content, 0, 0, bitmap->width, bitmap->height,
+ 0, 0, bitmap->width, bitmap->height, scale, 0xFFFFFF);
thumbnail_restore_output(save_area);
rufl_invalidate_cache();
- /* Go back from 32bpp to [n]bpp if we should.
- */
- if (temp_area != NULL) {
- save_area = thumbnail_switch_output(area, sprite);
- if (save_area != NULL) {
- _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
- (char *)(temp_area + 1), 0, 0,
- tinct_ERROR_DIFFUSE);
- thumbnail_restore_output(save_area);
- }
- free(temp_area);
+ /* if we changed to 8bpp then go back to 32bpp */
+ if (thumbnail_32bpp_available != 1) {
+ bitmap_get_buffer(bitmap);
+ error = _swix(Tinct_ConvertSprite, _INR(2,3),
+ sprite_header,
+ (osspriteop_header *)(bitmap->sprite_area + 1));
+ free(sprite_area);
+ if (error)
+ return false;
}
+
+ /* register the thumbnail with the URL */
+ if (url)
+ url_store_add_thumbnail(url, bitmap);
+
+ bitmap_modified(bitmap);
+ bitmap->persistent = true;
+ return true;
}
/**
- * Initialises a sprite.
+ * Convert a bitmap to 8bpp.
*
- * The sprite background cleared to white.
- * Any necessary palette data is set up to the default palette.
- * The sprite name is set to "thumbnail".
+ * \param bitmap the bitmap to convert
+ * \return a sprite area containing an 8bpp sprite
+ */
+osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) {
+ struct thumbnail_save_area *save_area;
+ osspriteop_area *sprite_area = NULL;
+ osspriteop_header *sprite_header = NULL;
+
+ sprite_area = thumbnail_create_8bpp(bitmap);
+ if (!sprite_area)
+ return NULL;
+ sprite_header = (osspriteop_header *)(sprite_area + 1);
+
+
+ /* switch output and redraw */
+ save_area = thumbnail_switch_output(sprite_area, sprite_header);
+ if (save_area == NULL) {
+ if (thumbnail_32bpp_available != 1)
+ free(sprite_area);
+ return false;
+ }
+ _swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
+ (osspriteop_header *)(bitmap->sprite_area + 1),
+ 0, 0,
+ tinct_ERROR_DIFFUSE);
+ thumbnail_restore_output(save_area);
+
+ return sprite_area;
+}
+
+
+/**
+ * Creates an 8bpp canvas.
*
- * @param width The sprite width
- * @param height The sprite height
- * @param mode The preferred mode (0x301680b5 or os_MODE8BPP90X90)
- * @return
+ * \param bitmap the bitmap to clone the size of
+ * \return a sprite area containing an 8bpp sprite
*/
-osspriteop_area* thumbnail_initialise(int width, int height, os_mode mode) {
+osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) {
unsigned int area_size;
- unsigned int remaining_bytes;
- osspriteop_area *sprite_area;
- osspriteop_header *sprite_header;
- char *sprite_image;
-
- /* Check if we can use 32bpp sprites if we haven't already. By
- doing it this way we don't need to allocate lot of memory
- first which will probably not be available on machines that
- can't handle such sprites..
- */
- if (thumbnail_32bpp_available == -1) thumbnail_test();
-
- /* If we can't handle 32bpp then we get 8bpp.
- */
- if (thumbnail_32bpp_available != 1) mode = os_MODE8BPP90X90;
-
- /* Calculate our required memory
- */
- area_size = sizeof(osspriteop_area) + sizeof(osspriteop_header);
- if (mode == (os_mode)0x301680b5) {
- area_size += width * height * 4;
- } else {
- area_size += ((width + 3) & ~3) * height + 2048;
- }
+ osspriteop_area *sprite_area = NULL;
+ osspriteop_header *sprite_header = NULL;
- /* Try to get enough memory
- */
- if ((sprite_area = (osspriteop_area *)malloc(area_size)) == NULL) {
- LOG(("Insufficient memory to create thumbnail."));
+ /* clone the sprite */
+ area_size = sizeof(osspriteop_area) +
+ sizeof(osspriteop_header) +
+ ((bitmap->width + 3) & ~3) * bitmap->height +
+ 2048;
+ sprite_area = (osspriteop_area *)malloc(area_size);
+ if (!sprite_area) {
+ LOG(("no memory for malloc()"));
return NULL;
}
-
- /* Initialise the sprite area
- */
sprite_area->size = area_size;
sprite_area->sprite_count = 1;
sprite_area->first = 16;
sprite_area->used = area_size;
-
- /* Initialise the sprite header. We can't trust OS_SpriteOp to
- set up our palette properly due to insane legacy 8bpp palettes,
- so we do it all manually.
- */
sprite_header = (osspriteop_header *)(sprite_area + 1);
sprite_header->size = area_size - sizeof(osspriteop_area);
memset(sprite_header->name, 0x00, 12);
- strcpy(sprite_header->name, "thumbnail");
+ strcpy(sprite_header->name, "bitmap");
sprite_header->left_bit = 0;
- sprite_header->height = height - 1;
- sprite_header->mode = mode;
- if (mode == (os_mode)0x301680b5) {
- sprite_header->right_bit = 31;
- sprite_header->width = width - 1;
- sprite_header->image = sizeof(osspriteop_header);
- sprite_header->mask = sizeof(osspriteop_header);
-
- /* Clear to white, full opacity
- */
- sprite_image = ((char *)sprite_header) + sprite_header->image;
- memset(sprite_image, 0xff, area_size - sizeof(osspriteop_area) -
- sizeof(osspriteop_header));
- } else {
- sprite_header->right_bit = ((width << 3) - 1) & 31;
- sprite_header->width = ((width + 3) >> 2) - 1;
- sprite_header->image = sizeof(osspriteop_header) + 2048;
- sprite_header->mask = sizeof(osspriteop_header) + 2048;
-
- /* Create the palette. We don't read the necessary size
- like we really should as we know it's going to have
- 256 entries of 8 bytes = 2048.
- */
- xcolourtrans_read_palette((osspriteop_area *)mode, (osspriteop_id)0,
+ sprite_header->height = bitmap->height - 1;
+ sprite_header->mode = os_MODE8BPP90X90;
+ sprite_header->right_bit = ((bitmap->width << 3) - 1) & 31;
+ sprite_header->width = ((bitmap->width + 3) >> 2) - 1;
+ sprite_header->image = sizeof(osspriteop_header) + 2048;
+ sprite_header->mask = sizeof(osspriteop_header) + 2048;
+
+ /* create the palette. we don't read the necessary size like
+ * we really should as we know it's going to have 256 entries
+ * of 8 bytes = 2048. */
+ xcolourtrans_read_palette((osspriteop_area *)os_MODE8BPP90X90,
+ (osspriteop_id)0,
(os_palette *)(sprite_header + 1), 2048,
- (colourtrans_palette_flags)(1 << 1), &remaining_bytes);
-
- /* Clear to white
- */
- sprite_image = ((char *)sprite_header) + sprite_header->image;
- memset(sprite_image, 0xff, area_size - sizeof(osspriteop_area) -
- sizeof(osspriteop_header) - 2048);
- }
-
- /* Return our sprite area
- */
+ (colourtrans_palette_flags)(1 << 1), 0);
return sprite_area;
}
-/*
- * Checks to see whether 32bpp sprites are available. Rather than
- * using Wimp_ReadSysInfo we test if 32bpp sprites are available in
- * case the user has a 3rd party patch to enable them.
+/**
+ * Check to see whether 32bpp sprites are available.
+ *
+ * Rather than using Wimp_ReadSysInfo we test if 32bpp sprites are available
+ * in case the user has a 3rd party patch to enable them.
*/
static void thumbnail_test(void) {
unsigned int area_size;
osspriteop_area *sprite_area;
- /* If we're configured not to use 32bpp then we don't
- */
- if (!option_thumbnail_32bpp) {
- thumbnail_32bpp_available = 0;
- return;
- }
-
- /* Get enough memory for a 1x1 32bpp sprite
- */
+ /* try to create a 1x1 32bpp sprite */
area_size = sizeof(osspriteop_area) +
sizeof(osspriteop_header) + sizeof(int);
if ((sprite_area = (osspriteop_area *)malloc(area_size)) == NULL) {
LOG(("Insufficient memory to perform sprite test."));
return;
}
-
- /* Initialise the sprite area
- */
sprite_area->size = area_size + 1;
sprite_area->sprite_count = 0;
sprite_area->first = 16;
sprite_area->used = 16;
-
- /* Try to create a 32bpp sprite
- */
if (xosspriteop_create_sprite(osspriteop_NAME, sprite_area,
- "test", false, 1, 1, (os_mode)tinct_SPRITE_MODE)) {
+ "test", false, 1, 1, (os_mode)tinct_SPRITE_MODE))
thumbnail_32bpp_available = 0;
- } else {
+ else
thumbnail_32bpp_available = 1;
- }
-
- /* Free our memory
- */
free(sprite_area);
}
-/* Switches output to the specified sprite and returns the previous context.
-*/
-static struct thumbnail_save_area* thumbnail_switch_output(osspriteop_area *sprite_area,
- osspriteop_header *sprite_header) {
+/**
+ * Switches output to the specified sprite and returns the previous context.
+ */
+static struct thumbnail_save_area* thumbnail_switch_output(
+ osspriteop_area *sprite_area,
+ osspriteop_header *sprite_header) {
struct thumbnail_save_area *save_area;
int size;
- /* Create a save area
- */
+ /* create a save area */
save_area = calloc(sizeof(struct thumbnail_save_area), 1);
if (save_area == NULL) return NULL;
- /* Allocate OS_SpriteOp save area
- */
+ /* allocate OS_SpriteOp save area */
if (xosspriteop_read_save_area_size(osspriteop_PTR, sprite_area,
(osspriteop_id)sprite_header, &size)) {
free(save_area);
return NULL;
}
- /* Create the save area
- */
+ /* create the save area */
save_area->save_area = malloc((unsigned)size);
if (save_area->save_area == NULL) {
free(save_area);
@@ -314,8 +275,7 @@ static struct thumbnail_save_area* thumbnail_switch_output(osspriteop_area *spri
}
save_area->save_area->a[0] = 0;
- /* Switch output to sprite
- */
+ /* switch output to sprite */
if (xosspriteop_switch_output_to_sprite(osspriteop_PTR, sprite_area,
(osspriteop_id)sprite_header, save_area->save_area,
0, &save_area->context1, &save_area->context2,
@@ -328,20 +288,17 @@ static struct thumbnail_save_area* thumbnail_switch_output(osspriteop_area *spri
}
-/* Restores output to the specified context, and destroys it.
-*/
+/**
+ * Restores output to the specified context, and destroys it.
+ */
static void thumbnail_restore_output(struct thumbnail_save_area *save_area) {
- /* We don't care if we err, as there's nothing we can do about it
- */
+ /* we don't care if we err, as there's nothing we can do about it */
xosspriteop_switch_output_to_sprite(osspriteop_PTR,
(osspriteop_area *)save_area->context1,
(osspriteop_id)save_area->context2,
(osspriteop_save_area *)save_area->context3,
0, 0, 0, 0);
-
- /* Free our workspace
- */
free(save_area->save_area);
free(save_area);
}