From f559054c1a1b0819e52e0f9d04fc55be484746c5 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Thu, 23 Jun 2005 17:24:23 +0000 Subject: [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 --- riscos/thumbnail.c | 327 +++++++++++++++++++++++------------------------------ 1 file changed, 142 insertions(+), 185 deletions(-) (limited to 'riscos/thumbnail.c') 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 - * Copyright 2004 Richard Wilson + * Copyright 2005 Richard Wilson */ /** \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); } -- cgit v1.2.3