summaryrefslogtreecommitdiff
path: root/frontends/riscos/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/riscos/image.c')
-rw-r--r--frontends/riscos/image.c230
1 files changed, 150 insertions, 80 deletions
diff --git a/frontends/riscos/image.c b/frontends/riscos/image.c
index 30cb30096..5c90b05ba 100644
--- a/frontends/riscos/image.c
+++ b/frontends/riscos/image.c
@@ -27,76 +27,9 @@
#include "riscos/image.h"
#include "riscos/gui.h"
+#include "riscos/wimp.h"
#include "riscos/tinct.h"
-static bool image_redraw_tinct(osspriteop_id header, int x, int y,
- int req_width, int req_height, int width, int height,
- colour background_colour, bool repeatx, bool repeaty,
- bool alpha, unsigned int tinct_options);
-static bool image_redraw_os(osspriteop_id header, int x, int y,
- int req_width, int req_height, int width, int height);
-
-/**
- * Plot an image at the given coordinates using the method specified
- *
- * \param area The sprite area containing the sprite
- * \param x Left edge of sprite
- * \param y Top edge of sprite
- * \param req_width The requested width of the sprite
- * \param req_height The requested height of the sprite
- * \param width The actual width of the sprite
- * \param height The actual height of the sprite
- * \param background_colour The background colour to blend to
- * \param repeatx Repeat the image in the x direction
- * \param repeaty Repeat the image in the y direction
- * \param background Use background image settings (otherwise foreground)
- * \param type The plot method to use
- * \return true on success, false otherwise
- */
-bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
- int req_height, int width, int height,
- colour background_colour,
- bool repeatx, bool repeaty, bool background, image_type type)
-{
- unsigned int tinct_options;
-
- /* failed decompression/loading can result in no image being present */
- if (!area)
- return false;
-
- osspriteop_id header = (osspriteop_id)
- ((char*) area + area->first);
- req_width *= 2;
- req_height *= 2;
- width *= 2;
- height *= 2;
- tinct_options = background ? nsoption_int(plot_bg_quality) :
- nsoption_int(plot_fg_quality);
- switch (type) {
- case IMAGE_PLOT_TINCT_ALPHA:
- return image_redraw_tinct(header, x, y,
- req_width, req_height,
- width, height,
- background_colour,
- repeatx, repeaty, true,
- tinct_options);
- case IMAGE_PLOT_TINCT_OPAQUE:
- return image_redraw_tinct(header, x, y,
- req_width, req_height,
- width, height,
- background_colour,
- repeatx, repeaty, false,
- tinct_options);
- case IMAGE_PLOT_OS:
- return image_redraw_os(header, x, y, req_width,
- req_height, width, height);
- default:
- break;
- }
-
- return false;
-}
-
/**
* Plot an image at the given coordinates using tinct
*
@@ -114,7 +47,7 @@ bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
* \param tinct_options The base option set to use
* \return true on success, false otherwise
*/
-bool image_redraw_tinct(osspriteop_id header, int x, int y,
+static bool image_redraw_tinct(osspriteop_id header, int x, int y,
int req_width, int req_height, int width, int height,
colour background_colour, bool repeatx, bool repeaty,
bool alpha, unsigned int tinct_options)
@@ -133,11 +66,11 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
if (alpha) {
error = _swix(Tinct_PlotScaledAlpha, _INR(2,7),
- header, x, y - req_height,
+ header, x, y,
req_width, req_height, tinct_options);
} else {
error = _swix(Tinct_PlotScaled, _INR(2,7),
- header, x, y - req_height,
+ header, x, y,
req_width, req_height, tinct_options);
}
@@ -150,7 +83,6 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
return true;
}
-
/**
* Plot an image at the given coordinates using os_spriteop
*
@@ -161,10 +93,11 @@ bool image_redraw_tinct(osspriteop_id header, int x, int y,
* \param req_height The requested height of the sprite
* \param width The actual width of the sprite
* \param height The actual height of the sprite
+ * \param tile Whether to tile the sprite
* \return true on success, false otherwise
*/
-bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
- int req_height, int width, int height)
+static bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
+ int req_height, int width, int height, bool tile)
{
int size;
os_factors f;
@@ -172,7 +105,7 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
os_error *error;
error = xcolourtrans_generate_table_for_sprite(
- (osspriteop_area *)0x100, header,
+ osspriteop_UNSPECIFIED, header,
os_CURRENT_MODE,
colourtrans_CURRENT_PALETTE,
0, colourtrans_GIVEN_SPRITE, 0, 0, &size);
@@ -192,7 +125,7 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
}
error = xcolourtrans_generate_table_for_sprite(
- (osspriteop_area *)0x100, header,
+ osspriteop_UNSPECIFIED, header,
os_CURRENT_MODE,
colourtrans_CURRENT_PALETTE,
table, colourtrans_GIVEN_SPRITE, 0, 0, 0);
@@ -210,10 +143,15 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
f.xdiv = width;
f.ydiv = height;
- error = xosspriteop_put_sprite_scaled(osspriteop_PTR,
- (osspriteop_area *)0x100, header,
- x, (int)(y - req_height),
- 8, &f, table);
+ if (tile) {
+ error = xosspriteop_plot_tiled_sprite(osspriteop_PTR,
+ osspriteop_UNSPECIFIED, header, x, y,
+ osspriteop_USE_MASK, &f, table);
+ } else {
+ error = xosspriteop_put_sprite_scaled(osspriteop_PTR,
+ osspriteop_UNSPECIFIED, header, x, y,
+ osspriteop_USE_MASK, &f, table);
+ }
if (error) {
NSLOG(netsurf, INFO,
"xosspriteop_put_sprite_scaled: 0x%x: %s",
@@ -227,3 +165,135 @@ bool image_redraw_os(osspriteop_id header, int x, int y, int req_width,
return true;
}
+
+/**
+ * Override a sprite's mode.
+ *
+ * Only replaces mode if existing mode matches \ref old.
+ *
+ * \param[in] area The sprite area containing the sprite.
+ * \param[in] type Requested plot mode.
+ * \param[in] old Existing sprite mode to check for.
+ * \param[in] new Sprite mode to set if existing mode is expected.
+ */
+static inline void image__override_sprite_mode(
+ osspriteop_area *area,
+ image_type type,
+ os_mode old,
+ os_mode new)
+{
+ osspriteop_header *sprite = (osspriteop_header *)(area + 1);
+
+ if (sprite->mode == old && type == IMAGE_PLOT_TINCT_ALPHA) {
+ sprite->mode = new;
+ }
+}
+
+/**
+ * Plot an image at the given coordinates using the method specified
+ *
+ * \param area The sprite area containing the sprite
+ * \param x Left edge of sprite
+ * \param y Top edge of sprite
+ * \param req_width The requested width of the sprite
+ * \param req_height The requested height of the sprite
+ * \param width The actual width of the sprite
+ * \param height The actual height of the sprite
+ * \param background_colour The background colour to blend to
+ * \param repeatx Repeat the image in the x direction
+ * \param repeaty Repeat the image in the y direction
+ * \param background Use background image settings (otherwise foreground)
+ * \param type The plot method to use
+ * \return true on success, false otherwise
+ */
+bool image_redraw(osspriteop_area *area, int x, int y, int req_width,
+ int req_height, int width, int height,
+ colour background_colour,
+ bool repeatx, bool repeaty, bool background, image_type type)
+{
+ image_type used_type = type;
+ unsigned int tinct_options;
+ bool tinct_avoid = false;
+ bool res = false;
+
+ /* failed decompression/loading can result in no image being present */
+ if (!area)
+ return false;
+
+ osspriteop_id header = (osspriteop_id)
+ ((char*) area + area->first);
+
+ req_width *= 2;
+ req_height *= 2;
+ width *= 2;
+ height *= 2;
+ y -= req_height;
+
+ tinct_options = background ? nsoption_int(plot_bg_quality) :
+ nsoption_int(plot_fg_quality);
+
+ if (os_alpha_sprite_supported) {
+ /* Ideally Tinct would be updated to understand that modern OS
+ * versions can cope with alpha channels, and we could continue
+ * to pass to Tinct. The main drawback of fully avoiding Tinct
+ * is that we lose the optimisation for tiling tiny bitmaps.
+ */
+ if (tinct_options & tinct_USE_OS_SPRITE_OP) {
+ used_type = IMAGE_PLOT_OS;
+ tinct_avoid = true;
+ }
+ }
+
+ if (tinct_avoid) {
+ int xeig;
+ int yeig;
+
+ if (ro_gui_wimp_read_eig_factors(os_CURRENT_MODE,
+ &xeig, &yeig)) {
+
+ req_width = (req_width / 2) * (4 >> xeig);
+ req_height = (req_height / 2) * (4 >> yeig);
+ }
+ }
+
+ switch (used_type) {
+ case IMAGE_PLOT_TINCT_ALPHA:
+ res = image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, true,
+ tinct_options);
+ break;
+
+ case IMAGE_PLOT_TINCT_OPAQUE:
+ res = image_redraw_tinct(header, x, y,
+ req_width, req_height,
+ width, height,
+ background_colour,
+ repeatx, repeaty, false,
+ tinct_options);
+ break;
+
+ case IMAGE_PLOT_OS:
+ if (tinct_avoid) {
+ image__override_sprite_mode(area, type,
+ tinct_SPRITE_MODE,
+ alpha_SPRITE_MODE);
+ }
+ res = image_redraw_os(header, x, y, req_width,
+ req_height, width, height,
+ repeatx | repeaty);
+ if (tinct_avoid) {
+ image__override_sprite_mode(area, type,
+ alpha_SPRITE_MODE,
+ tinct_SPRITE_MODE);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return res;
+}