summaryrefslogtreecommitdiff
path: root/riscos
diff options
context:
space:
mode:
authorAdrian Lees <adrian@aemulor.com>2006-03-24 03:44:37 +0000
committerAdrian Lees <adrian@aemulor.com>2006-03-24 03:44:37 +0000
commit4b03028b5111ca43dc5028c4aee471a83dbae58f (patch)
tree8c815dc593b719817a2d5c4a59e3ece5b926e289 /riscos
parent4c7a6f4f5c92c35cf48cb4816bd386b9b2985221 (diff)
downloadnetsurf-4b03028b5111ca43dc5028c4aee471a83dbae58f.tar.gz
netsurf-4b03028b5111ca43dc5028c4aee471a83dbae58f.tar.bz2
[project @ 2006-03-24 03:44:33 by adrianl]
Use thumbnails for iconised windows svn path=/import/netsurf/; revision=2157
Diffstat (limited to 'riscos')
-rw-r--r--riscos/bitmap.c102
-rw-r--r--riscos/bitmap.h2
-rw-r--r--riscos/gui.c25
-rw-r--r--riscos/gui.h3
-rw-r--r--riscos/print.c6
-rw-r--r--riscos/save.c2
-rw-r--r--riscos/sprite.c34
-rw-r--r--riscos/sprite.h3
-rw-r--r--riscos/thumbnail.c38
-rw-r--r--riscos/window.c130
10 files changed, 338 insertions, 7 deletions
diff --git a/riscos/bitmap.c b/riscos/bitmap.c
index f9c66bb34..b0d245fd0 100644
--- a/riscos/bitmap.c
+++ b/riscos/bitmap.c
@@ -25,10 +25,14 @@
#include "netsurf/riscos/filename.h"
#include "netsurf/riscos/image.h"
#include "netsurf/riscos/options.h"
+#include "netsurf/riscos/sprite.h"
#include "netsurf/riscos/tinct.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/utils.h"
+/** Colour in the overlay sprite that allows the bitmap to show through */
+#define OVERLAY_KEY 0xff0000U
+
#define MAINTENANCE_THRESHOLD 32
/** The head of the bitmap list
@@ -223,6 +227,92 @@ struct bitmap *bitmap_create_file(char *file)
/**
+ * Overlay a sprite onto the given bitmap
+ *
+ * \param bitmap bitmap object
+ * \param s 8bpp sprite to be overlayed onto bitmap
+ */
+
+void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s)
+{
+ const os_colour *palette;
+ const byte *sp, *mp;
+ bool masked = false;
+ bool alpha = false;
+ os_error *error;
+ int dp_offset;
+ int sp_offset;
+ unsigned *dp;
+ int x, y;
+ int w, h;
+
+ assert(sprite_bpp(s) == 8);
+
+ if ((unsigned)s->mode & 0x80000000U)
+ alpha = true;
+
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id)s,
+ &w, &h, NULL, NULL);
+ if (error) {
+ LOG(("xosspriteop_read_sprite_info: 0x%x:%s",
+ error->errnum, error->errmess));
+ return;
+ }
+
+ sp_offset = ((s->width + 1) * 4) - w;
+
+ if (w > bitmap->width) w = bitmap->width;
+ if (h > bitmap->height) h = bitmap->height;
+
+ dp_offset = bitmap_get_rowstride(bitmap)/4;
+
+ dp = (unsigned*)bitmap_get_buffer(bitmap);
+ sp = (byte*)s + s->image;
+ mp = (byte*)s + s->mask;
+
+ sp += s->left_bit / 8;
+ mp += s->left_bit / 8;
+
+ if (s->image > sizeof(*s))
+ palette = (os_colour*)(s + 1);
+ else
+ palette = default_palette8;
+
+ if (s->mask != s->image) {
+ masked = true;
+ bitmap_set_opaque(bitmap, false);
+ }
+
+ /* (partially-)transparent pixels in the overlayed sprite retain
+ their transparency in the output bitmap; opaque sprite pixels
+ are also propagated to the bitmap, except those which are the
+ OVERLAY_KEY colour which allow the original bitmap contents to
+ show through */
+
+ for(y = 0; y < h; y++) {
+ unsigned *sdp = dp;
+ for(x = 0; x < w; x++) {
+ os_colour d = ((unsigned)palette[(*sp++) << 1]) >> 8;
+ if (d == OVERLAY_KEY) d = *dp;
+ if (masked) {
+ if (alpha)
+ d |= ((*mp << 24) ^ 0xff000000U);
+ else if (*mp)
+ d |= 0xff000000U;
+ }
+ *dp++ = d;
+ mp++;
+ }
+ dp = sdp + dp_offset;
+ sp += sp_offset;
+ mp += sp_offset;
+ }
+}
+
+
+/**
* Initialise a bitmaps sprite area.
*
* \param bitmap the bitmap to initialise
@@ -852,3 +942,15 @@ void bitmap_delete_file(struct bitmap *bitmap)
ro_filename_release(bitmap->filename);
bitmap->filename[0] = 0;
}
+
+
+int bitmap_get_width(struct bitmap *bitmap)
+{
+ return bitmap->width;
+}
+
+
+int bitmap_get_height(struct bitmap *bitmap)
+{
+ return bitmap->height;
+}
diff --git a/riscos/bitmap.h b/riscos/bitmap.h
index a113d9b1b..ac196661a 100644
--- a/riscos/bitmap.h
+++ b/riscos/bitmap.h
@@ -32,6 +32,7 @@ struct bitmap {
};
struct bitmap *bitmap_create_file(char *file);
+void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s);
void bitmap_initialise_memory(void);
void bitmap_quit(void);
void bitmap_maintain(void);
@@ -52,5 +53,4 @@ extern unsigned int bitmap_direct_size;
*/
extern unsigned int bitmap_compressed_size;
-
#endif
diff --git a/riscos/gui.c b/riscos/gui.c
index b5ef080bf..d01ee6dfb 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -174,7 +174,7 @@ static struct {
} prev_sigs;
/** Accepted wimp user messages. */
-static wimp_MESSAGE_LIST(40) task_messages = { {
+static wimp_MESSAGE_LIST(41) task_messages = { {
message_HELP_REQUEST,
message_DATA_SAVE,
message_DATA_SAVE_ACK,
@@ -185,6 +185,7 @@ static wimp_MESSAGE_LIST(40) task_messages = { {
message_SAVE_DESKTOP,
message_MENU_WARNING,
message_MENUS_DELETED,
+ message_WINDOW_INFO,
message_MODE_CHANGE,
message_CLAIM_ENTITY,
message_DATA_REQUEST,
@@ -261,6 +262,7 @@ static void ro_msg_dataopen(wimp_message *message);
static void ro_gui_get_screen_properties(void);
static void ro_msg_prequit(wimp_message *message);
static void ro_msg_save_desktop(wimp_message *message);
+static void ro_msg_window_info(wimp_message *message);
static void ro_gui_view_source_bounce(wimp_message *message);
@@ -410,6 +412,8 @@ void gui_init(int argc, char** argv)
ro_gui_selection_dragging);
ro_message_register_route(message_DRAG_CLAIM,
ro_gui_selection_drag_claim);
+ ro_message_register_route(message_WINDOW_INFO,
+ ro_msg_window_info);
/* end of handler registration */
nsfont_init();
@@ -1962,6 +1966,25 @@ void ro_msg_save_desktop(wimp_message *message)
/**
+ * Handle WindowInfo message (part of the iconising protocol)
+ *
+ * \param message WindowInfo message from the Iconiser
+ */
+
+void ro_msg_window_info(wimp_message *message)
+{
+ wimp_full_message_window_info *wi;
+ struct gui_window *g;
+
+ wi = (wimp_full_message_window_info*)message;
+ g = ro_gui_window_lookup(wi->w);
+
+ /* ic_<task name> will suffice for our other windows */
+ if (g) ro_gui_window_iconise(g, wi);
+}
+
+
+/**
* Convert a RISC OS pathname to a file: URL.
*
* \param path RISC OS pathname
diff --git a/riscos/gui.h b/riscos/gui.h
index c6266bc9a..7eb55b746 100644
--- a/riscos/gui.h
+++ b/riscos/gui.h
@@ -80,6 +80,8 @@ struct gui_window {
int throbber; /**< Current frame of throbber animation. */
int throbtime; /**< Time of last throbber frame. */
+ int iconise_icon; /**< ID number of icon when window is iconised */
+
/** Options. */
struct {
float scale; /**< Scale, 1.0 = 100%. */
@@ -161,6 +163,7 @@ bool ro_gui_shift_pressed(void);
bool ro_gui_ctrl_pressed(void);
void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag);
void ro_gui_window_set_scale(struct gui_window *g, float scale);
+void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *wi);
/* in history.c */
void ro_gui_history_init(void);
diff --git a/riscos/print.c b/riscos/print.c
index 21b3a511b..724576aff 100644
--- a/riscos/print.c
+++ b/riscos/print.c
@@ -99,6 +99,8 @@ static bool print_fonts_plot_text(int x, int y, struct css_style *style,
const char *text, size_t length, colour bg, colour c);
static bool print_fonts_plot_disc(int x, int y, int radius, colour c,
bool filled);
+static bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
+ colour c);
static bool print_fonts_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg);
static bool print_fonts_plot_bitmap_tile(int x, int y, int width, int height,
@@ -123,6 +125,7 @@ static const struct plotter_table print_fonts_plotters = {
print_fonts_plot_clip,
print_fonts_plot_text,
print_fonts_plot_disc,
+ print_fonts_plot_arc,
print_fonts_plot_bitmap,
print_fonts_plot_bitmap_tile,
print_fonts_plot_group_start,
@@ -811,6 +814,9 @@ bool print_fonts_plot_clip(int clip_x0, int clip_y0,
int clip_x1, int clip_y1) { return true; }
bool print_fonts_plot_disc(int x, int y, int radius, colour colour, bool filled)
{ return true; }
+bool print_fonts_plot_arc(int x, int y, int radius, int angle1, int angle2,
+ colour c)
+ { return true; }
bool print_fonts_plot_bitmap(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg) { return true; }
bool print_fonts_plot_bitmap_tile(int x, int y, int width, int height,
diff --git a/riscos/save.c b/riscos/save.c
index 2fe3c59eb..67a860ee1 100644
--- a/riscos/save.c
+++ b/riscos/save.c
@@ -1033,7 +1033,7 @@ bool ro_gui_save_create_thumbnail(struct content *c, const char *name)
}
sprite_header = (osspriteop_header *)(area + 1);
- memcpy(sprite_header->name, name, 12);
+ strncpy(sprite_header->name, name, 12);
/* we can't resize the saveas sprite area because it may move and we have
no elegant way to update the window definition on all OS versions */
diff --git a/riscos/sprite.c b/riscos/sprite.c
index 27bc4f8af..941e224f0 100644
--- a/riscos/sprite.c
+++ b/riscos/sprite.c
@@ -110,3 +110,37 @@ bool sprite_redraw(struct content *c, int x, int y,
}
#endif
+
+
+/**
+ * Returns the bit depth of a sprite
+ *
+ * \param s sprite
+ * \return depth in bpp
+ */
+
+byte sprite_bpp(const osspriteop_header *s)
+{
+ /* bit 31 indicates the presence of a full alpha channel rather than a binary mask */
+ int type = ((unsigned)s->mode >> osspriteop_TYPE_SHIFT) & 15;
+ byte bpp = 0;
+
+ switch (type) {
+ case osspriteop_TYPE_OLD:
+ {
+ bits psr;
+ int val;
+ if (!xos_read_mode_variable(s->mode, os_MODEVAR_LOG2_BPP, &val, &psr) &&
+ !(psr & _C)) bpp = 1 << val;
+ }
+ break;
+ case osspriteop_TYPE1BPP: bpp = 1; break;
+ case osspriteop_TYPE2BPP: bpp = 2; break;
+ case osspriteop_TYPE4BPP: bpp = 4; break;
+ case osspriteop_TYPE8BPP: bpp = 8; break;
+ case osspriteop_TYPE16BPP: bpp = 16; break;
+ case osspriteop_TYPE32BPP: bpp = 32; break;
+ case osspriteop_TYPE_CMYK: bpp = 32; break;
+ }
+ return bpp;
+}
diff --git a/riscos/sprite.h b/riscos/sprite.h
index f360d2bb0..3e9c836bb 100644
--- a/riscos/sprite.h
+++ b/riscos/sprite.h
@@ -13,6 +13,7 @@
#define _NETSURF_RISCOS_SPRITE_H_
#include <stdbool.h>
+#include "oslib/osspriteop.h"
struct content;
@@ -27,4 +28,6 @@ bool sprite_redraw(struct content *c, int x, int y,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, colour background_colour);
+byte sprite_bpp(const osspriteop_header *s);
+
#endif
diff --git a/riscos/thumbnail.c b/riscos/thumbnail.c
index 8c5351cac..ed240fd28 100644
--- a/riscos/thumbnail.c
+++ b/riscos/thumbnail.c
@@ -156,7 +156,7 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap)
osspriteop_area *sprite_area = NULL;
osspriteop_header *sprite_header = NULL;
- sprite_area = thumbnail_create_8bpp(bitmap);
+ sprite_area = thumbnail_create_8bpp(bitmap);
if (!sprite_area)
return NULL;
sprite_header = (osspriteop_header *)(sprite_area + 1);
@@ -175,6 +175,30 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap)
tinct_ERROR_DIFFUSE);
thumbnail_restore_output(save_area);
+ if (sprite_header->image != sprite_header->mask) {
+ /* build the sprite mask from the alpha channel */
+ unsigned *dp = (unsigned*)bitmap_get_buffer(bitmap);
+ int h = bitmap_get_width(bitmap);
+ int w = bitmap_get_height(bitmap);
+ int dp_offset = bitmap_get_rowstride(bitmap)/4 - w;
+ int mp_offset = ((sprite_header->width + 1) * 4) - w;
+ byte *mp = (byte*)sprite_header + sprite_header->mask;
+ bool alpha = ((unsigned)sprite_header->mode & 0x80000000U) != 0;
+
+ while (h-- > 0) {
+ int x = 0;
+ for(x = 0; x < w; x++) {
+ unsigned d = *dp++;
+ if (alpha)
+ *mp++ = (d >> 24) ^ 0xff;
+ else
+ *mp++ = (d < 0xff000000U) ? 0 : 0xff;
+ }
+ dp += dp_offset;
+ mp += mp_offset;
+ }
+ }
+
return sprite_area;
}
@@ -187,15 +211,20 @@ osspriteop_area *thumbnail_convert_8bpp(struct bitmap *bitmap)
*/
osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap)
{
- unsigned int area_size;
- osspriteop_area *sprite_area = NULL;
+ unsigned image_size = ((bitmap->width + 3) & ~3) * bitmap->height;
+ bool opaque = bitmap_get_opaque(bitmap);
osspriteop_header *sprite_header = NULL;
+ osspriteop_area *sprite_area = NULL;
+ unsigned area_size;
/* clone the sprite */
area_size = sizeof(osspriteop_area) +
sizeof(osspriteop_header) +
- ((bitmap->width + 3) & ~3) * bitmap->height +
+ image_size +
2048;
+
+ if (!opaque) area_size += image_size;
+
sprite_area = (osspriteop_area *)malloc(area_size);
if (!sprite_area) {
LOG(("no memory for malloc()"));
@@ -216,6 +245,7 @@ osspriteop_area *thumbnail_create_8bpp(struct bitmap *bitmap)
sprite_header->width = ((bitmap->width + 3) >> 2) - 1;
sprite_header->image = sizeof(osspriteop_header) + 2048;
sprite_header->mask = sizeof(osspriteop_header) + 2048;
+ if (!opaque) sprite_header->mask += image_size;
/* create the palette. we don't read the necessary size like
* we really should as we know it's going to have 256 entries
diff --git a/riscos/window.c b/riscos/window.c
index 26e3be4e3..cb66962df 100644
--- a/riscos/window.c
+++ b/riscos/window.c
@@ -17,6 +17,7 @@
#include <assert.h>
#include <ctype.h>
#include <math.h>
+#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
@@ -37,6 +38,7 @@
#include "netsurf/desktop/gui.h"
#include "netsurf/render/box.h"
#include "netsurf/render/form.h"
+#include "netsurf/riscos/bitmap.h"
#include "netsurf/riscos/buffer.h"
#include "netsurf/riscos/dialog.h"
#include "netsurf/riscos/global_history.h"
@@ -61,6 +63,10 @@
#define SCROLL_VISIBLE_PADDING 32
+/** Remembers which iconised sprite numbers are in use */
+static bool iconise_used[64];
+static int iconise_next = 0;
+
/** List of all browser windows. */
static struct gui_window *window_list = 0;
/** GUI window which is being redrawn. Valid only during redraw. */
@@ -112,6 +118,7 @@ struct gui_window *gui_create_browser_window(struct browser_window *bw,
strcpy(g->title, "NetSurf");
g->throbber = 0;
g->throbtime = 0;
+ g->iconise_icon = -1;
/* Set the window position
*/
@@ -1173,6 +1180,12 @@ void ro_gui_window_open(struct gui_window *g, wimp_open *open)
int key_down = 0;
int inset = 0;
+ if (open->next == wimp_TOP && g->iconise_icon >= 0) {
+ /* window is no longer iconised, release its sprite number */
+ iconise_used[g->iconise_icon] = false;
+ g->iconise_icon = -1;
+ }
+
content = g->bw->current_content;
/* check for toggle to full size so we can force to full height for short contents */
@@ -2931,3 +2944,120 @@ bool ro_gui_window_import_text(struct gui_window *g, const char *filename,
free(utf8_buf);
return true;
}
+
+
+/**
+ * Window is being iconised. Create a suitable thumbnail sprite
+ * (which, sadly, must be in the Wimp sprite pool), and return
+ * the sprite name and truncated title to the iconiser
+ *
+ * \param g the gui window being iconised
+ * \param wi the WindowInfo message from the iconiser
+ */
+
+void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *wi)
+{
+ /* sadly there is no 'legal' way to get the sprite into
+ the Wimp sprite pool other than via a filing system */
+ const char *temp_fname = "Pipe:$._tmpfile";
+ struct browser_window *bw = g->bw;
+ osspriteop_header *overlay = NULL;
+ osspriteop_header *sprite_header;
+ struct bitmap *bitmap;
+ osspriteop_area *area;
+ int w = 34, h = 34;
+ struct content *c;
+ os_error *error;
+ int len, id;
+
+ assert(bw);
+
+ c = bw->current_content;
+ if (!c) return;
+
+ /* if an overlay sprite is defined, locate it and gets its dimensions
+ so that we can produce a thumbnail with the same dimensions */
+ if (!ro_gui_wimp_get_sprite("ic_netsfxx", &overlay)) {
+ error = xosspriteop_read_sprite_info(osspriteop_PTR,
+ (osspriteop_area *)0x100,
+ (osspriteop_id)overlay, &w, &h, NULL, NULL);
+ if (error) {
+ LOG(("xosspriteop_read_sprite_info: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ overlay = NULL;
+ }
+ else if (sprite_bpp(overlay) != 8) {
+ LOG(("overlay sprite is not 8bpp"));
+ overlay = NULL;
+ }
+ }
+
+ /* create the thumbnail sprite */
+ bitmap = bitmap_create(w, h, BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY);
+ if (!bitmap) {
+ LOG(("Thumbnail initialisation failed."));
+ return;
+ }
+ thumbnail_create(c, bitmap, NULL);
+ if (overlay) bitmap_overlay_sprite(bitmap, overlay);
+
+ area = thumbnail_convert_8bpp(bitmap);
+ bitmap_destroy(bitmap);
+ if (!area) {
+ LOG(("Thumbnail conversion failed."));
+ return;
+ }
+
+ /* choose a suitable sprite name */
+ id = 0;
+ while (iconise_used[id])
+ if (++id >= NOF_ELEMENTS(iconise_used)) {
+ id = iconise_next;
+ if (++iconise_next >= NOF_ELEMENTS(iconise_used))
+ iconise_next = 0;
+ break;
+ }
+
+ sprite_header = (osspriteop_header *)(area + 1);
+ len = sprintf(sprite_header->name, "ic_netsf%.2d", id);
+
+ error = xosspriteop_save_sprite_file(osspriteop_USER_AREA,
+ area, temp_fname);
+ if (error) {
+ LOG(("xosspriteop_save_sprite_file: 0x%x:%s",
+ error->errnum, error->errmess));
+ warn_user("MiscError", error->errmess);
+ free(area);
+ return;
+ }
+
+ error = xwimpspriteop_merge_sprite_file(temp_fname);
+ if (error) {
+ LOG(("xwimpspriteop_merge_sprite_file: 0x%x:%s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ remove(temp_fname);
+ free(area);
+ return;
+ }
+
+ memcpy(wi->sprite_name, sprite_header->name + 3, len - 2); /* inc NUL */
+ strncpy(wi->title, g->title, sizeof(wi->title));
+ wi->title[sizeof(wi->title) - 1] = '\0';
+
+ wi->size = sizeof(wimp_full_message_window_info);
+ wi->your_ref = wi->my_ref;
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)wi, wi->sender);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x:%s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ else {
+ g->iconise_icon = id;
+ iconise_used[id] = true;
+ }
+
+ free(area);
+}