summaryrefslogtreecommitdiff
path: root/desktop/treeview.c
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2013-10-02 23:34:34 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2013-10-02 23:34:34 +0100
commit2a4fb9ecd1b80cefab5999e5401c339c0973d574 (patch)
tree74a5482e3860f1868b8189e15bc495444bc4cea9 /desktop/treeview.c
parent506a0e7d940abb6a95a890caf024743a993c8dcd (diff)
downloadnetsurf-2a4fb9ecd1b80cefab5999e5401c339c0973d574.tar.gz
netsurf-2a4fb9ecd1b80cefab5999e5401c339c0973d574.tar.bz2
Generate anti-aliased triangles in bitmaps and plot via bitmap plotter. (Without anti-aliasing was too ugly to be endured.)
Diffstat (limited to 'desktop/treeview.c')
-rw-r--r--desktop/treeview.c364
1 files changed, 263 insertions, 101 deletions
diff --git a/desktop/treeview.c b/desktop/treeview.c
index b88566039..3bd0f6a35 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -26,6 +26,7 @@
#include "desktop/plotters.h"
#include "desktop/textarea.h"
#include "desktop/treeview.h"
+#include "image/bitmap.h"
#include "render/font.h"
#include "utils/log.h"
@@ -157,16 +158,27 @@ struct treeview {
};
+enum treeview_furniture_id {
+ TREE_FURN_EXPAND = 0,
+ TREE_FURN_CONTRACT,
+ TREE_FURN_LAST
+};
+struct treeview_furniture {
+ int size;
+ struct bitmap *bmp;
+ struct bitmap *sel;
+};
+
struct treeview_node_style {
plot_style_t bg; /**< Background */
plot_font_style_t text; /**< Text */
plot_font_style_t itext; /**< Entry field text */
- plot_style_t furn; /**< Furniture */
plot_style_t sbg; /**< Selected background */
plot_font_style_t stext; /**< Selected text */
plot_font_style_t sitext; /**< Selected entry field text */
- plot_style_t sfurn; /**< Selected furniture */
+
+ struct treeview_furniture furn[TREE_FURN_LAST];
};
struct treeview_node_style plot_style_odd; /**< Plot style for odd rows */
@@ -193,19 +205,6 @@ static struct treeview_resource treeview_res[TREE_RES_LAST] = {
}; /**< Treeview content resources */
-
-enum treeview_furniture_id {
- TREE_FURN_EXPAND = 0,
- TREE_FURN_CONTRACT,
- TREE_FURN_LAST
-};
-struct treeview_furniture {
- int pts; /* Number of points (max = 8) */
- int c[8]; /* Coordinate array. x-coord, y-coord... */
-};
-static struct treeview_furniture tree_furn[TREE_FURN_LAST];
-
-
/* Find the next node in depth first tree order
*
* \param node Start node
@@ -1669,12 +1668,10 @@ void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
plot_style_t *bg_style;
plot_font_style_t *text_style;
plot_font_style_t *infotext_style;
- plot_style_t *furn_style;
+ struct bitmap *furniture;
int height;
int sel_min, sel_max;
bool invert_selection;
- enum treeview_furniture_id furn_id;
- int coords[8];
assert(tree != NULL);
assert(tree->root != NULL);
@@ -1763,12 +1760,16 @@ void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
bg_style = &style->sbg;
text_style = &style->stext;
infotext_style = &style->sitext;
- furn_style = &style->sfurn;
+ furniture = (node->flags & TREE_NODE_EXPANDED) ?
+ style->furn[TREE_FURN_CONTRACT].sel :
+ style->furn[TREE_FURN_EXPAND].sel;
} else {
bg_style = &style->bg;
text_style = &style->text;
infotext_style = &style->itext;
- furn_style = &style->furn;
+ furniture = (node->flags & TREE_NODE_EXPANDED) ?
+ style->furn[TREE_FURN_CONTRACT].bmp :
+ style->furn[TREE_FURN_EXPAND].bmp;
}
/* Render background */
@@ -1777,18 +1778,11 @@ void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
new_ctx.plot->rectangle(r.x0, y0, r.x1, y1, bg_style);
/* Render toggle */
- if (node->flags & TREE_NODE_EXPANDED) {
- furn_id = TREE_FURN_CONTRACT;
- } else {
- furn_id = TREE_FURN_EXPAND;
- }
-
- for (i = 0; i < tree_furn[furn_id].pts; i += 2) {
- coords[i ] = tree_furn[furn_id].c[i ] + inset;
- coords[i + 1] = tree_furn[furn_id].c[i + 1] + render_y;
- }
- new_ctx.plot->polygon(coords, tree_furn[furn_id].pts / 2,
- furn_style);
+ new_ctx.plot->bitmap(inset, render_y + tree_g.line_height / 4,
+ style->furn[TREE_FURN_EXPAND].size,
+ style->furn[TREE_FURN_EXPAND].size,
+ furniture,
+ bg_style->fill_colour, BITMAPF_NONE);
/* Render icon */
if (node->type == TREE_NODE_ENTRY)
@@ -3481,10 +3475,6 @@ static void treeview_init_plot_styles(int font_pt_size)
plot_style_even.text.foreground,
plot_style_even.text.background, 255 * 10 / 16);
- /* Furniture colour */
- plot_style_even.furn = plot_style_even.bg;
- plot_style_even.furn.fill_colour = plot_style_even.itext.foreground;
-
/* Selected background colour */
plot_style_even.sbg = plot_style_even.bg;
plot_style_even.sbg.fill_colour = gui_system_colour_char("Highlight");
@@ -3501,10 +3491,6 @@ static void treeview_init_plot_styles(int font_pt_size)
plot_style_even.stext.foreground,
plot_style_even.stext.background, 255 * 25 / 32);
- /* Selected furniture colour */
- plot_style_even.sfurn = plot_style_even.bg;
- plot_style_even.sfurn.fill_colour = plot_style_even.sitext.foreground;
-
/* Odd numbered node styles */
plot_style_odd.bg = plot_style_even.bg;
@@ -3517,13 +3503,10 @@ static void treeview_init_plot_styles(int font_pt_size)
plot_style_odd.itext.foreground = mix_colour(
plot_style_odd.text.foreground,
plot_style_odd.text.background, 255 * 10 / 16);
- plot_style_odd.furn = plot_style_odd.bg;
- plot_style_odd.furn.fill_colour = plot_style_odd.itext.foreground;
plot_style_odd.sbg = plot_style_even.sbg;
plot_style_odd.stext = plot_style_even.stext;
plot_style_odd.sitext = plot_style_even.sitext;
- plot_style_odd.sfurn = plot_style_even.sfurn;
}
@@ -3571,91 +3554,258 @@ static void treeview_init_resources(void)
/**
- * Measures width of characters used to represent treeview furniture.
+ * Create a right-pointing anti-aliased triangle bitmap
+ *
+ * bg background colour
+ * fg foreground colour
+ * size required bitmap size
*/
-static void treeview_init_furniture(void)
+static struct bitmap * treeview_generate_triangle_bitmap(
+ colour bg, colour fg, int size)
{
- struct treeview_furniture *f;
- int size = tree_g.line_height / 2;
- int smax = size - 1;
- int i, y;
+ struct bitmap *b = NULL;
+ int x, y;
+ unsigned char *rpos;
+ unsigned char *pos;
+ size_t stride;
+
+ /* Set up required colour graduations. Ignores screen gamma. */
+ colour colour0 = bg;
+ colour colour1 = mix_colour(bg, fg, 255 * 3 / 4);
+ colour colour2 = blend_colour(bg, fg);
+ colour colour3 = mix_colour(bg, fg, 255 * 1 / 4);
+ colour colour4 = fg;
+
+ /* Create the bitmap */
+ b = bitmap_create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ if (b == NULL)
+ return NULL;
+
+ rpos = bitmap_get_buffer(b);
+ stride = bitmap_get_rowstride(b);
+
+ /* Draw the triangle */
+ for (y = 0; y < size; y++) {
+ pos = rpos;
+
+ if (y < size / 2) {
+ /* Top half */
+ for (x = 0; x < y * 2; x++) {
+ *(pos++) = red_from_colour(colour4);
+ *(pos++) = green_from_colour(colour4);
+ *(pos++) = blue_from_colour(colour4);
+ pos++;
+ }
+ *(pos++) = red_from_colour(colour3);
+ *(pos++) = green_from_colour(colour3);
+ *(pos++) = blue_from_colour(colour3);
+ pos++;
+ *(pos++) = red_from_colour(colour1);
+ *(pos++) = green_from_colour(colour1);
+ *(pos++) = blue_from_colour(colour1);
+ pos++;
+ for (x = y * 2 + 2; x < size ; x++) {
+ *(pos++) = red_from_colour(colour0);
+ *(pos++) = green_from_colour(colour0);
+ *(pos++) = blue_from_colour(colour0);
+ pos++;
+ }
+ } else if ((y == size / 2) && (size & 0x1)) {
+ /* Middle row */
+ for (x = 0; x < size - 1; x++) {
+ *(pos++) = red_from_colour(colour4);
+ *(pos++) = green_from_colour(colour4);
+ *(pos++) = blue_from_colour(colour4);
+ pos++;
+ }
+ *(pos++) = red_from_colour(colour2);
+ *(pos++) = green_from_colour(colour2);
+ *(pos++) = blue_from_colour(colour2);
+ pos++;
+ } else {
+ /* Bottom half */
+ for (x = 0; x < (size - y - 1) * 2; x++) {
+ *(pos++) = red_from_colour(colour4);
+ *(pos++) = green_from_colour(colour4);
+ *(pos++) = blue_from_colour(colour4);
+ pos++;
+ }
+ *(pos++) = red_from_colour(colour3);
+ *(pos++) = green_from_colour(colour3);
+ *(pos++) = blue_from_colour(colour3);
+ pos++;
+ *(pos++) = red_from_colour(colour1);
+ *(pos++) = green_from_colour(colour1);
+ *(pos++) = blue_from_colour(colour1);
+ pos++;
+ for (x = (size - y) * 2; x < size ; x++) {
+ *(pos++) = red_from_colour(colour0);
+ *(pos++) = green_from_colour(colour0);
+ *(pos++) = blue_from_colour(colour0);
+ pos++;
+ }
+ }
- /* Make TREE_FURN_EXPAND */
- f = &(tree_furn[TREE_FURN_EXPAND]);
+ rpos += stride;
+ }
- if (size & 0x1) {
- /* Size is odd; triangle */
- f->pts = 6;
+ bitmap_modified(b);
- f->c[0] = 0;
- f->c[1] = 0;
+ return b;
+}
- f->c[2] = smax;
- f->c[3] = size / 2;
- f->c[4] = 0;
- f->c[5] = smax;
+/**
+ * Create bitmap copy of another bitmap
+ *
+ * orig bitmap to copy
+ * size required bitmap size
+ */
+static struct bitmap * treeview_generate_copy_bitmap(
+ struct bitmap *orig, int size)
+{
+ struct bitmap *b = NULL;
+ unsigned char *data;
+ unsigned char *orig_data;
+ size_t stride;
- } else {
- /* Size is even; trapezium */
- f->pts = 8;
+ if (orig == NULL)
+ return NULL;
- f->c[0] = 0;
- f->c[1] = 0;
+ assert(size == bitmap_get_width(orig));
+ assert(size == bitmap_get_height(orig));
- f->c[2] = smax;
- f->c[3] = size / 2 - 1;
+ /* Create the bitmap */
+ b = bitmap_create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ if (b == NULL)
+ return NULL;
- f->c[4] = smax;
- f->c[5] = size / 2;
+ stride = bitmap_get_rowstride(b);
+ assert(stride == bitmap_get_rowstride(orig));
- f->c[6] = 0;
- f->c[7] = smax;
- }
+ data = bitmap_get_buffer(b);
+ orig_data = bitmap_get_buffer(orig);
- /* Make TREE_FURN_CONTRACT */
- f = &(tree_furn[TREE_FURN_CONTRACT]);
+ /* Copy the bitmap */
+ memcpy(data, orig_data, stride * size);
- if (size & 0x1) {
- /* Size is odd; triangle */
- f->pts = 6;
+ bitmap_modified(b);
- f->c[0] = 0;
- f->c[1] = 0;
+ return b;
+}
- f->c[2] = smax;
- f->c[3] = 0;
- f->c[4] = size / 2;
- f->c[5] = smax;
+/**
+ * Create bitmap from rotation of another bitmap
+ *
+ * orig bitmap to create rotation of
+ * size required bitmap size
+ */
+static struct bitmap * treeview_generate_rotate_bitmap(
+ struct bitmap *orig, int size)
+{
+ struct bitmap *b = NULL;
+ int x, y;
+ unsigned char *rpos;
+ unsigned char *pos;
+ unsigned char *orig_data;
+ unsigned char *orig_pos;
+ size_t stride;
- } else {
- /* Size is even; trapezium */
- f->pts = 8;
+ if (orig == NULL)
+ return NULL;
- f->c[0] = 0;
- f->c[1] = 0;
+ assert(size == bitmap_get_width(orig));
+ assert(size == bitmap_get_height(orig));
- f->c[2] = smax;
- f->c[3] = 0;
+ /* Create the bitmap */
+ b = bitmap_create(size, size, BITMAP_NEW | BITMAP_OPAQUE);
+ if (b == NULL)
+ return NULL;
- f->c[4] = size / 2;
- f->c[5] = smax;
+ stride = bitmap_get_rowstride(b);
+ assert(stride == bitmap_get_rowstride(orig));
- f->c[6] = size / 2 - 1;
- f->c[7] = smax;
- }
+ rpos = bitmap_get_buffer(b);
+ orig_data = bitmap_get_buffer(orig);
- /* Vertically offset for line height */
- for (i = 0; i < TREE_FURN_LAST; i++) {
- f = &(tree_furn[i]);
+ /* Copy the rotated bitmap */
+ for (y = 0; y < size; y++) {
+ pos = rpos;
- for (y = 1; y < f->pts; y += 2) {
- f->c[y] += tree_g.line_height / 4;
+ for (x = 0; x < size; x++) {
+ orig_pos = orig_data + x * stride + y * 4;
+ *(pos++) = *(orig_pos++);
+ *(pos++) = *(orig_pos++);
+ *(pos++) = *(orig_pos);
+ pos++;
+
}
+
+ rpos += stride;
}
+ bitmap_modified(b);
+
+ return b;
+}
+
+
+/**
+ * Measures width of characters used to represent treeview furniture.
+ */
+static nserror treeview_init_furniture(void)
+{
+ int size = tree_g.line_height / 2;
+
+ plot_style_odd.furn[TREE_FURN_EXPAND].size = size;
+ plot_style_odd.furn[TREE_FURN_EXPAND].bmp =
+ treeview_generate_triangle_bitmap(
+ plot_style_odd.bg.fill_colour,
+ plot_style_odd.itext.foreground, size);
+ plot_style_odd.furn[TREE_FURN_EXPAND].sel =
+ treeview_generate_triangle_bitmap(
+ plot_style_odd.sbg.fill_colour,
+ plot_style_odd.sitext.foreground, size);
+
+ plot_style_even.furn[TREE_FURN_EXPAND].size = size;
+ plot_style_even.furn[TREE_FURN_EXPAND].bmp =
+ treeview_generate_triangle_bitmap(
+ plot_style_even.bg.fill_colour,
+ plot_style_even.itext.foreground, size);
+ plot_style_even.furn[TREE_FURN_EXPAND].sel =
+ treeview_generate_copy_bitmap(
+ plot_style_odd.furn[TREE_FURN_EXPAND].sel, size);
+
+ plot_style_odd.furn[TREE_FURN_CONTRACT].size = size;
+ plot_style_odd.furn[TREE_FURN_CONTRACT].bmp =
+ treeview_generate_rotate_bitmap(
+ plot_style_odd.furn[TREE_FURN_EXPAND].bmp, size);
+ plot_style_odd.furn[TREE_FURN_CONTRACT].sel =
+ treeview_generate_rotate_bitmap(
+ plot_style_odd.furn[TREE_FURN_EXPAND].sel, size);
+
+ plot_style_even.furn[TREE_FURN_CONTRACT].size = size;
+ plot_style_even.furn[TREE_FURN_CONTRACT].bmp =
+ treeview_generate_rotate_bitmap(
+ plot_style_even.furn[TREE_FURN_EXPAND].bmp, size);
+ plot_style_even.furn[TREE_FURN_CONTRACT].sel =
+ treeview_generate_rotate_bitmap(
+ plot_style_even.furn[TREE_FURN_EXPAND].sel, size);
+
+ if (plot_style_odd.furn[TREE_FURN_EXPAND].bmp == NULL ||
+ plot_style_odd.furn[TREE_FURN_EXPAND].sel == NULL ||
+ plot_style_even.furn[TREE_FURN_EXPAND].bmp == NULL ||
+ plot_style_even.furn[TREE_FURN_EXPAND].sel == NULL ||
+ plot_style_odd.furn[TREE_FURN_CONTRACT].bmp == NULL ||
+ plot_style_odd.furn[TREE_FURN_CONTRACT].sel == NULL ||
+ plot_style_even.furn[TREE_FURN_CONTRACT].bmp == NULL ||
+ plot_style_even.furn[TREE_FURN_CONTRACT].sel == NULL)
+ return NSERROR_NOMEM;
+
tree_g.furniture_width = size + tree_g.line_height / 4;
+
+ return NSERROR_OK;
}
@@ -3663,6 +3813,7 @@ static void treeview_init_furniture(void)
nserror treeview_init(int font_pt_size)
{
int font_px_size;
+ nserror err;
if (tree_g.initialised == true)
return NSERROR_OK;
@@ -3675,7 +3826,9 @@ nserror treeview_init(int font_pt_size)
treeview_init_plot_styles(font_pt_size);
treeview_init_resources();
- treeview_init_furniture();
+ err = treeview_init_furniture();
+ if (err != NSERROR_OK)
+ return err;
tree_g.step_width = tree_g.furniture_width;
tree_g.window_padding = 6;
@@ -3699,6 +3852,15 @@ nserror treeview_fini(void)
hlcache_handle_release(treeview_res[i].c);
}
+ bitmap_destroy(plot_style_odd.furn[TREE_FURN_EXPAND].bmp);
+ bitmap_destroy(plot_style_odd.furn[TREE_FURN_EXPAND].sel);
+ bitmap_destroy(plot_style_even.furn[TREE_FURN_EXPAND].bmp);
+ bitmap_destroy(plot_style_even.furn[TREE_FURN_EXPAND].sel);
+ bitmap_destroy(plot_style_odd.furn[TREE_FURN_CONTRACT].bmp);
+ bitmap_destroy(plot_style_odd.furn[TREE_FURN_CONTRACT].sel);
+ bitmap_destroy(plot_style_even.furn[TREE_FURN_CONTRACT].bmp);
+ bitmap_destroy(plot_style_even.furn[TREE_FURN_CONTRACT].sel);
+
tree_g.initialised = false;
return NSERROR_OK;