summaryrefslogtreecommitdiffstats
path: root/src/display/sodipodi-ctrlrect.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/display/sodipodi-ctrlrect.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/display/sodipodi-ctrlrect.cpp')
-rw-r--r--src/display/sodipodi-ctrlrect.cpp330
1 files changed, 330 insertions, 0 deletions
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 <lauris@ximian.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Carl Hetherington <inkscape@carlh.net>
+ *
+ * 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 :