[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
This commit is contained in:
Richard Wilson 2005-06-23 17:24:23 +00:00
parent b88a81b9d9
commit f559054c1a
12 changed files with 337 additions and 313 deletions

View File

@ -17,7 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unixlib/features.h>
//#include <unixlib/features.h>
#include <unixlib/local.h>
#include "oslib/font.h"
#include "oslib/help.h"
@ -45,7 +45,9 @@
#include "netsurf/render/box.h"
#include "netsurf/render/font.h"
#include "netsurf/render/html.h"
#include "netsurf/riscos/bitmap.h"
#include "netsurf/riscos/buffer.h"
#include "netsurf/riscos/filename.h"
#include "netsurf/riscos/global_history.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/help.h"
@ -109,7 +111,7 @@
int os_version = 0;
const char *__dynamic_da_name = "NetSurf"; /**< For UnixLib. */
const char * const __dynamic_da_name = "NetSurf"; /**< For UnixLib. */
int __dynamic_da_max_size = 128 * 1024 * 1024; /**< For UnixLib. */
int __feature_imagefs_is_file = 1; /**< For UnixLib. */
/* default filename handling */
@ -260,6 +262,7 @@ void gui_init(int argc, char** argv)
xosfile_create_dir("<User$Path>.Choices.NetSurf.Choices", 0);
xosfile_create_dir("<User$Path>.Choices.NetSurf.Choices.Themes", 0);
#endif
ro_filename_initialise();
#ifdef WITH_SAVE_COMPLETE
save_complete_init();
@ -283,6 +286,7 @@ void gui_init(int argc, char** argv)
ro_gui_choose_language();
bitmap_initialise_memory();
url_store_load("Choices:WWW.NetSurf.URL");
nsdir_temp = getenv("NetSurf$Dir");
@ -584,7 +588,8 @@ void gui_init2(int argc, char** argv)
void gui_quit(void)
{
url_store_save("<Choices$Write>.WWW.NetSurf.URL");
bitmap_quit();
url_store_save("<Choices$Write>.WWW.NetSurf.URL");
ro_gui_window_quit();
ro_gui_global_history_save();
ro_gui_hotlist_save();
@ -655,7 +660,8 @@ void gui_poll(bool active)
xhourglass_off();
if (active) {
event = wimp_poll(mask, &block, 0);
} else if (sched_active || gui_track || gui_reformat_pending) {
} else if (sched_active || gui_track || gui_reformat_pending ||
bitmap_maintenance) {
os_t t = os_read_monotonic_time();
if (gui_track)
@ -686,6 +692,9 @@ void gui_poll(bool active)
if (gui_reformat_pending && event == wimp_NULL_REASON_CODE)
ro_gui_window_process_reformats();
else if (bitmap_maintenance_priority ||
(bitmap_maintenance && event == wimp_NULL_REASON_CODE))
bitmap_maintain();
}
@ -801,7 +810,7 @@ void ro_gui_poll_queue(wimp_event_no event, wimp_block *block)
q->event = event;
q->block = calloc(1, sizeof(*block));
if (!q->block) {
free(q);
free(q);
LOG(("Insufficient memory for calloc"));
warn_user("NoMemory", 0);
return;
@ -903,7 +912,7 @@ void ro_gui_redraw_window_request(wimp_draw *redraw)
else if ((g = ro_gui_window_lookup(redraw->w)) != NULL)
ro_gui_window_redraw(g, redraw);
else if ((g = ro_gui_toolbar_lookup(redraw->w)) != NULL) {
if (g->toolbar->toolbar_handle == redraw->w)
if (g->toolbar->toolbar_handle == redraw->w)
ro_gui_theme_redraw(g->toolbar, redraw);
else if ((g->toolbar->editor) &&
(g->toolbar->editor->toolbar_handle == redraw->w))
@ -1045,7 +1054,7 @@ void ro_gui_mouse_click(wimp_pointer *pointer)
(hotlist_tree->toolbar->editor->toolbar_handle == pointer->w))
ro_gui_tree_toolbar_click(pointer, hotlist_tree);
else if ((global_history_tree) && (global_history_tree->toolbar) &&
(global_history_tree->toolbar->toolbar_handle == pointer->w))
(global_history_tree->toolbar->toolbar_handle == pointer->w))
ro_gui_tree_toolbar_click(pointer, global_history_tree);
else if ((global_history_tree) && (global_history_tree->toolbar) &&
(global_history_tree->toolbar->editor) &&
@ -1410,8 +1419,8 @@ void ro_msg_dataload(wimp_message *message)
} else if ((hotlist_tree) && ((wimp_w)hotlist_tree->handle ==
message->data.data_xfer.w)) {
if (!title) {
tree_edit = true;
title = url;
tree_edit = true;
title = url;
}
ro_gui_tree_get_tree_coordinates(hotlist_tree,
message->data.data_xfer.pos.x,

View File

@ -3,6 +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 2005 Richard Wilson <info@tinct.net>
*/
/** \file
@ -16,12 +17,17 @@
#include "oslib/colourtrans.h"
#include "oslib/font.h"
#include "oslib/wimp.h"
#include "netsurf/content/url_store.h"
#include "netsurf/image/bitmap.h"
#include "netsurf/riscos/bitmap.h"
#include "netsurf/riscos/image.h"
#include "netsurf/riscos/options.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/thumbnail.h"
#include "netsurf/riscos/tinct.h"
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
#define SIZE 10
@ -45,7 +51,7 @@ struct history_entry {
struct history_entry *forward_last; /**< Last child. */
unsigned int children; /**< Number of children. */
int x, y, width;
osspriteop_area *sprite_area; /**< Thumbnail sprite area, or 0. */
struct bitmap *bitmap; /**< Thumbnail bitmap, or 0. */
};
/** History tree for a window. */
@ -108,20 +114,24 @@ struct history *history_create(void)
void history_add(struct history *history, struct content *content, char *frag_id)
{
url_func_result res;
struct history_entry *entry;
char *url;
char *title;
char *split;
int width;
osspriteop_area *area;
// os_error *error;
struct bitmap *bitmap;
if (!history)
return;
/* allocate space */
entry = malloc(sizeof *entry);
url = strdup(content->url);
res = url_normalize(content->url, &url);
if (res != URL_FUNC_OK) {
warn_user("NoMemory", 0);
return;
}
title = strdup(content->title ? content->title : url);
if (!entry || !url || !title) {
warn_user("NoMemory", 0);
@ -148,7 +158,7 @@ void history_add(struct history *history, struct content *content, char *frag_id
entry->forward = entry->forward_pref = entry->forward_last = 0;
entry->children = 0;
entry->width = width / 400;
entry->sprite_area = 0;
entry->bitmap = 0;
if (history->current) {
if (history->current->forward_last)
history->current->forward_last->next = entry;
@ -162,37 +172,20 @@ void history_add(struct history *history, struct content *content, char *frag_id
}
history->current = entry;
/* area = malloc(SPRITE_SIZE);
if (!area) {
LOG(("malloc failed"));
return;
/* if we have a thumbnail, don't update until the page has finished
* loading */
bitmap = url_store_get_thumbnail(url);
bitmap = NULL;
if (!bitmap) {
bitmap = bitmap_create(WIDTH / 2, HEIGHT / 2, false);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
return;
}
bitmap_set_opaque(bitmap, true);
thumbnail_create(content, bitmap, url);
}
area->size = SPRITE_SIZE;
area->sprite_count = 0;
area->first = 16;
area->used = 16;
error = xosspriteop_create_sprite(osspriteop_NAME,
area, "thumbnail", false,
WIDTH / 2, HEIGHT / 2, os_MODE8BPP90X90);
if (error) {
LOG(("0x%x: %s", error->errnum, error->errmess));
return;
}
*/
area = thumbnail_initialise(WIDTH / 2, HEIGHT / 2, (os_mode)0x301680b5);
if (!area) {
LOG(("Thumbnail initialisation failed."));
return;
}
thumbnail_create(content, area,
(osspriteop_header *) (area + 1),
WIDTH / 2, HEIGHT / 2);
/* xosspriteop_save_sprite_file(osspriteop_NAME,
area, "thumbnail");*/
entry->sprite_area = area;
entry->bitmap = bitmap;
}
@ -205,13 +198,10 @@ void history_add(struct history *history, struct content *content, char *frag_id
void history_update(struct history *history, struct content *content)
{
if (!history || !history->current || !history->current->sprite_area)
if (!history || !history->current || !history->current->bitmap)
return;
thumbnail_create(content, history->current->sprite_area,
(osspriteop_header *)
(history->current->sprite_area + 1),
WIDTH / 2, HEIGHT / 2);
thumbnail_create(content, history->current->bitmap, NULL);
}
@ -248,7 +238,6 @@ void history_free_entry(struct history_entry *entry)
if (entry->frag_id)
free(entry->frag_id);
free(entry->title);
free(entry->sprite_area);
free(entry);
}
@ -412,59 +401,23 @@ void ro_gui_history_redraw_tree(struct history_entry *he,
os_plot(os_PLOT_SOLID | os_PLOT_BY, -WIDTH - 1, 0);
os_plot(os_PLOT_SOLID | os_PLOT_BY, 0, HEIGHT + 1);
if (he->sprite_area) {
osspriteop_area *area = he->sprite_area;
osspriteop_header *header = (osspriteop_header *)(area + 1);
osspriteop_trans_tab *table;
/* Because we're supporting people with OS3.1 we need to check if the
sprite we have is a legacy 256 colour one
*/
if (header->mode == (os_mode)tinct_SPRITE_MODE) {
/* We plot with no mask and no scaling as any EIG factors are
handled internally by Tinct
*/
_swix(Tinct_Plot, _IN(2) | _IN(3) | _IN(4) | _IN(7),
(char *)(header),
x0 + he->x * FULL_WIDTH + MARGIN,
y0 - he->y * FULL_HEIGHT - FULL_HEIGHT + MARGIN,
tinct_ERROR_DIFFUSE | tinct_BILINEAR_FILTER);
if (he->bitmap) {
if (bitmap_get_buffer(he->bitmap)) {
image_redraw(he->bitmap->sprite_area,
x0 + he->x * FULL_WIDTH + MARGIN,
y0 - he->y * FULL_HEIGHT - MARGIN,
he->bitmap->width, he->bitmap->height,
he->bitmap->width, he->bitmap->height,
0xffffff,
false, false, false,
IMAGE_PLOT_TINCT_OPAQUE);
} else {
unsigned int size;
os_factors factors;
xcolourtrans_generate_table_for_sprite(
area, (osspriteop_id)header,
colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE,
0, colourtrans_GIVEN_SPRITE, 0, 0, &size);
table = calloc(size, 1);
if (!table) {
LOG(("Insufficient memory for calloc"));
warn_user("NoMemory", 0);
} else {
xcolourtrans_generate_table_for_sprite(
area, (osspriteop_id)header,
colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE,
table, colourtrans_GIVEN_SPRITE, 0, 0, 0);
factors.xmul = 1;
factors.ymul = 1;
factors.xdiv = 1;
factors.ydiv = 1;
xosspriteop_put_sprite_scaled(osspriteop_PTR,
area, (osspriteop_id)header,
x0 + he->x * FULL_WIDTH + MARGIN,
y0 - he->y * FULL_HEIGHT - FULL_HEIGHT + MARGIN,
osspriteop_USE_MASK | osspriteop_USE_PALETTE,
&factors, table);
free(table);
}
url_store_add_thumbnail(he->url, NULL);
he->bitmap = NULL;
}
}
if (he == history_current->current)
wimp_set_font_colours(wimp_COLOUR_WHITE, wimp_COLOUR_RED);
else

View File

@ -8,6 +8,8 @@
#ifndef _NETSURF_RISCOS_IMAGE_H_
#define _NETSURF_RISCOS_IMAGE_H_
#include "oslib/osspriteop.h"
struct osspriteop_area;
typedef enum {

View File

@ -31,6 +31,7 @@
#include "netsurf/riscos/wimp.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
#include "netsurf/utils/utf8.h"
@ -1277,6 +1278,8 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
struct node *node;
os_error *error;
char url[80];
url_func_result res;
char *norm_url = NULL;
ro_gui_menu_get_window_details(owner, &g, &bw, &c, &t, &tree);
@ -1312,11 +1315,17 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
/* hotlist actions */
case HOTLIST_ADD_URL:
if ((!hotlist_tree) || (!c))
if ((!hotlist_tree) || (!c) || (!c->url))
return false;
res = url_normalize(c->url, &norm_url);
if (res != URL_FUNC_OK) {
warn_user("NoMemory", 0);
return false;
}
node = tree_create_URL_node(hotlist_tree->root,
c->title, c->url, ro_content_filetype(c),
c->title, norm_url, ro_content_filetype(c),
time(NULL), -1, 0);
free(norm_url);
if (node) {
tree_redraw_area(hotlist_tree,
node->box.x - NODE_INSTEP, 0,
@ -1325,6 +1334,7 @@ bool ro_gui_menu_handle_action(wimp_w owner, menu_action action,
false, true);
ro_gui_tree_scroll_visible(hotlist_tree,
&node->data);
ro_gui_hotlist_save();
}
return true;
case HOTLIST_SHOW:

View File

@ -24,7 +24,6 @@ extern char *option_theme;
extern char *option_language;
extern int option_fg_plot_style; /* tinct flagword */
extern int option_bg_plot_style; /* tinct flagword */
extern bool option_thumbnail_32bpp;
extern bool option_history_tooltip;
extern int option_scale;
extern int option_toolbar_status_width;
@ -60,6 +59,8 @@ extern char *option_font_default_bold;
extern char *option_font_default_bold_italic;
extern bool option_block_popups;
extern bool option_url_suggestion;
extern int option_image_memory_direct; /* -1 means auto-detect */
extern int option_image_memory_compressed; /* -1 means auto-detect */
#define EXTRA_OPTION_DEFINE \
bool option_use_mouse_gestures = false;\
@ -68,7 +69,6 @@ char *option_theme = 0;\
char *option_language = 0;\
int option_fg_plot_style = tinct_ERROR_DIFFUSE;\
int option_bg_plot_style = tinct_DITHER;\
bool option_thumbnail_32bpp = true;\
bool option_history_tooltip = true; \
int option_scale = 100; \
int option_toolbar_status_width = 5000; \
@ -100,7 +100,9 @@ char *option_font_cursive = 0; \
char *option_font_fantasy = 0; \
int option_font_default = CSS_FONT_FAMILY_SANS_SERIF; \
bool option_block_popups = false; \
bool option_url_suggestion = true;
bool option_url_suggestion = true; \
int option_image_memory_direct = -1; \
int option_image_memory_compressed = -1;
#define EXTRA_OPTION_TABLE \
{ "use_mouse_gestures", OPTION_BOOL, &option_use_mouse_gestures },\
@ -109,7 +111,6 @@ bool option_url_suggestion = true;
{ "language", OPTION_STRING, &option_language },\
{ "plot_fg_quality", OPTION_INTEGER, &option_fg_plot_style },\
{ "plot_bg_quality", OPTION_INTEGER, &option_bg_plot_style },\
{ "thumbnail_32bpp", OPTION_BOOL, &option_thumbnail_32bpp },\
{ "history_tooltip", OPTION_BOOL, &option_history_tooltip }, \
{ "scale", OPTION_INTEGER, &option_scale }, \
{ "toolbar_show_status", OPTION_BOOL, &option_toolbar_show_status }, \
@ -141,6 +142,8 @@ bool option_url_suggestion = true;
{ "font_fantasy", OPTION_STRING, &option_font_fantasy }, \
{ "font_default", OPTION_INTEGER, &option_font_default }, \
{ "block_popups", OPTION_BOOL, &option_block_popups }, \
{ "url_suggestion", OPTION_BOOL, &option_url_suggestion }
{ "url_suggestion", OPTION_BOOL, &option_url_suggestion }, \
{ "image_memory_direct", OPTION_INTEGER, &option_image_memory_direct }, \
{ "image_memory_compressed",OPTION_INTEGER, &option_image_memory_compressed }
#endif

View File

@ -347,7 +347,8 @@ bool ro_plot_disc(int x, int y, int radius, colour colour)
bool ro_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg)
{
return image_redraw(&bitmap->sprite_area,
bitmap_get_buffer(bitmap);
return image_redraw(bitmap->sprite_area,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2,
width, height,
@ -364,7 +365,8 @@ bool ro_plot_bitmap_tile(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bool repeat_x, bool repeat_y)
{
return image_redraw(&bitmap->sprite_area,
bitmap_get_buffer(bitmap);
return image_redraw(bitmap->sprite_area,
ro_plot_origin_x + x * 2,
ro_plot_origin_y - y * 2,
width, height,

View File

@ -630,6 +630,7 @@ bool ro_gui_save_complete(struct content *c, char *path)
osspriteop_header *sprite_header;
char *appname;
unsigned int index;
struct bitmap *bitmap;
/* Create dir */
error = xosfile_create_dir(path, 0);
@ -663,21 +664,26 @@ bool ro_gui_save_complete(struct content *c, char *path)
appname = strrchr(path, '.');
if (!appname)
appname = path;
area = thumbnail_initialise(34, 34, os_MODE8BPP90X90);
if (!area) {
warn_user("NoMemory", 0);
bitmap = bitmap_create(34, 34, false);
if (!bitmap) {
LOG(("Thumbnail initialisation failed."));
return false;
}
bitmap_set_opaque(bitmap, true);
thumbnail_create(c, bitmap, NULL);
area = thumbnail_convert_8bpp(bitmap);
bitmap_destroy(bitmap);
if (!area) {
LOG(("Thumbnail conversion failed."));
return false;
}
sprite_header = (osspriteop_header *)(area + 1);
memset(sprite_header->name, 0x00, 12);
strncpy(sprite_header->name, appname + 1, 12);
/* Paint gets confused with uppercase characters */
for (index = 0; index < 12; index++)
sprite_header->name[index] = tolower(sprite_header->name[index]);
thumbnail_create(c, area,
(osspriteop_header *) ((char *) area + 16),
34, 34);
error = xosspriteop_save_sprite_file(osspriteop_NAME, area, buf);
free(area);
if (error) {

View File

@ -1051,7 +1051,7 @@ bool draw_plot_bitmap(int x, int y, int width, int height,
drawfile_object *dro;
drawfile_sprite *ds;
sprite_length = ((osspriteop_header*)((char*)&bitmap->sprite_area+bitmap->sprite_area.first))->size;
sprite_length = ((osspriteop_header*)((char*)bitmap->sprite_area+bitmap->sprite_area->first))->size;
if ((dro = (drawfile_object *)drawbuf_claim(8 + 16 + sprite_length, DrawBuf_eBody)) == NULL)
return false;
@ -1065,7 +1065,7 @@ bool draw_plot_bitmap(int x, int y, int width, int height,
ds->bbox.x1 = (x + width) * 512;
ds->bbox.y1 = (draw_plot_origin_y - y) * 512;
memcpy((char*)ds+16, (char*)&bitmap->sprite_area+bitmap->sprite_area.first, (unsigned)sprite_length);
memcpy((char*)ds+16, (char*)bitmap->sprite_area+bitmap->sprite_area->first, (unsigned)sprite_length);
return true;
}

View File

@ -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;
osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL;
_kernel_oserror *error;
/* 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();
/* check if we have access to 32bpp sprites natively */
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;
/* 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 width The sprite width
* @param height The sprite height
* @param mode The preferred mode (0x301680b5 or os_MODE8BPP90X90)
* @return
* \param bitmap the bitmap to convert
* \return a sprite area containing an 8bpp sprite
*/
osspriteop_area* thumbnail_initialise(int width, int height, os_mode mode) {
unsigned int area_size;
unsigned int remaining_bytes;
osspriteop_area *sprite_area;
osspriteop_header *sprite_header;
char *sprite_image;
osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap) {
struct thumbnail_save_area *save_area;
osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL;
/* 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;
}
/* Try to get enough memory
*/
if ((sprite_area = (osspriteop_area *)malloc(area_size)) == NULL) {
LOG(("Insufficient memory to create thumbnail."));
sprite_area = thumbnail_create_8bpp(bitmap);
if (!sprite_area)
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");
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,
(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);
/* 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;
}
/* Return our sprite area
*/
_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;
}
/*
* 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.
/**
* Creates an 8bpp canvas.
*
* \param bitmap the bitmap to clone the size of
* \return a sprite area containing an 8bpp sprite
*/
osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap) {
unsigned int area_size;
osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL;
/* 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;
}
sprite_area->size = area_size;
sprite_area->sprite_count = 1;
sprite_area->first = 16;
sprite_area->used = area_size;
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, "bitmap");
sprite_header->left_bit = 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), 0);
return sprite_area;
}
/**
* 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);
}

View File

@ -3,6 +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 2005 Richard Wilson <info@tinct.net>
*/
/** \file
@ -10,7 +11,8 @@
*/
#include "oslib/osspriteop.h"
#include "netsurf/image/bitmap.h"
void thumbnail_create(struct content *content, osspriteop_area *area,
osspriteop_header *sprite, int width, int height);
osspriteop_area* thumbnail_initialise(int width, int height, os_mode mode);
bool thumbnail_create(struct content *content, struct bitmap *bitmap,
const char *url);
osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap);

View File

@ -2,7 +2,7 @@
* 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 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
* Copyright 2005 Richard Wilson <info@tinct.net>
*/
/** \file
@ -20,8 +20,12 @@
#include "oslib/osbyte.h"
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "netsurf/content/url_store.h"
#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/tree.h"
#include "netsurf/riscos/bitmap.h"
#include "netsurf/riscos/gui.h"
#include "netsurf/riscos/image.h"
#include "netsurf/riscos/menus.h"
#include "netsurf/riscos/theme.h"
#include "netsurf/riscos/tinct.h"
@ -38,6 +42,7 @@
static bool ro_gui_tree_initialise_sprite(const char *name, int number);
static void ro_gui_tree_launch_selected_node(struct node *node, bool all);
static bool ro_gui_tree_launch_node(struct node *node);
static void tree_handle_node_changed_callback(void *p);
/* an array of sprite addresses for Tinct */
static char *ro_gui_tree_sprites[2];
@ -61,6 +66,12 @@ static wimp_icon_create ro_gui_tree_edit_icon;
/* dragging information */
static char ro_gui_tree_drag_name[12];
/* callback update */
struct node_update {
struct tree *tree;
struct node *node;
};
/**
* Performs any initialisation for tree rendering
@ -181,6 +192,10 @@ void tree_draw_node_element(struct tree *tree, struct node_element *element) {
os_error *error;
int temp;
int toolbar_height = 0;
struct node_element *url_element;
struct bitmap *bitmap = NULL;
struct node_update *update;
char *frame;
assert(tree);
assert(element);
@ -265,6 +280,50 @@ void tree_draw_node_element(struct tree *tree, struct node_element *element) {
ro_gui_tree_icon.data.indirected_sprite.size =
strlen(element->sprite->name);
break;
case NODE_ELEMENT_THUMBNAIL:
url_element = tree_find_element(element->parent, TREE_ELEMENT_URL);
if (url_element)
bitmap = url_store_get_thumbnail(url_element->text);
if (bitmap) {
frame = bitmap_get_buffer(bitmap);
if (!frame)
url_store_add_thumbnail(url_element->text, NULL);
if ((!frame) || (element->box.width == 0)) {
update = calloc(sizeof(struct node_update), 1);
if (!update)
return;
update->tree = tree;
update->node = element->parent;
schedule(0, tree_handle_node_changed_callback,
update);
return;
}
image_redraw(bitmap->sprite_area,
ro_gui_tree_origin_x + element->box.x + 2,
ro_gui_tree_origin_y - element->box.y,
bitmap->width, bitmap->height,
bitmap->width, bitmap->height,
0xffffff,
false, false, false,
IMAGE_PLOT_TINCT_OPAQUE);
tree_draw_line(tree, element->box.x,
element->box.y,
element->box.width - 1,
0);
tree_draw_line(tree, element->box.x,
element->box.y,
0,
element->box.height - 3);
tree_draw_line(tree, element->box.x,
element->box.y + element->box.height - 3,
element->box.width - 1,
0);
tree_draw_line(tree, element->box.x + element->box.width - 1,
element->box.y,
0,
element->box.height - 3);
}
return;
}
error = xwimp_plot_icon(&ro_gui_tree_icon);
@ -276,6 +335,14 @@ void tree_draw_node_element(struct tree *tree, struct node_element *element) {
}
void tree_handle_node_changed_callback(void *p) {
struct node_update *update = p;
tree_handle_node_changed(update->tree, update->node, true, false);
free(update);
}
/**
* Draws an elements expansion icon
*
@ -342,6 +409,8 @@ void tree_recalculate_node_element(struct node_element *element) {
int sprite_width;
int sprite_height;
osspriteop_flags flags;
struct bitmap *bitmap = NULL;
struct node_element *url_element;
assert(element);
@ -384,6 +453,17 @@ void tree_recalculate_node_element(struct node_element *element) {
if (element->box.height < TREE_TEXT_HEIGHT)
element->box.height = TREE_TEXT_HEIGHT;
break;
case NODE_ELEMENT_THUMBNAIL:
url_element = tree_find_element(element->parent, TREE_ELEMENT_URL);
if (url_element)
bitmap = url_store_get_thumbnail(url_element->text);
if (bitmap) {
element->box.width = bitmap->width * 2 + 2;
element->box.height = bitmap->height * 2 + 4;
} else {
element->box.width = 0;
element->box.height = 0;
}
}
}
@ -502,7 +582,6 @@ void tree_update_URL_node(struct node *node) {
element->user_data);
element->text = strdup(buffer);
}
}

View File

@ -16,6 +16,7 @@
#include "oslib/osspriteop.h"
#include "oslib/wimp.h"
#include "netsurf/desktop/tree.h"
#include "netsurf/image/bitmap.h"
#define TREE_TEXT_HEIGHT 40
#define TREE_SPRITE_WIDTH 40 /* text plus sprite entries only */