~mc.../inkscape/inkscape

« back to all changes in this revision

Viewing changes to src/display/sodipodi-ctrlrect.cpp

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __INKSCAPE_CTRLRECT_C__
 
2
 
 
3
/*
 
4
 * Simple non-transformed rectangle, usable for rubberband
 
5
 *
 
6
 * Author:
 
7
 *   Lauris Kaplinski <lauris@ximian.com>
 
8
 *   bulia byak <buliabyak@users.sf.net>
 
9
 *   Carl Hetherington <inkscape@carlh.net>
 
10
 *
 
11
 * Copyright (C) 1999-2001 Lauris Kaplinski
 
12
 * Copyright (C) 2000-2001 Ximian, Inc.
 
13
 *
 
14
 * Released under GNU GPL
 
15
 *
 
16
 */
 
17
 
 
18
#include "display-forward.h"
 
19
#include "sp-canvas-util.h"
 
20
#include "sodipodi-ctrlrect.h"
 
21
 
 
22
/*
 
23
 * Currently we do not have point method, as it should always be painted
 
24
 * during some transformation, which takes care of events...
 
25
 *
 
26
 * Corner coords can be in any order - i.e. x1 < x0 is allowed
 
27
 */
 
28
 
 
29
static void sp_ctrlrect_class_init(SPCtrlRectClass *c);
 
30
static void sp_ctrlrect_init(CtrlRect *ctrlrect);
 
31
static void sp_ctrlrect_destroy(GtkObject *object);
 
32
 
 
33
static void sp_ctrlrect_update(SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);
 
34
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf);
 
35
 
 
36
static SPCanvasItemClass *parent_class;
 
37
 
 
38
static const guint DASH_LENGTH = 4;
 
39
 
 
40
GtkType sp_ctrlrect_get_type()
 
41
{
 
42
    static GtkType ctrlrect_type = 0;
 
43
    
 
44
    if (!ctrlrect_type) {
 
45
        GtkTypeInfo ctrlrect_info = {
 
46
            "SPCtrlRect",
 
47
            sizeof(CtrlRect),
 
48
            sizeof(SPCtrlRectClass),
 
49
            (GtkClassInitFunc) sp_ctrlrect_class_init,
 
50
            (GtkObjectInitFunc) sp_ctrlrect_init,
 
51
            NULL, NULL, NULL
 
52
        };
 
53
        ctrlrect_type = gtk_type_unique(SP_TYPE_CANVAS_ITEM, &ctrlrect_info);
 
54
    }
 
55
    return ctrlrect_type;
 
56
}
 
57
 
 
58
static void sp_ctrlrect_class_init(SPCtrlRectClass *c)
 
59
{
 
60
    GtkObjectClass *object_class = (GtkObjectClass *) c;
 
61
    SPCanvasItemClass *item_class = (SPCanvasItemClass *) c;
 
62
 
 
63
    parent_class = (SPCanvasItemClass*) gtk_type_class(sp_canvas_item_get_type());
 
64
 
 
65
    object_class->destroy = sp_ctrlrect_destroy;
 
66
 
 
67
    item_class->update = sp_ctrlrect_update;
 
68
    item_class->render = sp_ctrlrect_render;
 
69
}
 
70
 
 
71
static void sp_ctrlrect_init(CtrlRect *cr)
 
72
{
 
73
    cr->init();
 
74
}
 
75
 
 
76
static void sp_ctrlrect_destroy(GtkObject *object)
 
77
{
 
78
    if (GTK_OBJECT_CLASS(parent_class)->destroy) {
 
79
        (* GTK_OBJECT_CLASS(parent_class)->destroy)(object);
 
80
    }
 
81
}
 
82
 
 
83
/* FIXME: use definitions from somewhere else */
 
84
#define RGBA_R(v) ((v) >> 24)
 
85
#define RGBA_G(v) (((v) >> 16) & 0xff)
 
86
#define RGBA_B(v) (((v) >> 8) & 0xff)
 
87
#define RGBA_A(v) ((v) & 0xff)
 
88
#define COMPOSE(b,f,a) ( ( ((guchar) b) * ((guchar) (0xff - a)) + ((guchar) ((b ^ ~f) + b/4 - (b>127? 63 : 0))) * ((guchar) a) ) / 0xff )
 
89
 
 
90
static void sp_ctrlrect_hline(SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba, guint dashed)
 
91
{
 
92
    if (y >= buf->rect.y0 && y < buf->rect.y1) {
 
93
        guint const r = RGBA_R(rgba);
 
94
        guint const g = RGBA_G(rgba);
 
95
        guint const b = RGBA_B(rgba);
 
96
        guint const a = RGBA_A(rgba);
 
97
        gint const x0 = MAX(buf->rect.x0, xs);
 
98
        gint const x1 = MIN(buf->rect.x1, xe + 1);
 
99
        guchar *p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3;
 
100
        for (gint x = x0; x < x1; x++) {
 
101
            if (!dashed || ((x / DASH_LENGTH) % 2)) {
 
102
                p[0] = COMPOSE(p[0], r, a);
 
103
                p[1] = COMPOSE(p[1], g, a);
 
104
                p[2] = COMPOSE(p[2], b, a);
 
105
            }
 
106
            p += 3;
 
107
        }
 
108
    }
 
109
}
 
