From 179fa413b047bede6e32109e2ce82437c5fb8d34 Mon Sep 17 00:00:00 2001 From: MenTaLguY Date: Mon, 16 Jan 2006 02:36:01 +0000 Subject: moving trunk for module inkscape (bzr r1) --- src/display/sodipodi-ctrlrect.cpp | 330 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 src/display/sodipodi-ctrlrect.cpp (limited to 'src/display/sodipodi-ctrlrect.cpp') diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp new file mode 100644 index 000000000..05449f2bb --- /dev/null +++ b/src/display/sodipodi-ctrlrect.cpp @@ -0,0 +1,330 @@ +#define __INKSCAPE_CTRLRECT_C__ + +/* + * Simple non-transformed rectangle, usable for rubberband + * + * Author: + * Lauris Kaplinski + * bulia byak + * Carl Hetherington + * + * Copyright (C) 1999-2001 Lauris Kaplinski + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL + * + */ + +#include "display-forward.h" +#include "sp-canvas-util.h" +#include "sodipodi-ctrlrect.h" + +/* + * Currently we do not have point method, as it should always be painted + * during some transformation, which takes care of events... + * + * Corner coords can be in any order - i.e. x1 < x0 is allowed + */ + +static void sp_ctrlrect_class_init(SPCtrlRectClass *c); +static void sp_ctrlrect_init(CtrlRect *ctrlrect); +static void sp_ctrlrect_destroy(GtkObject *object); + +static void sp_ctrlrect_update(SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags); +static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf); + +static SPCanvasItemClass *parent_class; + +static const guint DASH_LENGTH = 4; + +GtkType sp_ctrlrect_get_type() +{ + static GtkType ctrlrect_type = 0; + + if (!ctrlrect_type) { + GtkTypeInfo ctrlrect_info = { + "SPCtrlRect", + sizeof(CtrlRect), + sizeof(SPCtrlRectClass), + (GtkClassInitFunc) sp_ctrlrect_class_init, + (GtkObjectInitFunc) sp_ctrlrect_init, + NULL, NULL, NULL + }; + ctrlrect_type = gtk_type_unique(SP_TYPE_CANVAS_ITEM, &ctrlrect_info); + } + return ctrlrect_type; +} + +static void sp_ctrlrect_class_init(SPCtrlRectClass *c) +{ + GtkObjectClass *object_class = (GtkObjectClass *) c; + SPCanvasItemClass *item_class = (SPCanvasItemClass *) c; + + parent_class = (SPCanvasItemClass*) gtk_type_class(sp_canvas_item_get_type()); + + object_class->destroy = sp_ctrlrect_destroy; + + item_class->update = sp_ctrlrect_update; + item_class->render = sp_ctrlrect_render; +} + +static void sp_ctrlrect_init(CtrlRect *cr) +{ + cr->init(); +} + +static void sp_ctrlrect_destroy(GtkObject *object) +{ + if (GTK_OBJECT_CLASS(parent_class)->destroy) { + (* GTK_OBJECT_CLASS(parent_class)->destroy)(object); + } +} + +/* FIXME: use definitions from somewhere else */ +#define RGBA_R(v) ((v) >> 24) +#define RGBA_G(v) (((v) >> 16) & 0xff) +#define RGBA_B(v) (((v) >> 8) & 0xff) +#define RGBA_A(v) ((v) & 0xff) +#define COMPOSE(b,f,a) ( ( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) ((b ^ ~f) + b/4 - (b>127? 63 : 0))) * ((guchar) a) ) / 0xff ) + +static void sp_ctrlrect_hline(SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba, guint dashed) +{ + if (y >= buf->rect.y0 && y < buf->rect.y1) { + guint const r = RGBA_R(rgba); + guint const g = RGBA_G(rgba); + guint const b = RGBA_B(rgba); + guint const a = RGBA_A(rgba); + gint const x0 = MAX(buf->rect.x0, xs); + gint const x1 = MIN(buf->rect.x1, xe + 1); + guchar *p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3; + for (gint x = x0; x < x1; x++) { + if (!dashed || ((x / DASH_LENGTH) % 2)) { + p[0] = COMPOSE(p[0], r, a); + p[1] = COMPOSE(p[1], g, a); + p[2] = COMPOSE(p[2], b, a); + } + p += 3; + } + } +} + +static void sp_ctrlrect_vline(SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba, guint dashed) +{ + if (x >= buf->rect.x0 && x < buf->rect.x1) { + guint const r = RGBA_R(rgba); + guint const g = RGBA_G(rgba); + guint const b = RGBA_B(rgba); + guint const a = RGBA_A(rgba); + gint const y0 = MAX(buf->rect.y0, ys); + gint const y1 = MIN(buf->rect.y1, ye + 1); + guchar *p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3; + for (gint y = y0; y < y1; y++) { + if (!dashed || ((y / DASH_LENGTH) % 2)) { + p[0] = COMPOSE(p[0], r, a); + p[1] = COMPOSE(p[1], g, a); + p[2] = COMPOSE(p[2], b, a); + } + p += buf->buf_rowstride; + } + } +} + +/** Fills the pixels in [xs, xe)*[ys,ye) clipped to the tile with rgb * a. */ +static void sp_ctrlrect_area(SPCanvasBuf *buf, gint xs, gint ys, gint xe, gint ye, guint32 rgba) +{ + guint const r = RGBA_R(rgba); + guint const g = RGBA_G(rgba); + guint const b = RGBA_B(rgba); + guint const a = RGBA_A(rgba); + gint const x0 = MAX(buf->rect.x0, xs); + gint const x1 = MIN(buf->rect.x1, xe + 1); + gint const y0 = MAX(buf->rect.y0, ys); + gint const y1 = MIN(buf->rect.y1, ye + 1); + for (gint y = y0; y < y1; y++) { + guchar *p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3; + for (gint x = x0; x < x1; x++) { + p[0] = COMPOSE(p[0], r, a); + p[1] = COMPOSE(p[1], g, a); + p[2] = COMPOSE(p[2], b, a); + p += 3; + } + } +} + +static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf) +{ + SP_CTRLRECT(item)->render(buf); +} + + +static void sp_ctrlrect_update(SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags) +{ + SP_CTRLRECT(item)->update(affine, flags); +} + + + +void CtrlRect::init() +{ + _has_fill = false; + _dashed = false; + _shadow = 0; + + _area.x0 = _area.y0 = 0; + _area.x1 = _area.y1 = -1; + + _shadow_size = 0; + + _border_color = 0x000000ff; + _fill_color = 0xffffffff; + _shadow_color = 0x000000ff; +} + + +void CtrlRect::render(SPCanvasBuf *buf) +{ + if ((_area.x0 < buf->rect.x1) && + (_area.y0 < buf->rect.y1) && + ((_area.x1 + _shadow_size) >= buf->rect.x0) && + ((_area.y1 + _shadow_size) >= buf->rect.y0)) { + sp_canvas_prepare_buffer(buf); + + /* Top */ + sp_ctrlrect_hline(buf, _area.y0, _area.x0, _area.x1, _border_color, _dashed); + /* Bottom */ + sp_ctrlrect_hline(buf, _area.y1, _area.x0, _area.x1, _border_color, _dashed); + /* Left */ + sp_ctrlrect_vline(buf, _area.x0, _area.y0 + 1, _area.y1 - 1, _border_color, _dashed); + /* Right */ + sp_ctrlrect_vline(buf, _area.x1, _area.y0 + 1, _area.y1 - 1, _border_color, _dashed); + if (_shadow_size > 0) { + /* Right shadow */ + sp_ctrlrect_area(buf, _area.x1 + 1, _area.y0 + _shadow_size, + _area.x1 + _shadow_size, _area.y1 + _shadow_size, _shadow_color); + /* Bottom shadow */ + sp_ctrlrect_area(buf, _area.x0 + _shadow_size, _area.y1 + 1, + _area.x1, _area.y1 + _shadow_size, _shadow_color); + } + if (_has_fill) { + /* Fill */ + sp_ctrlrect_area(buf, _area.x0 + 1, _area.y0 + 1, + _area.x1 - 1, _area.y1 - 1, _fill_color); + } + } +} + + +void CtrlRect::update(NR::Matrix const &affine, unsigned int flags) +{ + if (((SPCanvasItemClass *) parent_class)->update) { + ((SPCanvasItemClass *) parent_class)->update(this, affine, flags); + } + + sp_canvas_item_reset_bounds(this); + + /* Request redraw old */ + if (!_has_fill) { + /* Top */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x1 + 1, _area.y0 + 1); + /* Left */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x0 + 1, _area.y1 + 1); + /* Right */ + sp_canvas_request_redraw(canvas, + _area.x1 - 1, _area.y0 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + /* Bottom */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y1 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + } else { + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + } + + NR::Rect bbox(_rect.min() * affine, _rect.max() * affine); + + _area.x0 = (int) floor(bbox.min()[NR::X] + 0.5); + _area.y0 = (int) floor(bbox.min()[NR::Y] + 0.5); + _area.x1 = (int) floor(bbox.max()[NR::X] + 0.5); + _area.y1 = (int) floor(bbox.max()[NR::Y] + 0.5); + + _shadow_size = _shadow; + + /* Request redraw new */ + if (!_has_fill) { + /* Top */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x1 + 1, _area.y0 + 1); + /* Left */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x0 + 1, _area.y1 + 1); + /* Right */ + sp_canvas_request_redraw(canvas, + _area.x1 - 1, _area.y0 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + /* Bottom */ + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y1 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + } else { + sp_canvas_request_redraw(canvas, + _area.x0 - 1, _area.y0 - 1, + _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1); + } + + x1 = _area.x0 - 1; + y1 = _area.y0 - 1; + x2 = _area.x1 + _shadow_size + 1; + y2 = _area.y1 + _shadow_size + 1; +} + + +void CtrlRect::setColor(guint32 b, bool h, guint f) +{ + _border_color = b; + _has_fill = h; + _fill_color = f; + _requestUpdate(); +} + +void CtrlRect::setShadow(int s, guint c) +{ + _shadow = s; + _shadow_color = c; + _requestUpdate(); +} + +void CtrlRect::setRectangle(NR::Rect const &r) +{ + _rect = r; + _requestUpdate(); +} + +void CtrlRect::setDashed(bool d) +{ + _dashed = d; + _requestUpdate(); +} + +void CtrlRect::_requestUpdate() +{ + sp_canvas_item_request_update(SP_CANVAS_ITEM(this)); +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : -- cgit v1.2.3