Code

disable filters in outline mode
[inkscape.git] / src / display / nr-arena-image.cpp
1 #define __NR_ARENA_IMAGE_C__
3 /*
4  * RGBA display list system for inkscape
5  *
6  * Author:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * Copyright (C) 2001-2002 Lauris Kaplinski
10  * Copyright (C) 2001 Ximian, Inc.
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #include <libnr/nr-compose-transform.h>
16 #include "../prefs-utils.h"
17 #include "nr-arena-image.h"
18 #include "style.h"
19 #include "display/nr-filter.h"
20 #include "display/nr-filter-gaussian.h"
21 #include "sp-filter.h"
22 #include "sp-gaussian-blur.h"
24 int nr_arena_image_x_sample = 1;
25 int nr_arena_image_y_sample = 1;
27 /*
28  * NRArenaCanvasImage
29  *
30  */
32 static void nr_arena_image_class_init (NRArenaImageClass *klass);
33 static void nr_arena_image_init (NRArenaImage *image);
34 static void nr_arena_image_finalize (NRObject *object);
36 static unsigned int nr_arena_image_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
37 static unsigned int nr_arena_image_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
38 static NRArenaItem *nr_arena_image_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
40 static NRArenaItemClass *parent_class;
42 NRType
43 nr_arena_image_get_type (void)
44 {
45         static NRType type = 0;
46         if (!type) {
47                 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
48                                                 "NRArenaImage",
49                                                 sizeof (NRArenaImageClass),
50                                                 sizeof (NRArenaImage),
51                                                 (void (*) (NRObjectClass *)) nr_arena_image_class_init,
52                                                 (void (*) (NRObject *)) nr_arena_image_init);
53         }
54         return type;
55 }
57 static void
58 nr_arena_image_class_init (NRArenaImageClass *klass)
59 {
60         NRObjectClass *object_class;
61         NRArenaItemClass *item_class;
63         object_class = (NRObjectClass *) klass;
64         item_class = (NRArenaItemClass *) klass;
66         parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
68         object_class->finalize = nr_arena_image_finalize;
69         object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaImage>;
71         item_class->update = nr_arena_image_update;
72         item_class->render = nr_arena_image_render;
73         item_class->pick = nr_arena_image_pick;
74 }
76 static void
77 nr_arena_image_init (NRArenaImage *image)
78 {
79         image->px = NULL;
81         image->pxw = image->pxh = image->pxrs = 0;
82         image->x = image->y = 0.0;
83         image->width = 256.0;
84         image->height = 256.0;
86         nr_matrix_set_identity (&image->grid2px);
88         image->style = 0;
89 }
91 static void
92 nr_arena_image_finalize (NRObject *object)
93 {
94         NRArenaImage *image = NR_ARENA_IMAGE (object);
96         image->px = NULL;
98         ((NRObjectClass *) parent_class)->finalize (object);
99 }
101 static unsigned int
102 nr_arena_image_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
104         NRMatrix grid2px;
106         NRArenaImage *image = NR_ARENA_IMAGE (item);
108         /* Request render old */
109         nr_arena_item_request_render (item);
111         /* Copy affine */
112         nr_matrix_invert (&grid2px, &gc->transform);
113         double hscale, vscale; // todo: replace with NR::scale
114         if (image->px) {
115                 hscale = image->pxw / image->width;
116                 vscale = image->pxh / image->height;
117         } else {
118                 hscale = 1.0;
119                 vscale = 1.0;
120         }
122         image->grid2px[0] = grid2px.c[0] * hscale;
123         image->grid2px[2] = grid2px.c[2] * hscale;
124         image->grid2px[4] = grid2px.c[4] * hscale;
125         image->grid2px[1] = grid2px.c[1] * vscale;
126         image->grid2px[3] = grid2px.c[3] * vscale;
127         image->grid2px[5] = grid2px.c[5] * vscale;
129         image->grid2px[4] -= image->x * hscale;
130         image->grid2px[5] -= image->y * vscale;
132         /* Calculate bbox */
133         if (image->px) {
134                 NRRect bbox;
136                 bbox.x0 = image->x;
137                 bbox.y0 = image->y;
138                 bbox.x1 = image->x + image->width;
139                 bbox.y1 = image->y + image->height;
140                 nr_rect_d_matrix_transform (&bbox, &bbox, &gc->transform);
142                 item->bbox.x0 = (int) floor (bbox.x0);
143                 item->bbox.y0 = (int) floor (bbox.y0);
144                 item->bbox.x1 = (int) ceil (bbox.x1);
145                 item->bbox.y1 = (int) ceil (bbox.y1);
146         } else {
147                 item->bbox.x0 = (int) gc->transform[4];
148                 item->bbox.y0 = (int) gc->transform[5];
149                 item->bbox.x1 = item->bbox.x0 - 1;
150                 item->bbox.y1 = item->bbox.y0 - 1;
151         }
153         nr_arena_item_request_render (item);
155         return NR_ARENA_ITEM_STATE_ALL;
158 #define FBITS 12
159 #define b2i (image->grid2px)
161 static unsigned int
162 nr_arena_image_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
164         nr_arena_image_x_sample = prefs_get_int_attribute ("options.bitmapoversample", "value", 1);
165         nr_arena_image_y_sample = nr_arena_image_x_sample;
167         NRArenaImage *image = NR_ARENA_IMAGE (item);
169         if (!image->px) return item->state;
171         guint32 Falpha = item->opacity;
172         if (Falpha < 1) return item->state;
174         unsigned char * dpx = NR_PIXBLOCK_PX (pb);
175         const int drs = pb->rs;
176         const int dw = pb->area.x1 - pb->area.x0;
177         const int dh = pb->area.y1 - pb->area.y0;
179         unsigned char * spx = image->px;
180         const int srs = image->pxrs;
181         const int sw = image->pxw;
182         const int sh = image->pxh;
184         NR::Matrix d2s;
186         d2s[0] = b2i[0];
187         d2s[1] = b2i[1];
188         d2s[2] = b2i[2];
189         d2s[3] = b2i[3];
190         d2s[4] = b2i[0] * pb->area.x0 + b2i[2] * pb->area.y0 + b2i[4];
191         d2s[5] = b2i[1] * pb->area.x0 + b2i[3] * pb->area.y0 + b2i[5];
193         if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) {
194                 /* fixme: This is not implemented yet (Lauris) */
195                 /* nr_R8G8B8_R8G8B8_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample); */
196         } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
197                 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
198         } else if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
200                 //FIXME: The _N_N_N_ version gives a gray border around images, see bug 906376
201                 // This mode is only used when exporting, screen rendering always has _P_P_P_, so I decided to simply replace it for now
202                 // Feel free to propose a better fix
204                 //nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
205                 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (dpx, dw, dh, drs, spx, sw, sh, srs, d2s, Falpha, nr_arena_image_x_sample, nr_arena_image_y_sample);
206         }
208         pb->empty = FALSE;
210         return item->state;
213 static NRArenaItem *
214 nr_arena_image_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
216         NRArenaImage *image = NR_ARENA_IMAGE (item);
218         if (!image->px) return NULL;
220         unsigned char * const pixels = image->px;
221         const int width = image->pxw;
222         const int height = image->pxh;
223         const int rowstride = image->pxrs;
224         NR::Point tp = p * image->grid2px;
225         const int ix = (int)(tp[NR::X]);
226         const int iy = (int)(tp[NR::Y]);
228         if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
229                 return NULL;
231         unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
232         // is the alpha not transparent?
233         return (pix_ptr[3] > 0) ? item : NULL;
236 /* Utility */
238 void
239 nr_arena_image_set_pixels (NRArenaImage *image, const unsigned char *px, unsigned int pxw, unsigned int pxh, unsigned int pxrs)
241         nr_return_if_fail (image != NULL);
242         nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
244         image->px = (unsigned char *) px;
245         image->pxw = pxw;
246         image->pxh = pxh;
247         image->pxrs = pxrs;
249         nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
252 void
253 nr_arena_image_set_geometry (NRArenaImage *image, double x, double y, double width, double height)
255         nr_return_if_fail (image != NULL);
256         nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
258         image->x = x;
259         image->y = y;
260         image->width = width;
261         image->height = height;
263         nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
266 void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style)
268   g_return_if_fail(image != NULL);
269   g_return_if_fail(NR_IS_ARENA_IMAGE(image));
271   if (style) sp_style_ref(style);
272   if (image->style) sp_style_unref(image->style);
273   image->style = style;
275   //if there is a filter set for this group
276   if (style && style->filter.set && style->filter.filter) {
277   
278         image->filter = new NR::Filter();
279         image->filter->set_x(style->filter.filter->x);
280         image->filter->set_y(style->filter.filter->y);
281         image->filter->set_width(style->filter.filter->width);
282         image->filter->set_height(style->filter.filter->height);
283         
284         //go through all SP filter primitives
285         for(int i=0; i<style->filter.filter->_primitive_count; i++)
286         {
287             SPFilterPrimitive *primitive = style->filter.filter->_primitives[i];
288             //if primitive is gaussianblur
289 //            if(SP_IS_GAUSSIANBLUR(primitive))
290             {
291                 NR::FilterGaussian * gaussian = (NR::FilterGaussian *) image->filter->add_primitive(NR::NR_FILTER_GAUSSIANBLUR);
292                 SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
293                 float num = spblur->stdDeviation.getNumber();
294                 if( num>=0.0 )
295                 {
296                     float optnum = spblur->stdDeviation.getOptNumber();
297                     if( optnum>=0.0 )
298                         gaussian->set_deviation((double) num, (double) optnum);
299                     else
300                         gaussian->set_deviation((double) num);
301                 }
302             }
303         }
304     }
305     else
306     {
307         //no filter set for this group
308         image->filter = NULL;
309     }
311   if (style && style->enable_background.set
312       && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
313     image->background_new = true;
314   }