110
 
 
111
static void sp_ctrlrect_vline(SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba, guint dashed)
 
112
{
 
113
    if (x >= buf->rect.x0 && x < buf->rect.x1) {
 
114
        guint const r = RGBA_R(rgba);
 
115
        guint const g = RGBA_G(rgba);
 
116
        guint const b = RGBA_B(rgba);
 
117
        guint const a = RGBA_A(rgba);
 
118
        gint const y0 = MAX(buf->rect.y0, ys);
 
119
        gint const y1 = MIN(buf->rect.y1, ye + 1);
 
120
        guchar *p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
 
121
        for (gint y = y0; y < y1; y++) {
 
122
            if (!dashed || ((y / DASH_LENGTH) % 2)) {
 
123
                p[0] = COMPOSE(p[0], r, a);
 
124
                p[1] = COMPOSE(p[1], g, a);
 
125
                p[2] = COMPOSE(p[2], b, a);
 
126
            }
 
127
            p += buf->buf_rowstride;
 
128
        }
 
129
    }
 
130
}
 
131
 
 
132
/** Fills the pixels in [xs, xe)*[ys,ye) clipped to the tile with rgb * a. */
 
133
static void sp_ctrlrect_area(SPCanvasBuf *buf, gint xs, gint ys, gint xe, gint ye, guint32 rgba)
 
134
{
 
135
    guint const r = RGBA_R(rgba);
 
136
    guint const g = RGBA_G(rgba);
 
137
    guint const b = RGBA_B(rgba);
 
138
    guint const a = RGBA_A(rgba);
 
139
    gint const x0 = MAX(buf->rect.x0, xs);
 
140
    gint const x1 = MIN(buf->rect.x1, xe + 1);
 
141
    gint const y0 = MAX(buf->rect.y0, ys);
 
142
    gint const y1 = MIN(buf->rect.y1, ye + 1);
 
143
    for (gint y = y0; y < y1; y++) {
 
144
        guchar *p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3;
 
145
        for (gint x = x0; x < x1; x++) {
 
146
            p[0] = COMPOSE(p[0], r, a);
 
147
            p[1] = COMPOSE(p[1], g, a);
 
148
            p[2] = COMPOSE(p[2], b, a);
 
149
            p += 3;
 
150
        }
 
151
    }
 
152
}
 
153
 
 
154
static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf)
 
155
{
 
156
    SP_CTRLRECT(item)->render(buf);
 
157
}
 
158
 
 
159
 
 
160
static void sp_ctrlrect_update(SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)
 
161
{
 
162
    SP_CTRLRECT(item)->update(affine, flags);
 
163
}
 
164
 
 
165
 
 
166
 
 
167
void CtrlRect::init()
 
168
{
 
169
    _has_fill = false;
 
170
    _dashed = false;
 
171
    _shadow = 0;
 
172
 
 
173
    _area.x0 = _area.y0 = 0;
 
174
    _area.x1 = _area.y1 = -1;
 
175
 
 
176
    _shadow_size = 0;
 
177
 
 
178
    _border_color = 0x000000ff;
 
179
    _fill_color = 0xffffffff;
 
180
    _shadow_color = 0x000000ff;
 
181
}
 
182
 
 
183
 
 
184
void CtrlRect::render(SPCanvasBuf *buf)
 
185
{
 
186
    if ((_area.x0 < buf->rect.x1) &&
 
187
        (_area.y0 < buf->rect.y1) &&
 
188
        ((_area.x1 + _shadow_size) >= buf->rect.x0) &&
 
189
        ((_area.y1 + _shadow_size) >= buf->rect.y0)) {
 
190
        sp_canvas_prepare_buffer(buf);
 
191
 
 
192
        /* Top */
 
193
        sp_ctrlrect_hline(buf, _area.y0, _area.x0, _area.x1, _border_color, _dashed);
 
194
        /* Bottom */
 
195
        sp_ctrlrect_hline(buf, _area.y1, _area.x0, _area.x1, _border_color, _dashed);
 
196
        /* Left */
 
197
        sp_ctrlrect_vline(buf, _area.x0, _area.y0 + 1, _area.y1 - 1, _border_color, _dashed);
 
198
        /* Right */
 
199
        sp_ctrlrect_vline(buf, _area.x1, _area.y0 + 1, _area.y1 - 1, _border_color, _dashed);
 
200
        if (_shadow_size > 0) {
 
201
            /* Right shadow */
 
202
            sp_ctrlrect_area(buf, _area.x1 + 1, _area.y0 + _shadow_size,
 
203
                             _area.x1 + _shadow_size, _area.y1 + _shadow_size, _shadow_color);
 
204
            /* Bottom shadow */
 
205
            sp_ctrlrect_area(buf, _area.x0 + _shadow_size, _area.y1 + 1,
 
206
                             _area.x1, _area.y1 + _shadow_size, _shadow_color);
 
207
        }
 
208
        if (_has_fill) {
 
209
            /* Fill */
 
210
            sp_ctrlrect_area(buf, _area.x0 + 1, _area.y0 + 1,
 
211
                             _area.x1 - 1, _area.y1 - 1, _fill_color);
 
212
        }
 
213
    }
 
214
}
 
