Code

disable filters in outline mode
[inkscape.git] / src / display / canvas-grid.cpp
1 #define SP_CANVAS_GRID_C
3 /*
4  * SPCGrid
5  *
6  * Copyright (C) Lauris Kaplinski 2000
7  *
8  */
11 #include "sp-canvas-util.h"
12 #include "canvas-grid.h"
13 #include "display-forward.h"
14 #include <libnr/nr-pixops.h>
16 enum {
17     ARG_0,
18     ARG_ORIGINX,
19     ARG_ORIGINY,
20     ARG_SPACINGX,
21     ARG_SPACINGY,
22     ARG_COLOR,
23     ARG_EMPCOLOR,
24     ARG_EMPSPACING
25 };
28 static void sp_cgrid_class_init (SPCGridClass *klass);
29 static void sp_cgrid_init (SPCGrid *grid);
30 static void sp_cgrid_destroy (GtkObject *object);
31 static void sp_cgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
33 static void sp_cgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);
34 static void sp_cgrid_render (SPCanvasItem *item, SPCanvasBuf *buf);
36 static SPCanvasItemClass * parent_class;
38 GtkType
39 sp_cgrid_get_type (void)
40 {
41     static GtkType cgrid_type = 0;
43     if (!cgrid_type) {
44         GtkTypeInfo cgrid_info = {
45             "SPCGrid",
46             sizeof (SPCGrid),
47             sizeof (SPCGridClass),
48             (GtkClassInitFunc) sp_cgrid_class_init,
49             (GtkObjectInitFunc) sp_cgrid_init,
50             NULL, NULL,
51             (GtkClassInitFunc) NULL
52         };
53         cgrid_type = gtk_type_unique (sp_canvas_item_get_type (), &cgrid_info);
54     }
55     return cgrid_type;
56 }
58 static void
59 sp_cgrid_class_init (SPCGridClass *klass)
60 {
61     GtkObjectClass *object_class;
62     SPCanvasItemClass *item_class;
64     object_class = (GtkObjectClass *) klass;
65     item_class = (SPCanvasItemClass *) klass;
67     parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());
69     gtk_object_add_arg_type ("SPCGrid::originx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINX);
70     gtk_object_add_arg_type ("SPCGrid::originy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINY);
71     gtk_object_add_arg_type ("SPCGrid::spacingx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGX);
72     gtk_object_add_arg_type ("SPCGrid::spacingy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGY);
73     gtk_object_add_arg_type ("SPCGrid::color", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COLOR);
74     gtk_object_add_arg_type ("SPCGrid::empcolor", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPCOLOR);
75     gtk_object_add_arg_type ("SPCGrid::empspacing", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPSPACING);
77     object_class->destroy = sp_cgrid_destroy;
78     object_class->set_arg = sp_cgrid_set_arg;
80     item_class->update = sp_cgrid_update;
81     item_class->render = sp_cgrid_render;
82 }
84 static void
85 sp_cgrid_init (SPCGrid *grid)
86 {
87     grid->origin[NR::X] = grid->origin[NR::Y] = 0.0;
88     grid->spacing[NR::X] = grid->spacing[NR::Y] = 8.0;
89     grid->color = 0x0000ff7f;
90     grid->empcolor = 0x3F3FFF40;
91     grid->empspacing = 5;
92 }
94 static void
95 sp_cgrid_destroy (GtkObject *object)
96 {
97     g_return_if_fail (object != NULL);
98     g_return_if_fail (SP_IS_CGRID (object));
100     if (GTK_OBJECT_CLASS (parent_class)->destroy)
101         (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
104 static void
105 sp_cgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
107     SPCanvasItem *item = SP_CANVAS_ITEM (object);
108     SPCGrid *grid = SP_CGRID (object);
110     switch (arg_id) {
111     case ARG_ORIGINX:
112         grid->origin[NR::X] = GTK_VALUE_DOUBLE (* arg);
113         sp_canvas_item_request_update (item);
114         break;
115     case ARG_ORIGINY:
116         grid->origin[NR::Y] = GTK_VALUE_DOUBLE (* arg);
117         sp_canvas_item_request_update (item);
118         break;
119     case ARG_SPACINGX:
120         grid->spacing[NR::X] = GTK_VALUE_DOUBLE (* arg);
121         if (grid->spacing[NR::X] < 0.01) grid->spacing[NR::X] = 0.01;
122         sp_canvas_item_request_update (item);
123         break;
124     case ARG_SPACINGY:
125         grid->spacing[NR::Y] = GTK_VALUE_DOUBLE (* arg);
126         if (grid->spacing[NR::Y] < 0.01) grid->spacing[NR::Y] = 0.01;
127         sp_canvas_item_request_update (item);
128         break;
129     case ARG_COLOR:
130         grid->color = GTK_VALUE_INT (* arg);
131         sp_canvas_item_request_update (item);
132         break;
133     case ARG_EMPCOLOR:
134         grid->empcolor = GTK_VALUE_INT (* arg);
135         sp_canvas_item_request_update (item);
136         break;
137     case ARG_EMPSPACING:
138         grid->empspacing = GTK_VALUE_INT (* arg);
139         // std::cout << "Emphasis Spacing: " << grid->empspacing << std::endl;
140         sp_canvas_item_request_update (item);
141         break;
142     default:
143         break;
144     }
147 static void
148 sp_grid_hline (SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba)
150     if ((y >= buf->rect.y0) && (y < buf->rect.y1)) {
151         guint r, g, b, a;
152         gint x0, x1, x;
153         guchar *p;
154         r = NR_RGBA32_R (rgba);
155         g = NR_RGBA32_G (rgba);
156         b = NR_RGBA32_B (rgba);
157         a = NR_RGBA32_A (rgba);
158         x0 = MAX (buf->rect.x0, xs);
159         x1 = MIN (buf->rect.x1, xe + 1);
160         p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3;
161         for (x = x0; x < x1; x++) {
162             p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
163             p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
164             p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
165             p += 3;
166         }
167     }
170 static void
171 sp_grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)
173     if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {
174         guint r, g, b, a;
175         gint y0, y1, y;
176         guchar *p;
177         r = NR_RGBA32_R(rgba);
178         g = NR_RGBA32_G (rgba);
179         b = NR_RGBA32_B (rgba);
180         a = NR_RGBA32_A (rgba);
181         y0 = MAX (buf->rect.y0, ys);
182         y1 = MIN (buf->rect.y1, ye + 1);
183         p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
184         for (y = y0; y < y1; y++) {
185             p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
186             p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
187             p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
188             p += buf->buf_rowstride;
189         }
190     }
193 /**
194     \brief  This function renders the grid on a particular canvas buffer
195     \param  item  The grid to render on the buffer
196     \param  buf   The buffer to render the grid on
197     
198     This function gets called a touch more than you might believe,
199     about once per tile.  This means that it could probably be optimized
200     and help things out.
202     Basically this function has to determine where in the canvas it is,
203     and how that associates with the grid.  It does this first by looking
204     at the bounding box of the buffer, and then calculates where the grid
205     starts in that buffer.  It will then step through grid lines until
206     it is outside of the buffer.
208     For each grid line it is drawn using the function \c sp_grid_hline
209     or \c sp_grid_vline.  These are convience functions for the sake
210     of making the function easier to read.
212     Also, there are emphisized lines on the grid.  While the \c syg and
213     \c sxg variable track grid positioning, the \c xlinestart and \c
214     ylinestart variables track the 'count' of what lines they are.  If
215     that count is a multiple of the line seperation between emphisis
216     lines, then that line is drawn in the emphisis color.
217 */
218 static void
219 sp_cgrid_render (SPCanvasItem * item, SPCanvasBuf * buf)
221     SPCGrid *grid = SP_CGRID (item);
223     sp_canvas_prepare_buffer (buf);
225     const gdouble sxg = floor ((buf->rect.x0 - grid->ow[NR::X]) / grid->sw[NR::X]) * grid->sw[NR::X] + grid->ow[NR::X];
226     const gint  xlinestart = (gint) Inkscape::round((sxg - grid->ow[NR::X]) / grid->sw[NR::X]);
227     const gdouble syg = floor ((buf->rect.y0 - grid->ow[NR::Y]) / grid->sw[NR::Y]) * grid->sw[NR::Y] + grid->ow[NR::Y];
228     const gint  ylinestart = (gint) Inkscape::round((syg - grid->ow[NR::Y]) / grid->sw[NR::Y]);
230     gint ylinenum;
231     gdouble y;
232     for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += grid->sw[NR::Y], ylinenum++) {
233         const gint y0 = (gint) Inkscape::round(y);
235         if (!grid->scaled[NR::Y] && (ylinenum % grid->empspacing) == 0) {
236             sp_grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, grid->empcolor);
237         } else {
238             sp_grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, grid->color);
239         }
240     }     
242     gint xlinenum;
243     gdouble x;
244     for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += grid->sw[NR::X], xlinenum++) {
245         const gint ix = (gint) Inkscape::round(x);
246         if (!grid->scaled[NR::X] && (xlinenum % grid->empspacing) == 0) {
247             sp_grid_vline (buf, ix, buf->rect.y0, buf->rect.y1, grid->empcolor);
248         } else {
249             sp_grid_vline (buf, ix, buf->rect.y0, buf->rect.y1, grid->color);
250         }
251     }
254 static void
255 sp_cgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)
257     SPCGrid *grid = SP_CGRID (item);
259     if (parent_class->update)
260         (* parent_class->update) (item, affine, flags);
262     grid->ow = grid->origin * affine;
263     grid->sw = grid->spacing * affine;
264     grid->sw -= NR::Point(affine[4], affine[5]);
266     for(int dim = 0; dim < 2; dim++) {
267         gint scaling_factor = grid->empspacing;
269         if (scaling_factor <= 1)
270             scaling_factor = 5;
272         grid->scaled[dim] = FALSE;
273         grid->sw[dim] = fabs (grid->sw[dim]);
274         while (grid->sw[dim] < 8.0) {
275             grid->scaled[dim] = TRUE;
276             grid->sw[dim] *= scaling_factor;
277             /* First pass, go up to the major line spacing, then
278                keep increasing by two. */
279             scaling_factor = 2;
280         }
281     }
283     if (grid->empspacing == 0) {
284         grid->scaled[NR::Y] = TRUE;
285         grid->scaled[NR::X] = TRUE;
286     }
288     sp_canvas_request_redraw (item->canvas,
289                      -1000000, -1000000,
290                      1000000, 1000000);
291                      
292     item->x1 = item->y1 = -1000000;
293     item->x2 = item->y2 = 1000000;
296 /*
297   Local Variables:
298   mode:c++
299   c-file-style:"stroustrup"
300   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
301   indent-tabs-mode:nil
302   fill-column:99
303   End:
304 */
305 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :