diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/display/sodipodi-ctrl.cpp | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/display/sodipodi-ctrl.cpp')
| -rw-r--r-- | src/display/sodipodi-ctrl.cpp | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp new file mode 100644 index 000000000..71786fd96 --- /dev/null +++ b/src/display/sodipodi-ctrl.cpp @@ -0,0 +1,494 @@ +#define INKSCAPE_CTRL_C + +/* + * SPCtrl + * + * We render it by hand to reduce allocing/freeing svps & to get clean + * (non-aa) images + * + */ + +#include "sp-canvas-util.h" +#include "display-forward.h" +#include "sodipodi-ctrl.h" + +enum { + ARG_0, + ARG_SHAPE, + ARG_MODE, + ARG_ANCHOR, + ARG_SIZE, + ARG_FILLED, + ARG_FILL_COLOR, + ARG_STROKED, + ARG_STROKE_COLOR, + ARG_PIXBUF +}; + + +static void sp_ctrl_class_init (SPCtrlClass *klass); +static void sp_ctrl_init (SPCtrl *ctrl); +static void sp_ctrl_destroy (GtkObject *object); +static void sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); + +static void sp_ctrl_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags); +static void sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf); + +static double sp_ctrl_point (SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_item); + + +static SPCanvasItemClass *parent_class; + +GtkType +sp_ctrl_get_type (void) +{ + static GtkType ctrl_type = 0; + if (!ctrl_type) { + static const GTypeInfo ctrl_info = { + sizeof (SPCtrlClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) sp_ctrl_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (SPCtrl), + 0, /* n_preallocs */ + (GInstanceInitFunc) sp_ctrl_init, + NULL + }; + ctrl_type = g_type_register_static (SP_TYPE_CANVAS_ITEM, "SPCtrl", &ctrl_info, (GTypeFlags)0); + } + return ctrl_type; +} + +static void +sp_ctrl_class_init (SPCtrlClass *klass) +{ + GtkObjectClass *object_class; + SPCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) klass; + item_class = (SPCanvasItemClass *) klass; + + parent_class = (SPCanvasItemClass *)gtk_type_class (sp_canvas_item_get_type ()); + + gtk_object_add_arg_type ("SPCtrl::shape", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_SHAPE); + gtk_object_add_arg_type ("SPCtrl::mode", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MODE); + gtk_object_add_arg_type ("SPCtrl::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR); + gtk_object_add_arg_type ("SPCtrl::size", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_SIZE); + gtk_object_add_arg_type ("SPCtrl::pixbuf", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PIXBUF); + gtk_object_add_arg_type ("SPCtrl::filled", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILLED); + gtk_object_add_arg_type ("SPCtrl::fill_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR); + gtk_object_add_arg_type ("SPCtrl::stroked", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_STROKED); + gtk_object_add_arg_type ("SPCtrl::stroke_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_STROKE_COLOR); + + object_class->destroy = sp_ctrl_destroy; + object_class->set_arg = sp_ctrl_set_arg; + + item_class->update = sp_ctrl_update; + item_class->render = sp_ctrl_render; + item_class->point = sp_ctrl_point; +} + +static void +sp_ctrl_init (SPCtrl *ctrl) +{ + ctrl->shape = SP_CTRL_SHAPE_SQUARE; + ctrl->mode = SP_CTRL_MODE_COLOR; + ctrl->anchor = GTK_ANCHOR_CENTER; + ctrl->span = 3; + ctrl->defined = TRUE; + ctrl->shown = FALSE; + ctrl->build = FALSE; + ctrl->filled = 1; + ctrl->stroked = 0; + ctrl->fill_color = 0x000000ff; + ctrl->stroke_color = 0x000000ff; + + ctrl->box.x0 = ctrl->box.y0 = ctrl->box.x1 = ctrl->box.y1 = 0; + ctrl->cache = NULL; + ctrl->pixbuf = NULL; +} + +static void +sp_ctrl_destroy (GtkObject *object) +{ + SPCtrl *ctrl; + + g_return_if_fail (object != NULL); + g_return_if_fail (SP_IS_CTRL (object)); + + ctrl = SP_CTRL (object); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +static void +sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + SPCanvasItem *item; + SPCtrl *ctrl; + GdkPixbuf * pixbuf = NULL; + + item = SP_CANVAS_ITEM (object); + ctrl = SP_CTRL (object); + + switch (arg_id) { + case ARG_SHAPE: + ctrl->shape = (SPCtrlShapeType)(GTK_VALUE_INT (*arg)); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_MODE: + ctrl->mode = (SPCtrlModeType)(GTK_VALUE_INT (*arg)); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_ANCHOR: + ctrl->anchor = (GtkAnchorType)(GTK_VALUE_INT (*arg)); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_SIZE: + ctrl->span = (gint) ((GTK_VALUE_DOUBLE (*arg) - 1.0) / 2.0 + 0.5); + ctrl->defined = (ctrl->span > 0); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_FILLED: + ctrl->filled = GTK_VALUE_BOOL (*arg); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_FILL_COLOR: + ctrl->fill_color = GTK_VALUE_INT (*arg); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_STROKED: + ctrl->stroked = GTK_VALUE_BOOL (*arg); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_STROKE_COLOR: + ctrl->stroke_color = GTK_VALUE_INT (*arg); + ctrl->build = FALSE; + sp_canvas_item_request_update (item); + break; + case ARG_PIXBUF: + pixbuf = (GdkPixbuf*)(GTK_VALUE_POINTER (*arg)); + if (gdk_pixbuf_get_has_alpha (pixbuf)) { + ctrl->pixbuf = pixbuf; + } else { + ctrl->pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); + gdk_pixbuf_unref (pixbuf); + } + ctrl->build = FALSE; + break; + default: + break; + } +} + +static void +sp_ctrl_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags) +{ + SPCtrl *ctrl; + gint x, y; + + ctrl = SP_CTRL (item); + + if (((SPCanvasItemClass *) parent_class)->update) + (* ((SPCanvasItemClass *) parent_class)->update) (item, affine, flags); + + sp_canvas_item_reset_bounds (item); + + if (ctrl->shown) { + sp_canvas_request_redraw (item->canvas, ctrl->box.x0, ctrl->box.y0, ctrl->box.x1 + 1, ctrl->box.y1 + 1); + } + + if (!ctrl->defined) return; + + x = (gint) ((affine[4] > 0) ? (affine[4] + 0.5) : (affine[4] - 0.5)) - ctrl->span; + y = (gint) ((affine[5] > 0) ? (affine[5] + 0.5) : (affine[5] - 0.5)) - ctrl->span; + + switch (ctrl->anchor) { + case GTK_ANCHOR_N: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_S: + break; + case GTK_ANCHOR_NW: + case GTK_ANCHOR_W: + case GTK_ANCHOR_SW: + x += ctrl->span; + break; + case GTK_ANCHOR_NE: + case GTK_ANCHOR_E: + case GTK_ANCHOR_SE: + x -= (ctrl->span + 1); + break; + } + + switch (ctrl->anchor) { + case GTK_ANCHOR_W: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_E: + break; + case GTK_ANCHOR_NW: + case GTK_ANCHOR_N: + case GTK_ANCHOR_NE: + y += ctrl->span; + break; + case GTK_ANCHOR_SW: + case GTK_ANCHOR_S: + case GTK_ANCHOR_SE: + y -= (ctrl->span + 1); + break; + } + + ctrl->box.x0 = x; + ctrl->box.y0 = y; + ctrl->box.x1 = ctrl->box.x0 + 2 * ctrl->span; + ctrl->box.y1 = ctrl->box.y0 + 2 * ctrl->span; + + sp_canvas_update_bbox (item, ctrl->box.x0, ctrl->box.y0, ctrl->box.x1 + 1, ctrl->box.y1 + 1); + +} + +static double +sp_ctrl_point (SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_item) +{ + SPCtrl *ctrl = SP_CTRL (item); + + *actual_item = item; + + const double x = p[NR::X]; + const double y = p[NR::Y]; + + if ((x >= ctrl->box.x0) && (x <= ctrl->box.x1) && (y >= ctrl->box.y0) && (y <= ctrl->box.y1)) return 0.0; + + return 1e18; +} + +static void +sp_ctrl_build_cache (SPCtrl *ctrl) +{ + guchar * p, *q; + gint size, x, y, z, s, a, side, c; + guint8 fr, fg, fb, fa, sr, sg, sb, sa; + + if (ctrl->filled) { + fr = (ctrl->fill_color >> 24) & 0xff; + fg = (ctrl->fill_color >> 16) & 0xff; + fb = (ctrl->fill_color >> 8) & 0xff; + fa = (ctrl->fill_color) & 0xff; + } else { fr = 0x00; fg = 0x00; fb = 0x00; fa = 0x00; } + if (ctrl->stroked) { + sr = (ctrl->stroke_color >> 24) & 0xff; + sg = (ctrl->stroke_color >> 16) & 0xff; + sb = (ctrl->stroke_color >> 8) & 0xff; + sa = (ctrl->stroke_color) & 0xff; + } else { sr = fr; sg = fg; sb = fb; sa = fa; } + + + side = (ctrl->span * 2 +1); + c = ctrl->span ; + g_free (ctrl->cache); + size = (side) * (side) * 4; + ctrl->cache = (guchar*)g_malloc (size); + if (side < 2) return; + + switch (ctrl->shape) { + case SP_CTRL_SHAPE_SQUARE: + p = ctrl->cache; + for (x=0; x < side; x++) { *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; } + for (y = 2; y < side; y++) { + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; + for (x=2; x < side; x++) { *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa; } + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; + } + for (x=0; x < side; x++) { *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; } + ctrl->build = TRUE; + break; + case SP_CTRL_SHAPE_DIAMOND: + p = ctrl->cache; + for (y = 0; y < side; y++) { + z = abs (c - y); + for (x = 0; x < z; x++) {*p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;} + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++; + for (; x < side - z -1; x++) { *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa; } + if (z != c) {*p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;} + for (; x < side; x++) {*p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;} + } + break; + case SP_CTRL_SHAPE_CIRCLE: + p = ctrl->cache; + q = p + size -1; + s = -1; + for (y = 0; y <= c ; y++) { + a = abs (c - y); + z = (gint)(0.0 + sqrt ((c+.4)*(c+.4) - a*a)); + x = 0; + while (x < c-z) { + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; + *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; + x++; + } + do { + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; + *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr; + x++; + } while (x < c-s); + while (x < MIN(c+s+1, c+z)) { + *p++ = fr; *p++ = fg; *p++ = fb; *p++ = fa; + *q-- = fa; *q-- = fb; *q-- = fg; *q-- = fr; + x++; + } + do { + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; + *q-- = sa; *q-- = sb; *q-- = sg; *q-- = sr; + x++; + } while (x <= c+z); + while (x < side) { + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; + *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; *q-- = 0x00; + x++; + } + s = z; + } + ctrl->build = TRUE; + break; + case SP_CTRL_SHAPE_CROSS: + p = ctrl->cache; + for (y = 0; y < side; y++) { + z = abs (c - y); + for (x = 0; x < c-z; x++) {*p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;} + *p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++; + for (; x < c + z; x++) {*p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;} + if (z != 0) {*p++ = sr; *p++ = sg; *p++ = sb; *p++ = sa; x++;} + for (; x < side; x++) {*p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00;} + } + ctrl->build = TRUE; + break; + case SP_CTRL_SHAPE_BITMAP: + if (ctrl->pixbuf) { + unsigned char *px; + unsigned int rs; + px = gdk_pixbuf_get_pixels (ctrl->pixbuf); + rs = gdk_pixbuf_get_rowstride (ctrl->pixbuf); + for (y = 0; y < side; y++){ + unsigned char *s, *d; + s = px + y * rs; + d = ctrl->cache + 4 * side * y; + for (x = 0; x < side; x++) { + if (s[3] < 0x80) { + d[0] = 0x00; + d[1] = 0x00; + d[2] = 0x00; + d[3] = 0x00; + } else if (s[0] < 0x80) { + d[0] = sr; + d[1] = sg; + d[2] = sb; + d[3] = sa; + } else { + d[0] = fr; + d[1] = fg; + d[2] = fb; + d[3] = fa; + } + s += 4; + d += 4; + } + } + } else { + g_print ("control has no pixmap\n"); + } + ctrl->build = TRUE; + break; + case SP_CTRL_SHAPE_IMAGE: + if (ctrl->pixbuf) { + guint r = gdk_pixbuf_get_rowstride (ctrl->pixbuf); + guchar * pix; + q = gdk_pixbuf_get_pixels (ctrl->pixbuf); + p = ctrl->cache; + for (y = 0; y < side; y++){ + pix = q + (y * r); + for (x = 0; x < side; x++) { + *p++ = *pix++; + *p++ = *pix++; + *p++ = *pix++; + *p++ = *pix++; + } + } + } else { g_print ("control has no pixmap\n"); } + ctrl->build = TRUE; + break; + default: + break; + } + +} + +// composite background, foreground, alpha for xor mode +#define COMPOSE_X(b,f,a) ( ( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) ((b ^ ~f) + b/4 - (b>127? 63 : 0))) * ((guchar) a) ) / 0xff ) +// composite background, foreground, alpha for color mode +#define COMPOSE_N(b,f,a) ( ( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) f) * ((guchar) a) ) / 0xff ) + +static void +sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf) +{ + gint y0, y1, y, x0,x1,x; + guchar * p, * q, a; + + SPCtrl *ctrl = SP_CTRL (item); + + if (!ctrl->defined) return; + if ((!ctrl->filled) && (!ctrl->stroked)) return; + + sp_canvas_prepare_buffer (buf); + + // the control-image is rendered into ctrl->cache + if (!ctrl->build) sp_ctrl_build_cache (ctrl); + + // then we render from ctrl->cache + y0 = MAX (ctrl->box.y0, buf->rect.y0); + y1 = MIN (ctrl->box.y1, buf->rect.y1 - 1); + x0 = MAX (ctrl->box.x0, buf->rect.x0); + x1 = MIN (ctrl->box.x1, buf->rect.x1 - 1); + + bool colormode; + + for (y = y0; y <= y1; y++) { + p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3; + q = ctrl->cache + ((y - ctrl->box.y0) * (ctrl->span*2+1) + (x0 - ctrl->box.x0)) * 4; + for (x = x0; x <= x1; x++) { + a = *(q + 3); + // 00000000 is the only way to get invisible; all other colors with alpha 00 are treated as mode_color with alpha ff + colormode = false; + if (a == 0x00 && !(q[0] == 0x00 && q[1] == 0x00 && q[2] == 0x00)) { + a = 0xff; + colormode = true; + } + if (ctrl->mode == SP_CTRL_MODE_COLOR || colormode) { + p[0] = COMPOSE_N (p[0], q[0], a); + p[1] = COMPOSE_N (p[1], q[1], a); + p[2] = COMPOSE_N (p[2], q[2], a); + q += 4; + p += 3; + } else if (ctrl->mode == SP_CTRL_MODE_XOR) { + p[0] = COMPOSE_X (p[0], q[0], a); + p[1] = COMPOSE_X (p[1], q[1], a); + p[2] = COMPOSE_X (p[2], q[2], a); + q += 4; + p += 3; + } + } + } + ctrl->shown = TRUE; +} + +void SPCtrl::moveto (NR::Point const p) { + sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), NR::Matrix(NR::translate (p))); +} |