215
 
 
216
 
 
217
void CtrlRect::update(NR::Matrix const &affine, unsigned int flags)
 
218
{
 
219
    if (((SPCanvasItemClass *) parent_class)->update) {
 
220
        ((SPCanvasItemClass *) parent_class)->update(this, affine, flags);
 
221
    }
 
222
 
 
223
    sp_canvas_item_reset_bounds(this);
 
224
 
 
225
    /* Request redraw old */
 
226
    if (!_has_fill) {
 
227
        /* Top */
 
228
        sp_canvas_request_redraw(canvas,
 
229
                                 _area.x0 - 1, _area.y0 - 1,
 
230
                                 _area.x1 + 1, _area.y0 + 1);
 
231
        /* Left */
 
232
        sp_canvas_request_redraw(canvas,
 
233
                                 _area.x0 - 1, _area.y0 - 1,
 
234
                                 _area.x0 + 1, _area.y1 + 1);
 
235
        /* Right */
 
236
        sp_canvas_request_redraw(canvas,
 
237
                                 _area.x1 - 1, _area.y0 - 1,
 
238
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
239
        /* Bottom */
 
240
        sp_canvas_request_redraw(canvas,
 
241
                                 _area.x0 - 1, _area.y1 - 1,
 
242
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
243
    } else {
 
244
        sp_canvas_request_redraw(canvas,
 
245
                                 _area.x0 - 1, _area.y0 - 1,
 
246
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
247
    }
 
248
 
 
249
    NR::Rect bbox(_rect.min() * affine, _rect.max() * affine);
 
250
    
 
251
    _area.x0 = (int) floor(bbox.min()[NR::X] + 0.5);
 
252
    _area.y0 = (int) floor(bbox.min()[NR::Y] + 0.5);
 
253
    _area.x1 = (int) floor(bbox.max()[NR::X] + 0.5);
 
254
    _area.y1 = (int) floor(bbox.max()[NR::Y] + 0.5);
 
255
    
 
256
    _shadow_size = _shadow;
 
257
    
 
258
    /* Request redraw new */
 
259
    if (!_has_fill) {
 
260
        /* Top */
 
261
        sp_canvas_request_redraw(canvas,
 
262
                                 _area.x0 - 1, _area.y0 - 1,
 
263
                                 _area.x1 + 1, _area.y0 + 1);
 
264
        /* Left */
 
265
        sp_canvas_request_redraw(canvas,
 
266
                                 _area.x0 - 1, _area.y0 - 1,
 
267
                                 _area.x0 + 1, _area.y1 + 1);
 
268
        /* Right */
 
269
        sp_canvas_request_redraw(canvas,
 
270
                                 _area.x1 - 1, _area.y0 - 1,
 
271
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
272
        /* Bottom */
 
273
        sp_canvas_request_redraw(canvas,
 
274
                                 _area.x0 - 1, _area.y1 - 1,
 
275
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
276
    } else {
 
277
        sp_canvas_request_redraw(canvas,
 
278
                                 _area.x0 - 1, _area.y0 - 1,
 
279
                                 _area.x1 + _shadow_size + 1, _area.y1 + _shadow_size + 1);
 
280
    }
 
281
    
 
282
    x1 = _area.x0 - 1;
 
283
    y1 = _area.y0 - 1;
 
284
    x2 = _area.x1 + _shadow_size + 1;
 
285
    y2 = _area.y1 + _shadow_size + 1;
 
286
}
 
287
 
 
288
 
 
289
void CtrlRect::setColor(guint32 b, bool h, guint f)
 
290
{
 
291
    _border_color = b;
 
292
    _has_fill = h;
 
293
    _fill_color = f;
 
294
    _requestUpdate();
 
295
}
 
296
 
 
297
void CtrlRect::setShadow(int s, guint c)
 
298
{
 
299
    _shadow = s;
 
300
    _shadow_color = c;
 
301
    _requestUpdate();
 
302
}
 
303
 
 
304
void CtrlRect::setRectangle(NR::Rect const &r)
 
305
{
 
306
    _rect = r;
 
307
    _requestUpdate();
 
308
}
 
309
 
 
310
void CtrlRect::setDashed(bool d)
 
311
{
 
312
    _dashed = d;
 
313
    _requestUpdate();
 
314
}
 
315
 
 
316
void CtrlRect::_requestUpdate()
 
317
{
 
318
    sp_canvas_item_request_update(SP_CANVAS_ITEM(this));
 
319
}
 
320
 
 
321
/*
 
322
  Local Variables:
 
323
  mode:c++
 
324
  c-file-style:"stroustrup"
 
325
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
326
  indent-tabs-mode:nil
 
327
  fill-column:99
 
328
  End:
 
329
*/
 
330
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :