~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/display/guideline.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Kees Cook, Ted Gould
  • Date: 2008-02-10 14:20:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080210142016-vcnb2zqyhszu0xvb
Tags: 0.46~pre1-0ubuntu1
[ Kees Cook ]
* debian/control:
  - add libgtkspell-dev build-dep to gain GtkSpell features (LP: #183547).
  - update Standards version (no changes needed).
  - add Vcs and Homepage fields.
  - switch to new python-lxml dep.
* debian/{control,rules}: switch from dpatch to quilt for more sanity.
* debian/patches/20_fix_glib_and_gxx43_ftbfs.patch:
  - merged against upstream fixes.
  - added additional fixes for newly written code.
* debian/rules: enable parallel building.

[ Ted Gould ]
* Updating POTFILES.in to make it so things build correctly.
* debian/control:
  - add ImageMagick++ and libboost-dev to build-deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#define __SP_GUIDELINE_C__
2
2
 
3
3
/*
4
 
 * Infinite horizontal/vertical line
 
4
 * Horizontal/vertical but can also be angled line
5
5
 *
6
 
 * Author:
 
6
 * Authors:
7
7
 *   Lauris Kaplinski <lauris@kaplinski.com>
 
8
 *   Johan Engelen
8
9
 *
9
10
 * Copyright (C) 2000-2002 Lauris Kaplinski
 
11
 * Copyright (C) 2007 Johan Engelen
10
12
 *
11
13
 * Released under GNU GPL, read the file 'COPYING' for more information
12
14
 */
26
28
 
27
29
static double sp_guideline_point(SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_item);
28
30
 
 
31
static void sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba);
 
32
 
29
33
static SPCanvasItemClass *parent_class;
30
34
 
31
35
GType sp_guideline_get_type()
33
37
    static GType guideline_type = 0;
34
38
 
35
39
    if (!guideline_type) {
36
 
        static const GTypeInfo guideline_info =
37
 
            {
38
 
                sizeof (SPGuideLineClass),
39
 
                NULL, NULL,
40
 
                (GClassInitFunc) sp_guideline_class_init,
41
 
                NULL, NULL,
42
 
                sizeof (SPGuideLine),
43
 
                16,
44
 
                (GInstanceInitFunc) sp_guideline_init,
45
 
                        NULL,
46
 
            };
47
 
        
 
40
        static GTypeInfo const guideline_info = {
 
41
            sizeof (SPGuideLineClass),
 
42
            NULL, NULL,
 
43
            (GClassInitFunc) sp_guideline_class_init,
 
44
            NULL, NULL,
 
45
            sizeof (SPGuideLine),
 
46
            16,
 
47
            (GInstanceInitFunc) sp_guideline_init,
 
48
            NULL,
 
49
        };
 
50
 
48
51
        guideline_type = g_type_register_static(SP_TYPE_CANVAS_ITEM, "SPGuideLine", &guideline_info, (GTypeFlags) 0);
49
52
    }
50
 
    
 
53
 
51
54
    return guideline_type;
52
55
}
53
56
 
54
57
static void sp_guideline_class_init(SPGuideLineClass *c)
55
58
{
56
 
        parent_class = (SPCanvasItemClass*) g_type_class_peek_parent(c);
57
 
 
58
 
        GtkObjectClass *object_class = (GtkObjectClass *) c;
59
 
        object_class->destroy = sp_guideline_destroy;
60
 
 
61
 
        SPCanvasItemClass *item_class = (SPCanvasItemClass *) c;
62
 
        item_class->update = sp_guideline_update;
63
 
        item_class->render = sp_guideline_render;
64
 
        item_class->point = sp_guideline_point;
 
59
    parent_class = (SPCanvasItemClass*) g_type_class_peek_parent(c);
 
60
 
 
61
    GtkObjectClass *object_class = (GtkObjectClass *) c;
 
62
    object_class->destroy = sp_guideline_destroy;
 
63
 
 
64
    SPCanvasItemClass *item_class = (SPCanvasItemClass *) c;
 
65
    item_class->update = sp_guideline_update;
 
66
    item_class->render = sp_guideline_render;
 
67
    item_class->point = sp_guideline_point;
65
68
}
66
69
 
67
70
static void sp_guideline_init(SPGuideLine *gl)
68
71
{
69
72
    gl->rgba = 0x0000ff7f;
70
 
    
71
 
    gl->vertical = 0;
 
73
 
 
74
    gl->normal_to_line = Geom::Point(0,1);
 
75
    gl->angle = 3.14159265358979323846/2;
 
76
    gl->point_on_line = Geom::Point(0,0);
72
77
    gl->sensitive = 0;
73
78
}
74
79
 
