diff options
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/knockout.c | 765 | ||||
-rw-r--r-- | desktop/knockout.h | 19 | ||||
-rw-r--r-- | desktop/options.c | 3 | ||||
-rw-r--r-- | desktop/options.h | 1 |
4 files changed, 788 insertions, 0 deletions
diff --git a/desktop/knockout.c b/desktop/knockout.c new file mode 100644 index 000000000..89ef58bc3 --- /dev/null +++ b/desktop/knockout.c @@ -0,0 +1,765 @@ +/* + * 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 2006 Richard Wilson <info@tinct.net> + */ + +/** \file + * Knockout rendering (implementation). + */ + +#include <assert.h> +#include <string.h> +#include "netsurf/desktop/knockout.h" +#include "netsurf/desktop/plotters.h" +#include "netsurf/image/bitmap.h" +#include "netsurf/utils/log.h" + + +#define KNOCKOUT_BOXES 512 /* 28 bytes each */ +#define KNOCKOUT_ENTRIES 4096 /* 40 bytes each */ +#define KNOCKOUT_POLYGONS 512 /* 4 bytes each */ + +struct knockout_box; +struct knockout_entry; + +static void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *box); +static bool knockout_plot_fill_recursive(struct knockout_box *box, colour c); +static bool knockout_plot_bitmap_tile_recursive(struct knockout_box *box, + struct knockout_entry *entry); + +static bool knockout_plot_clg(colour c); +static bool knockout_plot_rectangle(int x0, int y0, int width, int height, + int line_width, colour c, bool dotted, bool dashed); +static bool knockout_plot_line(int x0, int y0, int x1, int y1, int width, + colour c, bool dotted, bool dashed); +static bool knockout_plot_polygon(int *p, unsigned int n, colour fill); +static bool knockout_plot_fill(int x0, int y0, int x1, int y1, colour c); +static bool knockout_plot_clip(int clip_x0, int clip_y0, + int clip_x1, int clip_y1); +static bool knockout_plot_text(int x, int y, struct css_style *style, + const char *text, size_t length, colour bg, colour c); +static bool knockout_plot_disc(int x, int y, int radius, colour colour, bool filled); +static bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, + colour c); +static bool knockout_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg); +static bool knockout_plot_bitmap_tile(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bool repeat_x, bool repeat_y); +static bool knockout_plot_group_start(const char *name); +static bool knockout_plot_group_end(void); + + +struct knockout_entry knockout_entries[KNOCKOUT_ENTRIES]; +struct knockout_box knockout_boxes[KNOCKOUT_BOXES]; +int knockout_polygons[KNOCKOUT_POLYGONS]; +int knockout_entry_cur = 0; +int knockout_box_cur = 0; +int knockout_polygon_cur = 0; +struct knockout_box *knockout_list = NULL; + +struct plotter_table real_plot; + +int clip_x0_cur; +int clip_y0_cur; +int clip_x1_cur; +int clip_y1_cur; + + +const struct plotter_table knockout_plotters = { + knockout_plot_clg, + knockout_plot_rectangle, + knockout_plot_line, + knockout_plot_polygon, + knockout_plot_fill, + knockout_plot_clip, + knockout_plot_text, + knockout_plot_disc, + knockout_plot_arc, + knockout_plot_bitmap, + knockout_plot_bitmap_tile, + knockout_plot_group_start, + knockout_plot_group_end +}; + + +typedef enum { + KNOCKOUT_PLOT_CLG, /* translated to _FILL */ + KNOCKOUT_PLOT_RECTANGLE, + KNOCKOUT_PLOT_LINE, + KNOCKOUT_PLOT_POLYGON, + KNOCKOUT_PLOT_FILL, /* knockout, knocked out */ + KNOCKOUT_PLOT_CLIP, + KNOCKOUT_PLOT_TEXT, + KNOCKOUT_PLOT_DISC, + KNOCKOUT_PLOT_ARC, + KNOCKOUT_PLOT_BITMAP, /* knockout */ + KNOCKOUT_PLOT_BITMAP_TILE, /* knockout, knocked out */ + KNOCKOUT_PLOT_GROUP_START, + KNOCKOUT_PLOT_GROUP_END, +} knockout_type; + + +struct knockout_box { + struct { + int x0; + int y0; + int x1; + int y1; + } bbox; + bool deleted; /* box has been totally knocked out */ + struct knockout_box *child; + struct knockout_box *next; +}; + + +struct knockout_entry { + knockout_type type; + struct knockout_box *box; /* relating series of knockout clips */ + union { + struct { + colour c; + } clg; + struct { + int x0; + int y0; + int width; + int height; + int line_width; + colour c; + bool dotted; + bool dashed; + } rectangle; + struct { + int x0; + int y0; + int x1; + int y1; + int width; + colour c; + bool dotted; + bool dashed; + } line; + struct { + int *p; + unsigned int n; + colour fill; + } polygon; + struct { + int x0; + int y0; + int x1; + int y1; + colour c; + } fill; + struct { + int x0; + int y0; + int x1; + int y1; + } clip; + struct { + int x; + int y; + struct css_style *style; + const char *text; + size_t length; + colour bg; + colour c; + } text; + struct { + int x; + int y; + int radius; + colour colour; + bool filled; + } disc; + struct { + int x; + int y; + int radius; + int angle1; + int angle2; + colour c; + } arc; + struct { + int x; + int y; + int width; + int height; + struct bitmap *bitmap; + colour bg; + } bitmap; + struct { + int x; + int y; + int width; + int height; + struct bitmap *bitmap; + colour bg; + bool repeat_x; + bool repeat_y; + } bitmap_tile; + struct { + const char *name; + } group_start; + } data; +}; + + +/** + * Start a knockout plotting session + * + * \param plotter the plotter to use + * \return true on success, false otherwise + */ +bool knockout_plot_start(struct plotter_table *plotter) +{ + /* end any previous sessions */ + if (knockout_entry_cur > 0) + knockout_plot_end(); + + /* take over the plotter */ + real_plot = *plotter; + plot = knockout_plotters; + return true; +} + + +/** + * End a knockout plotting session + * + * \return true on success, false otherwise + */ +bool knockout_plot_end(void) +{ + int i; + bool success = true; + struct knockout_box *box; + + /* release our plotter */ + plot = real_plot; + + for (i = 0; i < knockout_entry_cur; i++) { + switch (knockout_entries[i].type) { + case KNOCKOUT_PLOT_CLG: + success &= plot.clg( + knockout_entries[i].data.clg.c); + break; + case KNOCKOUT_PLOT_RECTANGLE: + success &= plot.rectangle( + knockout_entries[i].data.rectangle.x0, + knockout_entries[i].data.rectangle.y0, + knockout_entries[i].data.rectangle.width, + knockout_entries[i].data.rectangle.height, + knockout_entries[i].data.rectangle.line_width, + knockout_entries[i].data.rectangle.c, + knockout_entries[i].data.rectangle.dotted, + knockout_entries[i].data.rectangle.dashed); + break; + case KNOCKOUT_PLOT_LINE: + success &= plot.line( + knockout_entries[i].data.line.x0, + knockout_entries[i].data.line.y0, + knockout_entries[i].data.line.x1, + knockout_entries[i].data.line.y1, + knockout_entries[i].data.line.width, + knockout_entries[i].data.line.c, + knockout_entries[i].data.line.dotted, + knockout_entries[i].data.line.dashed); + break; + case KNOCKOUT_PLOT_POLYGON: + success &= plot.polygon( + knockout_entries[i].data.polygon.p, + knockout_entries[i].data.polygon.n, + knockout_entries[i].data.polygon.fill); + break; + case KNOCKOUT_PLOT_FILL: + box = knockout_entries[i].box->child; + if (box) + success &= knockout_plot_fill_recursive(box, + knockout_entries[i].data.fill.c); + else if (!knockout_entries[i].box->deleted) + success &= plot.fill( + knockout_entries[i].data.fill.x0, + knockout_entries[i].data.fill.y0, + knockout_entries[i].data.fill.x1, + knockout_entries[i].data.fill.y1, + knockout_entries[i].data.fill.c); + break; + case KNOCKOUT_PLOT_CLIP: + success &= plot.clip( + knockout_entries[i].data.clip.x0, + knockout_entries[i].data.clip.y0, + knockout_entries[i].data.clip.x1, + knockout_entries[i].data.clip.y1); + break; + case KNOCKOUT_PLOT_TEXT: + success &= plot.text( + knockout_entries[i].data.text.x, + knockout_entries[i].data.text.y, + knockout_entries[i].data.text.style, + knockout_entries[i].data.text.text, + knockout_entries[i].data.text.length, + knockout_entries[i].data.text.bg, + knockout_entries[i].data.text.c); + break; + case KNOCKOUT_PLOT_DISC: + success &= plot.disc( + knockout_entries[i].data.disc.x, + knockout_entries[i].data.disc.y, + knockout_entries[i].data.disc.radius, + knockout_entries[i].data.disc.colour, + knockout_entries[i].data.disc.filled); + break; + case KNOCKOUT_PLOT_ARC: + success &= plot.arc( + knockout_entries[i].data.arc.x, + knockout_entries[i].data.arc.y, + knockout_entries[i].data.arc.radius, + knockout_entries[i].data.arc.angle1, + knockout_entries[i].data.arc.angle2, + knockout_entries[i].data.arc.c); + break; + case KNOCKOUT_PLOT_BITMAP: + success &= plot.bitmap( + knockout_entries[i].data.bitmap.x, + knockout_entries[i].data.bitmap.y, + knockout_entries[i].data.bitmap.width, + knockout_entries[i].data.bitmap.height, + knockout_entries[i].data.bitmap.bitmap, + knockout_entries[i].data.bitmap.bg); + break; + case KNOCKOUT_PLOT_BITMAP_TILE: + box = knockout_entries[i].box->child; + if (box) { + success &= knockout_plot_bitmap_tile_recursive(box, + &knockout_entries[i]); + success &= plot.clip(knockout_entries[i].box->bbox.x0, + knockout_entries[i].box->bbox.y0, + knockout_entries[i].box->bbox.x1, + knockout_entries[i].box->bbox.y1); + } else if (!knockout_entries[i].box->deleted) { + success &= plot.bitmap_tile( + knockout_entries[i].data. + bitmap_tile.x, + knockout_entries[i].data. + bitmap_tile.y, + knockout_entries[i].data. + bitmap_tile.width, + knockout_entries[i].data. + bitmap_tile.height, + knockout_entries[i].data. + bitmap_tile.bitmap, + knockout_entries[i].data. + bitmap_tile.bg, + knockout_entries[i].data. + bitmap_tile.repeat_x, + knockout_entries[i].data. + bitmap_tile.repeat_y); + } + break; + case KNOCKOUT_PLOT_GROUP_START: + success &= plot.group_start( + knockout_entries[i].data.group_start.name); + break; + case KNOCKOUT_PLOT_GROUP_END: + success &= plot.group_end(); + break; + } + } + + knockout_entry_cur = 0; + knockout_box_cur = 0; + knockout_polygon_cur = 0; + knockout_list = NULL; + return success; +} + + +/** + * Knockout a section of previous rendering + * + * \param x0 the left edge of the removal box + * \param y0 the bottom edge of the removal box + * \param x1 the right edge of the removal box + * \param y1 the top edge of the removal box + * \param box the current box set to consider +*/ +void knockout_calculate(int x0, int y0, int x1, int y1, struct knockout_box *box) +{ + struct knockout_box *parent; + int nx0, ny0, nx1, ny1; + + for (parent = box; parent; parent = parent->next) { + if (parent->deleted) + continue; + /* reject non-overlapping boxes */ + if ((parent->bbox.x0 >= x1) || + (parent->bbox.x1 <= x0) || + (parent->bbox.y0 >= y1) || + (parent->bbox.y1 <= y0)) + continue; + /* has the box been replaced by children? */ + if (parent->child) { + knockout_calculate(x0, y0, x1, y1, parent->child); + } else { + nx0 = parent->bbox.x0; + ny0 = parent->bbox.y0; + nx1 = parent->bbox.x1; + ny1 = parent->bbox.y1; + + /* check for a total knockout */ + if ((x0 <= nx0) && (x1 >= nx1) && (y0 <= ny0) && (y1 >= ny1)) { + parent->deleted = true; + continue; + } + + /* we need a maximum of 4 child boxes */ + if (knockout_box_cur + 4 >= KNOCKOUT_ENTRIES) { + knockout_plot_start(&real_plot); + return; + } + + /* clip top */ + if (y1 < ny1) { + knockout_boxes[knockout_box_cur].bbox.x0 = nx0; + knockout_boxes[knockout_box_cur].bbox.y0 = y1; + knockout_boxes[knockout_box_cur].bbox.x1 = nx1; + knockout_boxes[knockout_box_cur].bbox.y1 = ny1; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = parent->child; + parent->child = &knockout_boxes[knockout_box_cur++]; + ny1 = y1; + } + /* clip bottom */ + if (y0 > ny0) { + knockout_boxes[knockout_box_cur].bbox.x0 = nx0; + knockout_boxes[knockout_box_cur].bbox.y0 = ny0; + knockout_boxes[knockout_box_cur].bbox.x1 = nx1; + knockout_boxes[knockout_box_cur].bbox.y1 = y0; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = parent->child; + parent->child = &knockout_boxes[knockout_box_cur++]; + ny0 = y0; + } + /* clip right */ + if (x1 < nx1) { + knockout_boxes[knockout_box_cur].bbox.x0 = x1; + knockout_boxes[knockout_box_cur].bbox.y0 = ny0; + knockout_boxes[knockout_box_cur].bbox.x1 = nx1; + knockout_boxes[knockout_box_cur].bbox.y1 = ny1; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = parent->child; + parent->child = &knockout_boxes[knockout_box_cur++]; + nx1 = x1; + } + /* clip left */ + if (x0 > nx0) { + knockout_boxes[knockout_box_cur].bbox.x0 = nx0; + knockout_boxes[knockout_box_cur].bbox.y0 = ny0; + knockout_boxes[knockout_box_cur].bbox.x1 = x0; + knockout_boxes[knockout_box_cur].bbox.y1 = ny1; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = parent->child; + parent->child = &knockout_boxes[knockout_box_cur++]; + //nx0 = x0; + } + } + } +} + + +bool knockout_plot_fill_recursive(struct knockout_box *box, colour c) +{ + bool success = true; + struct knockout_box *parent; + + for (parent = box; parent; parent = parent->next) { + if (parent->deleted) + continue; + if (parent->child) + knockout_plot_fill_recursive(parent->child, c); + else + success &= plot.fill(parent->bbox.x0, + parent->bbox.y0, + parent->bbox.x1, + parent->bbox.y1, + c); + } + return success; +} + + +bool knockout_plot_bitmap_tile_recursive(struct knockout_box *box, + struct knockout_entry *entry) +{ + bool success = true; + struct knockout_box *parent; + + for (parent = box; parent; parent = parent->next) { + if (parent->deleted) + continue; + if (parent->child) + knockout_plot_bitmap_tile_recursive(parent->child, entry); + else { + success &= plot.clip(parent->bbox.x0, + parent->bbox.y0, + parent->bbox.x1, + parent->bbox.y1); + success &= plot.bitmap_tile(entry->data.bitmap_tile.x, + entry->data.bitmap_tile.y, + entry->data.bitmap_tile.width, + entry->data.bitmap_tile.height, + entry->data.bitmap_tile.bitmap, + entry->data.bitmap_tile.bg, + entry->data.bitmap_tile.repeat_x, + entry->data.bitmap_tile.repeat_y); + } + } + return success; +} + +bool knockout_plot_clg(colour c) +{ + return knockout_plot_fill(clip_x0_cur, clip_y0_cur, clip_x1_cur, clip_y1_cur, c); +} + + +bool knockout_plot_rectangle(int x0, int y0, int width, int height, + int line_width, colour c, bool dotted, bool dashed) +{ + knockout_entries[knockout_entry_cur].data.rectangle.x0 = x0; + knockout_entries[knockout_entry_cur].data.rectangle.y0 = y0; + knockout_entries[knockout_entry_cur].data.rectangle.width = width; + knockout_entries[knockout_entry_cur].data.rectangle.height = height; + knockout_entries[knockout_entry_cur].data.rectangle.line_width = line_width; + knockout_entries[knockout_entry_cur].data.rectangle.c = c; + knockout_entries[knockout_entry_cur].data.rectangle.dotted = dotted; + knockout_entries[knockout_entry_cur].data.rectangle.dashed = dashed; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_RECTANGLE; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_line(int x0, int y0, int x1, int y1, int width, + colour c, bool dotted, bool dashed) +{ + knockout_entries[knockout_entry_cur].data.line.x0 = x0; + knockout_entries[knockout_entry_cur].data.line.y0 = y0; + knockout_entries[knockout_entry_cur].data.line.x1 = x1; + knockout_entries[knockout_entry_cur].data.line.y1 = y1; + knockout_entries[knockout_entry_cur].data.line.width = width; + knockout_entries[knockout_entry_cur].data.line.c = c; + knockout_entries[knockout_entry_cur].data.line.dotted = dotted; + knockout_entries[knockout_entry_cur].data.line.dashed = dashed; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_LINE; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_polygon(int *p, unsigned int n, colour fill) +{ + bool success = true; + int *dest; + + /* ensure we have sufficient room even when flushed */ + if (n * 2 >= KNOCKOUT_POLYGONS) { + knockout_plot_end(); + success = plot.polygon(p, n, fill); + knockout_plot_start(&real_plot); + return success; + } + + /* ensure we have enough room right now */ + if (knockout_polygon_cur + n * 2 >= KNOCKOUT_POLYGONS) + knockout_plot_start(&real_plot); + + /* copy our data */ + dest = &(knockout_polygons[knockout_polygon_cur]); + memcpy(dest, p, n * 2 * sizeof(int)); + knockout_polygon_cur += n * 2; + knockout_entries[knockout_entry_cur].data.polygon.p = dest; + knockout_entries[knockout_entry_cur].data.polygon.n = n; + knockout_entries[knockout_entry_cur].data.polygon.fill = fill; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_POLYGON; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_fill(int x0, int y0, int x1, int y1, colour c) +{ + /* fills both knock out and get knocked out */ + knockout_calculate(x0, y0, x1, y1, knockout_list); + knockout_boxes[knockout_box_cur].bbox.x0 = x0; + knockout_boxes[knockout_box_cur].bbox.y0 = y0; + knockout_boxes[knockout_box_cur].bbox.x1 = x1; + knockout_boxes[knockout_box_cur].bbox.y1 = y1; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = knockout_list; + knockout_list = &knockout_boxes[knockout_box_cur]; + knockout_entries[knockout_entry_cur].box = &knockout_boxes[knockout_box_cur]; + knockout_entries[knockout_entry_cur].data.fill.x0 = x0; + knockout_entries[knockout_entry_cur].data.fill.y0 = y0; + knockout_entries[knockout_entry_cur].data.fill.x1 = x1; + knockout_entries[knockout_entry_cur].data.fill.y1 = y1; + knockout_entries[knockout_entry_cur].data.fill.c = c; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_FILL; + if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) || + (++knockout_box_cur >= KNOCKOUT_BOXES)) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_clip(int clip_x0, int clip_y0, + int clip_x1, int clip_y1) +{ + if (clip_x1 < clip_x0 || clip_y0 > clip_y1) { + LOG(("bad clip rectangle %i %i %i %i", + clip_x0, clip_y0, clip_x1, clip_y1)); + return false; + } + + /* memorise clip for bitmap tiling */ + clip_x0_cur = clip_x0; + clip_y0_cur = clip_y0; + clip_x1_cur = clip_x1; + clip_y1_cur = clip_y1; + + knockout_entries[knockout_entry_cur].data.clip.x0 = clip_x0; + knockout_entries[knockout_entry_cur].data.clip.y0 = clip_y0; + knockout_entries[knockout_entry_cur].data.clip.x1 = clip_x1; + knockout_entries[knockout_entry_cur].data.clip.y1 = clip_y1; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_CLIP; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_text(int x, int y, struct css_style *style, + const char *text, size_t length, colour bg, colour c) +{ + knockout_entries[knockout_entry_cur].data.text.x = x; + knockout_entries[knockout_entry_cur].data.text.y = y; + knockout_entries[knockout_entry_cur].data.text.style = style; + knockout_entries[knockout_entry_cur].data.text.text = text; + knockout_entries[knockout_entry_cur].data.text.length = length; + knockout_entries[knockout_entry_cur].data.text.bg = bg; + knockout_entries[knockout_entry_cur].data.text.c = c; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_TEXT; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_disc(int x, int y, int radius, colour colour, bool filled) +{ + knockout_entries[knockout_entry_cur].data.disc.x = x; + knockout_entries[knockout_entry_cur].data.disc.y = y; + knockout_entries[knockout_entry_cur].data.disc.radius = radius; + knockout_entries[knockout_entry_cur].data.disc.colour = colour; + knockout_entries[knockout_entry_cur].data.disc.filled = filled; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_DISC; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + +bool knockout_plot_arc(int x, int y, int radius, int angle1, int angle2, colour c) +{ + knockout_entries[knockout_entry_cur].data.arc.x = x; + knockout_entries[knockout_entry_cur].data.arc.y = y; + knockout_entries[knockout_entry_cur].data.arc.radius = radius; + knockout_entries[knockout_entry_cur].data.arc.angle1 = angle1; + knockout_entries[knockout_entry_cur].data.arc.angle2 = angle2; + knockout_entries[knockout_entry_cur].data.arc.c = c; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_ARC; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + +bool knockout_plot_bitmap(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg) +{ + /* opaque bitmaps knockout, but don't get knocked out */ + if (bitmap_get_opaque(bitmap)) + knockout_calculate(x, y, x + width, y + height, knockout_list); + knockout_entries[knockout_entry_cur].data.bitmap.x = x; + knockout_entries[knockout_entry_cur].data.bitmap.x = x; + knockout_entries[knockout_entry_cur].data.bitmap.y = y; + knockout_entries[knockout_entry_cur].data.bitmap.width = width; + knockout_entries[knockout_entry_cur].data.bitmap.height = height; + knockout_entries[knockout_entry_cur].data.bitmap.bitmap = bitmap; + knockout_entries[knockout_entry_cur].data.bitmap.bg = bg; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_BITMAP; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + + +bool knockout_plot_bitmap_tile(int x, int y, int width, int height, + struct bitmap *bitmap, colour bg, + bool repeat_x, bool repeat_y) +{ + /* tiled bitmaps both knock out and get knocked out */ + if (bitmap_get_opaque(bitmap)) + knockout_calculate(clip_x0_cur, clip_y0_cur, clip_x1_cur, clip_y1_cur, + knockout_list); + knockout_boxes[knockout_box_cur].bbox.x0 = clip_x0_cur; + knockout_boxes[knockout_box_cur].bbox.y0 = clip_y0_cur; + knockout_boxes[knockout_box_cur].bbox.x1 = clip_x1_cur; + knockout_boxes[knockout_box_cur].bbox.y1 = clip_y1_cur; + knockout_boxes[knockout_box_cur].deleted = false; + knockout_boxes[knockout_box_cur].child = NULL; + knockout_boxes[knockout_box_cur].next = knockout_list; + knockout_list = &knockout_boxes[knockout_box_cur]; + knockout_entries[knockout_entry_cur].box = &knockout_boxes[knockout_box_cur]; + knockout_entries[knockout_entry_cur].data.bitmap_tile.x = x; + knockout_entries[knockout_entry_cur].data.bitmap_tile.y = y; + knockout_entries[knockout_entry_cur].data.bitmap_tile.width = width; + knockout_entries[knockout_entry_cur].data.bitmap_tile.height = height; + knockout_entries[knockout_entry_cur].data.bitmap_tile.bitmap = bitmap; + knockout_entries[knockout_entry_cur].data.bitmap_tile.bg = bg; + knockout_entries[knockout_entry_cur].data.bitmap_tile.repeat_x = repeat_x; + knockout_entries[knockout_entry_cur].data.bitmap_tile.repeat_y = repeat_y; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_BITMAP_TILE; + if ((++knockout_entry_cur >= KNOCKOUT_ENTRIES) || + (++knockout_box_cur >= KNOCKOUT_BOXES)) + knockout_plot_start(&real_plot); + return true; +} + +bool knockout_plot_group_start(const char *name) +{ + knockout_entries[knockout_entry_cur].data.group_start.name = name; + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_START; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} + +bool knockout_plot_group_end(void) +{ + knockout_entries[knockout_entry_cur].type = KNOCKOUT_PLOT_GROUP_END; + if (++knockout_entry_cur >= KNOCKOUT_ENTRIES) + knockout_plot_start(&real_plot); + return true; +} diff --git a/desktop/knockout.h b/desktop/knockout.h new file mode 100644 index 000000000..d564ee6f0 --- /dev/null +++ b/desktop/knockout.h @@ -0,0 +1,19 @@ +/* + * 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 2006 Richard Wilson <info@tinct.net> + */ + +/** \file + * Knockout rendering (interface). + */ + +#include "netsurf/desktop/plotters.h" + + +bool knockout_plot_start(struct plotter_table *plotter); +bool knockout_plot_end(void); + + +extern const struct plotter_table knockout_plotters; diff --git a/desktop/options.c b/desktop/options.c index 1787e55a5..d01caad61 100644 --- a/desktop/options.c +++ b/desktop/options.c @@ -101,6 +101,8 @@ int option_max_fetchers_per_host = 5; * is this plus option_max_fetchers. */ int option_max_cached_fetch_handles = 6; +/** Whether to use knockout rendering */ +bool option_knockout_rendering = false; EXTRA_OPTION_DEFINE @@ -142,6 +144,7 @@ struct { OPTION_INTEGER, &option_max_fetchers_per_host }, { "max_cached_fetch_handles", OPTION_INTEGER, &option_max_cached_fetch_handles }, + { "knockout_rendering", OPTION_BOOL, &option_knockout_rendering }, EXTRA_OPTION_TABLE }; diff --git a/desktop/options.h b/desktop/options.h index 35e1d62a9..08e808b99 100644 --- a/desktop/options.h +++ b/desktop/options.h @@ -55,6 +55,7 @@ extern char *option_ca_bundle; extern char *option_cookie_file; extern char *option_cookie_jar; extern char *option_homepage_url; +extern bool option_knockout_rendering; /* Fetcher configuration. */ extern int option_max_fetchers; |