80
85
static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
81
86
{
82
87
    SPGuideLine const *gl = SP_GUIDELINE (item);
83
 
    
 
88
 
84
89
    sp_canvas_prepare_buffer(buf);
85
 
    
 
90
 
86
91
    unsigned int const r = NR_RGBA32_R (gl->rgba);
87
92
    unsigned int const g = NR_RGBA32_G (gl->rgba);
88
93
    unsigned int const b = NR_RGBA32_B (gl->rgba);
89
94
    unsigned int const a = NR_RGBA32_A (gl->rgba);
90
 
    
91
 
    int p0, p1, step;
92
 
    unsigned char *d;
93
 
 
94
 
    if (gl->vertical) {
95
 
 
96
 
        if (gl->position < buf->rect.x0 || gl->position >= buf->rect.x1) {
97
 
            return;
98
 
        }
99
 
 
100
 
        p0 = buf->rect.y0;
101
 
        p1 = buf->rect.y1;
102
 
        step = buf->buf_rowstride;
103
 
        d = buf->buf + 3 * (gl->position - buf->rect.x0);
104
 
        
 
95
 
 
96
    if (gl->is_vertical()) {
 
97
        int position = gl->point_on_line[Geom::X];
 
98
        if (position < buf->rect.x0 || position >= buf->rect.x1) {
 
99
            return;
 
100
        }
 
101
 
 
102
        int p0 = buf->rect.y0;
 
103
        int p1 = buf->rect.y1;
 
104
        int step = buf->buf_rowstride;
 
105
        unsigned char *d = buf->buf + 3 * (position - buf->rect.x0);
 
106
 
 
107
        for (int p = p0; p < p1; p++) {
 
108
            d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
 
109
            d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
 
110
            d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
 
111
            d += step;
 
112
        }
 
113
    } else if (gl->is_horizontal()) {
 
114
        int position = gl->point_on_line[Geom::Y];
 
115
        if (position < buf->rect.y0 || position >= buf->rect.y1) {
 
116
            return;
 
117
        }
 
118
 
 
119
        int p0 = buf->rect.x0;
 
120
        int p1 = buf->rect.x1;
 
121
        int step = 3;
 
122
        unsigned char *d = buf->buf + (position - buf->rect.y0) * buf->buf_rowstride;
 
123
 
 
124
        for (int p = p0; p < p1; p++) {
 
125
            d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
 
126
            d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
 
127
            d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
 
128
            d += step;
 
129
        }
105
130
    } else {
106
 
 
107
 
        if (gl->position < buf->rect.y0 || gl->position >= buf->rect.y1) {
108
 
            return;
109
 
        }
110
 
        
111
 
        p0 = buf->rect.x0;
112
 
        p1 = buf->rect.x1;
113
 
        step = 3;
114
 
        d = buf->buf + (gl->position - buf->rect.y0) * buf->buf_rowstride;
115
 
    }
116
 
 
117
 
    for (int p = p0; p < p1; p++) {
118
 
        d[0] = NR_COMPOSEN11_1111(r, a, d[0]);
119
 
        d[1] = NR_COMPOSEN11_1111(g, a, d[1]);
120
 
        d[2] = NR_COMPOSEN11_1111(b, a, d[2]);
121
 
        d += step;
 
131
        // render angled line, once intersection has been detected, draw from there.
 
132
        Geom::Point parallel_to_line( gl->normal_to_line[Geom::Y],
 
133
                                      /*should be minus, but inverted y axis*/ gl->normal_to_line[Geom::X]); 
 
134
 
 
135
        //try to intersect with left vertical of rect
 
136
        double y_intersect_left = (buf->rect.x0 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
 
137
        if ( (y_intersect_left >= buf->rect.y0) && (y_intersect_left <= buf->rect.y1) ) {
 
138
            // intersects with left vertical!
 
139
            double y_intersect_right = (buf->rect.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
 
140
            sp_guideline_drawline (buf, buf->rect.x0, round(y_intersect_left), buf->rect.x1, round(y_intersect_right), gl->rgba);
 
141
            return;
 
142
        }
 
143
 
 
144
        //try to intersect with right vertical of rect
 
145
        double y_intersect_right = (buf->rect.x1 - gl->point_on_line[Geom::X]) * parallel_to_line[Geom::Y] / parallel_to_line[Geom::X] + gl->point_on_line[Geom::Y];
 
146
        if ( (y_intersect_right >= buf->rect.y0) && (y_intersect_right <= buf->rect.y1) ) {
 
147
            // intersects with right vertical!
 
148
            sp_guideline_drawline (buf, buf->rect.x1, round(y_intersect_right), buf->rect.x0, round(y_intersect_left), gl->rgba);
 
149
            return;
 
150
        }
 
151
 
 
152
        //try to intersect with top horizontal of rect
 
153
        double x_intersect_top = (buf->rect.y0 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
 
154
        if ( (x_intersect_top >= buf->rect.x0) && (x_intersect_top <= buf->rect.x1) ) {
 
155
            // intersects with top horizontal!
 
156
            double x_intersect_bottom = (buf->rect.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
 
157
            sp_guideline_drawline (buf, round(x_intersect_top), buf->rect.y0, round(x_intersect_bottom), buf->rect.y1, gl->rgba);
 
158
            return;
 
159
        }
 
160
 
 
161
        //try to intersect with bottom horizontal of rect
 
162
        double x_intersect_bottom = (buf->rect.y1 - gl->point_on_line[Geom::Y]) * parallel_to_line[Geom::X] / parallel_to_line[Geom::Y] + gl->point_on_line[Geom::X];
 
163
        if ( (x_intersect_top >= buf->rect.x0) && (x_intersect_top <= buf->rect.x1) ) {
 
164
            // intersects with bottom horizontal!
 
165
            sp_guideline_drawline (buf, round(x_intersect_bottom), buf->rect.y1, round(x_intersect_top), buf->rect.y0, gl->rgba);
 
166
            return;
 
167
        }
122
168
    }
123
169
}
124
170
 
130
176
        ((SPCanvasItemClass *) parent_class)->update(item, affine, flags);
131
177
    }
132
178
 
133
 
    if (gl->vertical) {
134
 
        gl->position = (int) (affine[4] + 0.5);
135
 
        sp_canvas_update_bbox (item, gl->position, -1000000, gl->position + 1, 1000000);
 
179
    gl->point_on_line[Geom::X] = affine[4] +0.5;
 
180
    gl->point_on_line[Geom::Y] = affine[5] -0.5;
 
181
 
 
182
    if (gl->is_horizontal()) {
 
183
        sp_canvas_update_bbox (item, -1000000, gl->point_on_line[Geom::Y], 1000000, gl->point_on_line[Geom::Y] + 1);
 
184
    } else if (gl->is_vertical()) {
 
185
        sp_canvas_update_bbox (item, gl->point_on_line[Geom::X], -1000000, gl->point_on_line[Geom::X]+1, 1000000);
136
186
    } else {
137
 
        gl->position = (int) (affine[5] - 0.5);
138
 
        sp_canvas_update_bbox (item, -1000000, gl->position, 1000000, gl->position + 1);
 
187
        sp_canvas_update_bbox (item, -1000000, -1000000, 1000000, 1000000);
139
188
    }
140
189
}
141
190
 
 
191
// Returns 0.0 if point is on the guideline
142
192
static double sp_guideline_point(SPCanvasItem *item, NR::Point p, SPCanvasItem **actual_item)
143
193
{
144
194
    SPGuideLine *gl = SP_GUIDELINE (item);
149
199
 
150
200
    *actual_item = item;
151
201
 
152
 
    if (gl->vertical) {
153
 
        return MAX(fabs(gl->position - p[NR::X])-1, 0);
154
 
    } else {
155
 
        return MAX(fabs(gl->position - p[NR::Y])-1, 0);
156
 
    }
 
202
    Geom::Point vec(gl->normal_to_line[Geom::X], - gl->normal_to_line[Geom::Y]);
 
203
    double distance = Geom::dot((p.to_2geom() - gl->point_on_line), vec);
 
204
    return MAX(fabs(distance)-1, 0);
157
205
}
158
206
 
159
 
SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, double position, unsigned int vertical)
 
207
SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line, Geom::Point normal)
160
208
{
161
209
    SPCanvasItem *item = sp_canvas_item_new(parent, SP_TYPE_GUIDELINE, NULL);
162
210
 
163
211
    SPGuideLine *gl = SP_GUIDELINE(item);
164
212
 
165
 
    gl->vertical = vertical;
166
 
    sp_guideline_set_position(gl, position);
 
213
    normal.normalize();
 
214
    gl->normal_to_line = normal;
 
215
    gl->angle = tan( -gl->normal_to_line[Geom::X] / gl->normal_to_line[Geom::Y]);
 
216
    sp_guideline_set_position(gl, point_on_line);
167
217
 
168
218
    return item;
169
219
}
170
220
 
171
 
void sp_guideline_set_position(SPGuideLine *gl, double position)
172
 
{
173
 
    sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), 
174
 
                                   NR::Matrix(NR::translate(position, position)));
 
221
void sp_guideline_set_position(SPGuideLine *gl, Geom::Point point_on_line)
 
222
{
 
223
    sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl),
 
224
                                   NR::Matrix(NR::translate(point_on_line)));
 
225
}
 
226
 
 
227
void sp_guideline_set_normal(SPGuideLine *gl, Geom::Point normal_to_line)
 
228
{
 
229
    gl->normal_to_line = normal_to_line;
 
230
    gl->angle = tan( -normal_to_line[Geom::X] / normal_to_line[Geom::Y]);
 
231
 
 
232
    sp_canvas_item_request_update(SP_CANVAS_ITEM (gl));
175
233
}
176
234
 
177
235
void sp_guideline_set_color(SPGuideLine *gl, unsigned int rgba)
186
244
    gl->sensitive = sensitive;
187
245
}
188
246
 
 
247
//##########################################################
 
248
// Line rendering
 
249
#define SAFE_SETPIXEL   //undefine this when it is certain that setpixel is never called with invalid params
 
250
 
 
251
/**
 
252
    \brief  This function renders a pixel on a particular buffer.
 
253
 
 
254
    The topleft of the buffer equals
 
255
                        ( rect.x0 , rect.y0 )  in screen coordinates
 
256
                        ( 0 , 0 )  in setpixel coordinates
 
257
    The bottomright of the buffer equals
 
258
                        ( rect.x1 , rect,y1 )  in screen coordinates
 
259
                        ( rect.x1 - rect.x0 , rect.y1 - rect.y0 )  in setpixel coordinates
 
260
*/
 
261
static void
 
262
sp_guideline_setpixel (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
 
263
{
 
264
#ifdef SAFE_SETPIXEL
 
265
    if ( (x >= buf->rect.x0) && (x < buf->rect.x1) && (y >= buf->rect.y0) && (y < buf->rect.y1) ) {
 
266
#endif
 
267
        guint r, g, b, a;
 
268
        r = NR_RGBA32_R (rgba);
 
269
        g = NR_RGBA32_G (rgba);
 
270
        b = NR_RGBA32_B (rgba);
 
271
        a = NR_RGBA32_A (rgba);
 
272
        guchar * p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
 
273
        p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
 
274
        p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
 
275
        p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
 
276
#ifdef SAFE_SETPIXEL
 
277
    }
 
278
#endif
 
279
}
 
280
 
 
281
/**
 
282
    \brief  This function renders a line on a particular canvas buffer,
 
283
            using Bresenham's line drawing function.
 
284
            http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
 
285
            Coordinates are interpreted as SCREENcoordinates
 
286
*/
 
287
static void
 
288
sp_guideline_drawline (SPCanvasBuf *buf, gint x0, gint y0, gint x1, gint y1, guint32 rgba)
 
289
{
 
290
    int dy = y1 - y0;
 
291
    int dx = x1 - x0;
 
292
    int stepx, stepy;
 
293
 
 
294
    if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
 
295
    if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
 
296
    dy <<= 1;                                                  // dy is now 2*dy
 
297
    dx <<= 1;                                                  // dx is now 2*dx
 
298
 
 
299
    sp_guideline_setpixel(buf, x0, y0, rgba);
 
300
    if (dx > dy) {
 
301
        int fraction = dy - (dx >> 1);                         // same as 2*dy - dx
 
302
        while (x0 != x1) {
 
303
            if (fraction >= 0) {
 
304
                y0 += stepy;
 
305
                fraction -= dx;                                // same as fraction -= 2*dx
 
306
            }
 
307
            x0 += stepx;
 
308
            fraction += dy;                                    // same as fraction -= 2*dy
 
309
            sp_guideline_setpixel(buf, x0, y0, rgba);
 
310
        }
 
311
    } else {
 
312
        int fraction = dx - (dy >> 1);
 
313
        while (y0 != y1) {
 
314
            if (fraction >= 0) {
 
315
                x0 += stepx;
 
316
                fraction -= dy;
 
317
            }
 
318
            y0 += stepy;
 
319
            fraction += dx;
 
320
            sp_guideline_setpixel(buf, x0, y0, rgba);
 
321
        }
 
322
    }
 
323
}
 
324
 
189
325
/*
190
326
  Local Variables:
191
327
  mode:c++
195
331
  fill-column:99
196
332
  End:
197
333
*/
198
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
 
334
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :