15
15
#define noNR_ARENA_ITEM_VERBOSE
16
16
#define noNR_ARENA_ITEM_DEBUG_CASCADE
19
21
#include <libnr/nr-blit.h>
20
22
#include <libnr/nr-pixops.h>
21
23
#include "nr-arena.h"
22
24
#include "nr-arena-item.h"
23
//#include "nr-arena-group.h"
24
25
#include "gc-core.h"
27
#include "nr-filter.h"
28
#include "libnr/nr-rect.h"
29
#include "nr-arena-group.h"
30
#include "prefs-utils.h"
26
32
namespace GC = Inkscape::GC;
28
34
static void nr_arena_item_class_init (NRArenaItemClass *klass);
29
35
static void nr_arena_item_init (NRArenaItem *item);
30
36
static void nr_arena_item_private_finalize (NRObject *object);
32
#ifdef arena_item_tile_cache
33
bool insert_cache(NRArenaItem* owner,int th,int tv,NRPixBlock *ipb,NRPixBlock *mpb,double activity,double duration);
34
void remove_caches(NRArenaItem* owner);
35
bool test_cache(NRArenaItem* owner,int th,int tv,NRPixBlock &ipb,NRPixBlock &mpb,bool &hasMask);
38
38
static NRObjectClass *parent_class;
41
41
nr_arena_item_get_type (void)
43
static NRType type = 0;
45
type = nr_object_register_type (NR_TYPE_OBJECT,
47
sizeof (NRArenaItemClass),
49
(void (*) (NRObjectClass *)) nr_arena_item_class_init,
50
(void (*) (NRObject *)) nr_arena_item_init);
43
static NRType type = 0;
45
type = nr_object_register_type (NR_TYPE_OBJECT,
47
sizeof (NRArenaItemClass),
49
(void (*)(NRObjectClass *))
50
nr_arena_item_class_init,
51
(void (*)(NRObject *))
56
58
nr_arena_item_class_init (NRArenaItemClass *klass)
58
NRObjectClass *object_class;
60
object_class = (NRObjectClass *) klass;
62
parent_class = ((NRObjectClass *) klass)->parent;
64
object_class->finalize = nr_arena_item_private_finalize;
65
object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaItem>;
60
NRObjectClass *object_class;
62
object_class = (NRObjectClass *) klass;
64
parent_class = ((NRObjectClass *) klass)->parent;
66
object_class->finalize = nr_arena_item_private_finalize;
67
object_class->cpp_ctor = NRObject::invoke_ctor < NRArenaItem >;
69
71
nr_arena_item_init (NRArenaItem *item)
73
item->next = item->prev = NULL;
78
item->sensitive = TRUE;
81
memset(&item->bbox, 0, sizeof(item->bbox));
82
item->transform = NULL;
84
item->render_opacity = FALSE;
86
#ifdef arena_item_tile_cache
88
item->skipCaching=false;
91
item->transform = NULL;
75
item->next = item->prev = NULL;
80
item->sensitive = TRUE;
83
memset (&item->bbox, 0, sizeof (item->bbox));
84
item->transform = NULL;
86
item->render_opacity = FALSE;
88
item->transform = NULL;
94
item->background_pb = NULL;
95
item->background_new = false;
99
99
nr_arena_item_private_finalize (NRObject *object)
101
NRArenaItem *item=static_cast<NRArenaItem *>(object);
103
#ifdef arena_item_tile_cache
108
item->transform = NULL;
110
((NRObjectClass *) (parent_class))->finalize (object);
101
NRArenaItem *item = static_cast < NRArenaItem * >(object);
104
item->transform = NULL;
106
((NRObjectClass *) (parent_class))->finalize (object);
114
110
nr_arena_item_children (NRArenaItem *item)
116
nr_return_val_if_fail (item != NULL, NULL);
117
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
119
if (NR_ARENA_ITEM_VIRTUAL (item, children))
120
return NR_ARENA_ITEM_VIRTUAL (item, children) (item);
112
nr_return_val_if_fail (item != NULL, NULL);
113
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
115
if (NR_ARENA_ITEM_VIRTUAL (item, children))
116
return NR_ARENA_ITEM_VIRTUAL (item, children) (item);
126
122
nr_arena_item_last_child (NRArenaItem *item)
128
nr_return_val_if_fail (item != NULL, NULL);
129
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
124
nr_return_val_if_fail (item != NULL, NULL);
125
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
131
if (NR_ARENA_ITEM_VIRTUAL (item, last_child)) {
132
return NR_ARENA_ITEM_VIRTUAL (item, last_child) (item);
135
ref = nr_arena_item_children (item);
136
if (ref) while (ref->next) ref = ref->next;
127
if (NR_ARENA_ITEM_VIRTUAL (item, last_child)) {
128
return NR_ARENA_ITEM_VIRTUAL (item, last_child) (item);
130
NRArenaItem *ref = nr_arena_item_children (item);
142
nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
139
nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child,
144
nr_return_if_fail (item != NULL);
145
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
146
nr_return_if_fail (child != NULL);
147
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
148
nr_return_if_fail (child->parent == NULL);
149
nr_return_if_fail (child->prev == NULL);
150
nr_return_if_fail (child->next == NULL);
151
nr_return_if_fail (child->arena == item->arena);
152
nr_return_if_fail (child != ref);
153
nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
154
nr_return_if_fail (!ref || (ref->parent == item));
142
nr_return_if_fail (item != NULL);
143
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
144
nr_return_if_fail (child != NULL);
145
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
146
nr_return_if_fail (child->parent == NULL);
147
nr_return_if_fail (child->prev == NULL);
148
nr_return_if_fail (child->next == NULL);
149
nr_return_if_fail (child->arena == item->arena);
150
nr_return_if_fail (child != ref);
151
nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
152
nr_return_if_fail (!ref || (ref->parent == item));
156
if (NR_ARENA_ITEM_VIRTUAL (item, add_child))
157
NR_ARENA_ITEM_VIRTUAL (item, add_child) (item, child, ref);
154
if (NR_ARENA_ITEM_VIRTUAL (item, add_child))
155
NR_ARENA_ITEM_VIRTUAL (item, add_child) (item, child, ref);
161
159
nr_arena_item_remove_child (NRArenaItem *item, NRArenaItem *child)
163
nr_return_if_fail (item != NULL);
164
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
165
nr_return_if_fail (child != NULL);
166
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
167
nr_return_if_fail (child->parent == item);
161
nr_return_if_fail (item != NULL);
162
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
163
nr_return_if_fail (child != NULL);
164
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
165
nr_return_if_fail (child->parent == item);
169
if (NR_ARENA_ITEM_VIRTUAL (item, remove_child))
170
NR_ARENA_ITEM_VIRTUAL (item, remove_child) (item, child);
167
if (NR_ARENA_ITEM_VIRTUAL (item, remove_child))
168
NR_ARENA_ITEM_VIRTUAL (item, remove_child) (item, child);
174
nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
172
nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child,
176
nr_return_if_fail (item != NULL);
177
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
178
nr_return_if_fail (child != NULL);
179
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
180
nr_return_if_fail (child->parent == item);
181
nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
182
nr_return_if_fail (!ref || (ref->parent == item));
175
nr_return_if_fail (item != NULL);
176
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
177
nr_return_if_fail (child != NULL);
178
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
179
nr_return_if_fail (child->parent == item);
180
nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
181
nr_return_if_fail (!ref || (ref->parent == item));
184
if (NR_ARENA_ITEM_VIRTUAL (item, set_child_position))
185
NR_ARENA_ITEM_VIRTUAL (item, set_child_position) (item, child, ref);
183
if (NR_ARENA_ITEM_VIRTUAL (item, set_child_position))
184
NR_ARENA_ITEM_VIRTUAL (item, set_child_position) (item, child, ref);
189
188
nr_arena_item_ref (NRArenaItem *item)
191
nr_object_ref ((NRObject *) item);
190
nr_object_ref ((NRObject *) item);
197
196
nr_arena_item_unref (NRArenaItem *item)
199
nr_object_unref ((NRObject *) item);
198
nr_object_unref ((NRObject *) item);
205
nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
204
nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
205
unsigned int state, unsigned int reset)
209
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
210
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NR_ARENA_ITEM_STATE_INVALID);
211
nr_return_val_if_fail (!(state & NR_ARENA_ITEM_STATE_INVALID), NR_ARENA_ITEM_STATE_INVALID);
209
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
210
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
211
NR_ARENA_ITEM_STATE_INVALID);
212
nr_return_val_if_fail (!(state & NR_ARENA_ITEM_STATE_INVALID),
213
NR_ARENA_ITEM_STATE_INVALID);
213
215
#ifdef NR_ARENA_ITEM_DEBUG_CASCADE
214
printf ("Update %s:%p %x %x %x\n", nr_type_name_from_instance ((GTypeInstance *) item), item, state, item->state, reset);
217
/* return if in error */
218
if (item->state & NR_ARENA_ITEM_STATE_INVALID) return item->state;
219
/* Set reset flags according to propagation status */
220
if (item->propagate) {
221
reset |= ~item->state;
222
item->propagate = FALSE;
224
/* Reset our state */
225
item->state &= ~reset;
227
if (!(~item->state & state)) return item->state;
228
/* Test whether to return immediately */
229
if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
230
if (!nr_rect_l_test_intersect (area, &item->bbox)) return item->state;
233
/* Reset image cache, if not to be kept */
234
if (!(item->state & NR_ARENA_ITEM_STATE_IMAGE) && (item->px)) {
237
#ifdef arena_item_tile_cache
241
/* Set up local gc */
243
if (item->transform) {
244
nr_matrix_multiply (&childgc.transform, item->transform, &childgc.transform);
247
/* Invoke the real method */
248
item->state = NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state, reset);
249
if (item->state & NR_ARENA_ITEM_STATE_INVALID) return item->state;
252
unsigned int newstate;
253
newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset);
254
if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
255
item->state |= NR_ARENA_ITEM_STATE_INVALID;
258
nr_rect_l_intersect (&item->bbox, &item->bbox, &item->clip->bbox);
262
unsigned int newstate;
263
newstate = nr_arena_item_invoke_update (item->mask, area, &childgc, state, reset);
264
if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
265
item->state |= NR_ARENA_ITEM_STATE_INVALID;
268
nr_rect_l_intersect (&item->bbox, &item->bbox, &item->mask->bbox);
216
printf ("Update %s:%p %x %x %x\n",
217
nr_type_name_from_instance ((GTypeInstance *) item), item, state,
221
/* return if in error */
222
if (item->state & NR_ARENA_ITEM_STATE_INVALID)
224
/* Set reset flags according to propagation status */
225
if (item->propagate) {
226
reset |= ~item->state;
227
item->propagate = FALSE;
229
/* Reset our state */
230
item->state &= ~reset;
232
if (!(~item->state & state))
234
/* Test whether to return immediately */
235
if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
236
if (!nr_rect_l_test_intersect (area, &item->bbox))
240
/* Reset image cache, if not to be kept */
241
if (!(item->state & NR_ARENA_ITEM_STATE_IMAGE) && (item->px)) {
245
/* Set up local gc */
247
if (item->transform) {
248
nr_matrix_multiply (&childgc.transform, item->transform,
251
/* Remember the transformation matrix */
252
item->ctm = childgc.transform;
254
/* Invoke the real method */
256
NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state,
258
if (item->state & NR_ARENA_ITEM_STATE_INVALID)
260
/* Enlarge the bounding box to contain filter effects */
262
item->filter->bbox_enlarge (item->bbox);
264
// fixme: to fix the display glitches, in outline mode bbox must be a combination of
265
// full item bbox and its clip and mask (after we have the API to get these)
269
// FIXME: since here we only need bbox, consider passing
270
// ((state & !(NR_ARENA_ITEM_STATE_RENDER)) | NR_ARENA_ITEM_STATE_BBOX)
271
// instead of state, so it does not have to create rendering structures in nr_arena_shape_update
272
unsigned int newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset);
273
if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
274
item->state |= NR_ARENA_ITEM_STATE_INVALID;
277
nr_rect_l_intersect (&item->bbox, &item->bbox, &item->clip->bbox);
281
unsigned int newstate = nr_arena_item_invoke_update (item->mask, area, &childgc, state, reset);
282
if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
283
item->state |= NR_ARENA_ITEM_STATE_INVALID;
286
nr_rect_l_intersect (&item->bbox, &item->bbox, &item->mask->bbox);
277
295
* \return Has NR_ARENA_ITEM_STATE_RENDER set on success.
280
unsigned int nr_arena_item_invoke_render(NRArenaItem *item, NRRectL const *area, NRPixBlock *pb, unsigned int flags)
299
nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area,
300
NRPixBlock *pb, unsigned int flags)
302
bool outline = (item->arena->rendermode == RENDERMODE_OUTLINE);
287
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
288
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NR_ARENA_ITEM_STATE_INVALID);
289
nr_return_val_if_fail (item->state & NR_ARENA_ITEM_STATE_BBOX, item->state);
304
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
305
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
306
NR_ARENA_ITEM_STATE_INVALID);
307
nr_return_val_if_fail (item->state & NR_ARENA_ITEM_STATE_BBOX,
291
310
#ifdef NR_ARENA_ITEM_VERBOSE
292
printf ("Invoke render %p: %d %d - %d %d\n", item, area->x0, area->y0, area->x1, area->y1);
295
#ifdef arena_item_tile_cache
299
/* If we are outside bbox just return successfully */
300
if (!item->visible) return item->state | NR_ARENA_ITEM_STATE_RENDER;
301
nr_rect_l_intersect (&carea, area, &item->bbox);
302
if (nr_rect_l_test_empty (&carea)) return item->state | NR_ARENA_ITEM_STATE_RENDER;
305
/* Has cache pixblock, render this and return */
306
nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P,
307
/* fixme: This probably cannot overflow, because we render only if visible */
308
/* fixme: and pixel cache is there only for small items */
309
/* fixme: But this still needs extra check (Lauris) */
310
item->bbox.x0, item->bbox.y0,
311
item->bbox.x1, item->bbox.y1,
312
item->px, 4 * (item->bbox.x1 - item->bbox.x0), FALSE, FALSE);
313
nr_blit_pixblock_pixblock (pb, &cpb);
314
nr_pixblock_release (&cpb);
316
return item->state | NR_ARENA_ITEM_STATE_RENDER;
321
#ifdef arena_item_tile_cache
322
bool checkCache=false;
323
int tile_h=0,tile_v=0;
325
/* Setup cache if we can */
326
if ((!(flags & NR_ARENA_ITEM_RENDER_NO_CACHE)) &&
327
(carea.x0 <= item->bbox.x0) && (carea.y0 <= item->bbox.y0) &&
328
(carea.x1 >= item->bbox.x1) && (carea.y1 >= item->bbox.y1) &&
329
(((item->bbox.x1 - item->bbox.x0) * (item->bbox.y1 - item->bbox.y0)) <= 4096)) {
330
// Item bbox is fully in renderable area and size is acceptable
331
carea.x0 = item->bbox.x0;
332
carea.y0 = item->bbox.y0;
333
carea.x1 = item->bbox.x1;
334
carea.y1 = item->bbox.y1;
335
item->px = new (GC::ATOMIC) unsigned char[4 * (carea.x1 - carea.x0) * (carea.y1 - carea.y0)];
336
nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P,
337
carea.x0, carea.y0, carea.x1, carea.y1,
338
item->px, 4 * (carea.x1 - carea.x0), TRUE, TRUE);
339
cpb.visible_area = pb->visible_area;
341
// Set nocache flag for downstream rendering
342
flags |= NR_ARENA_ITEM_RENDER_NO_CACHE;
344
#ifdef arena_item_tile_cache
345
if ( item->skipCaching ) {
347
int tl=area->x0&(~127);
348
int tt=area->y0&(~127);
349
if ( area->x1 <= tl+128 && area->y1 <= tt+128 ) {
353
int surf=(area->x1-area->x0)*(area->y1-area->y0);
354
if ( surf >= 4096 ) {
366
#ifdef arena_item_tile_cache
370
#ifdef arena_item_tile_cache
374
if ( test_cache(item,tile_h,tile_v,ipb,mpb,hasMask) ) {
375
// youpi! c'etait deja cache
377
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
378
} else if ( ((item->opacity != 255) && !item->render_opacity) ) {
379
nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
381
nr_blit_pixblock_pixblock (pb, &ipb);
384
return item->state | NR_ARENA_ITEM_STATE_RENDER;
389
#ifdef arena_item_tile_cache
390
// nota: exclusif de dpb != pb, donc pas de cas particulier a la fin
393
// struct timeval start_time,end_time;
394
// gettimeofday(&start_time,NULL);
395
GTimeVal start_time,end_time;
396
g_get_current_time (&start_time);
399
/* Setup and render item buffer */
400
nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
401
ipb.visible_area = pb->visible_area;
402
state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags);
403
if (state & NR_ARENA_ITEM_STATE_INVALID) {
404
/* Clean up and return error */
405
nr_pixblock_release (&ipb);
406
if (dpb != pb) nr_pixblock_release (dpb);
407
item->state |= NR_ARENA_ITEM_STATE_INVALID;
412
if (item->clip || item->mask) {
413
/* Setup mask pixblock */
414
nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
415
mpb.visible_area = pb->visible_area;
416
/* Do clip if needed */
418
state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb);
419
if (state & NR_ARENA_ITEM_STATE_INVALID) {
420
/* Clean up and return error */
421
nr_pixblock_release (&mpb);
422
nr_pixblock_release (&ipb);
423
if (dpb != pb) nr_pixblock_release (dpb);
424
item->state |= NR_ARENA_ITEM_STATE_INVALID;
429
/* Do mask if needed */
432
/* Set up yet another temporary pixblock */
433
nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
434
tpb.visible_area = pb->visible_area;
435
state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, &tpb, flags);
436
if (state & NR_ARENA_ITEM_STATE_INVALID) {
437
/* Clean up and return error */
438
nr_pixblock_release (&tpb);
439
nr_pixblock_release (&mpb);
440
nr_pixblock_release (&ipb);
441
if (dpb != pb) nr_pixblock_release (dpb);
442
item->state |= NR_ARENA_ITEM_STATE_INVALID;
445
/* Composite with clip */
448
for (y = carea.y0; y < carea.y1; y++) {
449
unsigned char *s, *d;
450
s = NR_PIXBLOCK_PX (&tpb) + (y - carea.y0) * tpb.rs;
451
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
452
for (x = carea.x0; x < carea.x1; x++) {
454
m = ((s[0] + s[1] + s[2]) * s[3] + 127) / (3 * 255);
455
d[0] = NR_PREMUL (d[0], m);
462
for (y = carea.y0; y < carea.y1; y++) {
463
unsigned char *s, *d;
464
s = NR_PIXBLOCK_PX (&tpb) + (y - carea.y0) * tpb.rs;
465
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
466
for (x = carea.x0; x < carea.x1; x++) {
468
m = ((s[0] + s[1] + s[2]) * s[3] + 127) / (3 * 255);
476
nr_pixblock_release (&tpb);
478
/* Multiply with opacity if needed */
479
if ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE) {
483
for (y = carea.y0; y < carea.y1; y++) {
485
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
486
for (x = carea.x0; x < carea.x1; x++) {
487
d[0] = NR_PREMUL (d[0], a);
492
/* Compose rendering pixblock int destination */
493
// gettimeofday(&end_time,NULL);
494
g_get_current_time (&end_time);
495
duration=(end_time.tv_sec-start_time.tv_sec)*1000+(end_time.tv_usec-start_time.tv_usec)/1000;
496
if ( !(ipb.empty) ) {
497
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
498
if ( insert_cache(item,tile_h,tile_v,&ipb,&mpb,item->activity,(double)duration) ) {
500
nr_pixblock_release (&mpb);
501
nr_pixblock_release (&ipb);
505
nr_pixblock_release (&ipb);
507
} else if ( ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE) ) {
509
// gettimeofday(&end_time,NULL);
510
g_get_current_time (&end_time);
511
duration=(end_time.tv_sec-start_time.tv_sec)*1000+(end_time.tv_usec-start_time.tv_usec)/1000;
512
if ( !(ipb.empty) ) {
513
nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
514
if ( insert_cache(item,tile_h,tile_v,&ipb,NULL,item->activity,(double)duration) ) {
516
nr_pixblock_release (&ipb);
520
nr_pixblock_release (&ipb);
523
// gettimeofday(&end_time,NULL);
524
g_get_current_time (&end_time);
525
duration=(end_time.tv_sec-start_time.tv_sec)*1000+(end_time.tv_usec-start_time.tv_usec)/1000;
526
if ( !(ipb.empty) ) {
527
nr_blit_pixblock_pixblock (dpb, &ipb);
528
if ( insert_cache(item,tile_h,tile_v,&ipb,NULL,item->activity,(double)duration) ) {
530
nr_pixblock_release (&ipb);
534
nr_pixblock_release (&ipb);
311
printf ("Invoke render %p: %d %d - %d %d\n", item, area->x0, area->y0,
315
/* If we are outside bbox just return successfully */
317
return item->state | NR_ARENA_ITEM_STATE_RENDER;
320
nr_rect_l_intersect (&carea, area, &item->bbox);
321
if (nr_rect_l_test_empty (&carea))
322
return item->state | NR_ARENA_ITEM_STATE_RENDER;
323
if (item->filter && !outline) {
324
item->filter->area_enlarge (carea, item->ctm);
325
nr_rect_l_intersect (&carea, &carea, &item->bbox);
329
// No caching in outline mode for now; investigate if it really gives any advantage with cairo.
330
// Also no attempts to clip anything; just render everything: item, clip, mask
331
// First, render the object itself
332
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
333
if (state & NR_ARENA_ITEM_STATE_INVALID) {
334
/* Clean up and return error */
335
item->state |= NR_ARENA_ITEM_STATE_INVALID;
339
// render clip and mask, if any
340
guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
341
// render clippath as an object, using a different color
343
item->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "clips", 0x00ff00ff); // green clips
344
NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, &carea, pb, flags);
346
// render mask as an object, using a different color
348
item->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "masks", 0x0000ffff); // blue masks
349
NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, pb, flags);
351
item->arena->outlinecolor = saved_rgba; // restore outline color
353
return item->state | NR_ARENA_ITEM_STATE_RENDER;
358
/* Has cache pixblock, render this and return */
359
nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P,
360
/* fixme: This probably cannot overflow, because we render only if visible */
361
/* fixme: and pixel cache is there only for small items */
362
/* fixme: But this still needs extra check (Lauris) */
363
item->bbox.x0, item->bbox.y0,
364
item->bbox.x1, item->bbox.y1,
366
4 * (item->bbox.x1 - item->bbox.x0), FALSE,
368
nr_blit_pixblock_pixblock (pb, &cpb);
369
nr_pixblock_release (&cpb);
371
return item->state | NR_ARENA_ITEM_STATE_RENDER;
374
NRPixBlock *dpb = pb;
376
/* Setup cache if we can */
377
if ((!(flags & NR_ARENA_ITEM_RENDER_NO_CACHE)) &&
378
(carea.x0 <= item->bbox.x0) && (carea.y0 <= item->bbox.y0) &&
379
(carea.x1 >= item->bbox.x1) && (carea.y1 >= item->bbox.y1) &&
380
(((item->bbox.x1 - item->bbox.x0) * (item->bbox.y1 -
381
item->bbox.y0)) <= 4096)) {
382
// Item bbox is fully in renderable area and size is acceptable
383
carea.x0 = item->bbox.x0;
384
carea.y0 = item->bbox.y0;
385
carea.x1 = item->bbox.x1;
386
carea.y1 = item->bbox.y1;
388
new (GC::ATOMIC) unsigned char[4 * (carea.x1 - carea.x0) *
389
(carea.y1 - carea.y0)];
390
nr_pixblock_setup_extern (&cpb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0,
391
carea.y0, carea.x1, carea.y1, item->px,
392
4 * (carea.x1 - carea.x0), TRUE, TRUE);
393
cpb.visible_area = pb->visible_area;
395
// Set nocache flag for downstream rendering
396
flags |= NR_ARENA_ITEM_RENDER_NO_CACHE;
539
399
/* Determine, whether we need temporary buffer */
540
if (item->clip || item->mask || ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE)) {
543
/* Setup and render item buffer */
544
nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
545
ipb.visible_area = pb->visible_area;
546
state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, &ipb, flags);
547
if (state & NR_ARENA_ITEM_STATE_INVALID) {
548
/* Clean up and return error */
400
if (item->clip || item->mask
401
|| ((item->opacity != 255) && !item->render_opacity)
402
|| (item->filter) || item->background_new
403
|| (item->parent && item->parent->background_pb)) {
405
/* Setup and render item buffer */
407
nr_pixblock_setup_fast (&ipb, NR_PIXBLOCK_MODE_R8G8B8A8P,
408
carea.x0, carea.y0, carea.x1, carea.y1,
411
// if memory allocation failed, abort render
412
if (ipb.size != NR_PIXBLOCK_SIZE_TINY && ipb.data.px == NULL) {
413
nr_pixblock_release (&ipb);
414
return (item->state);
417
/* If background access is used, save the pixblock address.
418
* This address is set to NULL at the end of this block */
419
if (item->background_new ||
420
(item->parent && item->parent->background_pb)) {
421
item->background_pb = &ipb;
424
ipb.visible_area = pb->visible_area;
426
item->filter->area_enlarge (ipb.visible_area, item->ctm);
429
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, &ipb, flags);
430
if (state & NR_ARENA_ITEM_STATE_INVALID) {
431
/* Clean up and return error */
432
nr_pixblock_release (&ipb);
434
nr_pixblock_release (dpb);
435
item->state |= NR_ARENA_ITEM_STATE_INVALID;
440
/* Run filtering, if a filter is set for this object */
442
item->filter->render (item, &ipb);
445
if (item->clip || item->mask) {
446
/* Setup mask pixblock */
448
nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0,
449
carea.y0, carea.x1, carea.y1, TRUE);
451
if (mpb.data.px != NULL) { // if memory allocation was successful
453
mpb.visible_area = pb->visible_area;
454
/* Do clip if needed */
456
state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb);
457
if (state & NR_ARENA_ITEM_STATE_INVALID) {
458
/* Clean up and return error */
459
nr_pixblock_release (&mpb);
460
nr_pixblock_release (&ipb);
462
nr_pixblock_release (dpb);
463
item->state |= NR_ARENA_ITEM_STATE_INVALID;
468
/* Do mask if needed */
471
/* Set up yet another temporary pixblock */
472
nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N,
473
carea.x0, carea.y0, carea.x1,
476
if (tpb.data.px != NULL) { // if memory allocation was successful
478
tpb.visible_area = pb->visible_area;
479
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, &carea, &tpb, flags);
480
if (state & NR_ARENA_ITEM_STATE_INVALID) {
481
/* Clean up and return error */
482
nr_pixblock_release (&tpb);
483
nr_pixblock_release (&mpb);
484
nr_pixblock_release (&ipb);
486
nr_pixblock_release (dpb);
487
item->state |= NR_ARENA_ITEM_STATE_INVALID;
490
/* Composite with clip */
493
for (y = carea.y0; y < carea.y1; y++) {
494
unsigned char *s, *d;
495
s = NR_PIXBLOCK_PX (&tpb) + (y -
497
d = NR_PIXBLOCK_PX (&mpb) + (y -
499
for (x = carea.x0; x < carea.x1; x++) {
501
m = NR_PREMUL_112 (s[0] + s[1] + s[2], s[3]);
503
FAST_DIV_ROUND < 3 * 255 * 255 >
504
(NR_PREMUL_123 (d[0], m));
511
for (y = carea.y0; y < carea.y1; y++) {
512
unsigned char *s, *d;
513
s = NR_PIXBLOCK_PX (&tpb) + (y -
515
d = NR_PIXBLOCK_PX (&mpb) + (y -
517
for (x = carea.x0; x < carea.x1; x++) {
519
m = NR_PREMUL_112 (s[0] + s[1] + s[2], s[3]);
520
d[0] = FAST_DIV_ROUND < 3 * 255 > (m);
528
nr_pixblock_release (&tpb);
530
/* Multiply with opacity if needed */
531
if ((item->opacity != 255) && !item->render_opacity
536
for (y = carea.y0; y < carea.y1; y++) {
538
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
539
for (x = carea.x0; x < carea.x1; x++) {
540
d[0] = NR_PREMUL_111 (d[0], a);
545
/* Compose rendering pixblock int destination */
546
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
548
nr_pixblock_release (&mpb);
550
if (item->render_opacity) { // opacity was already rendered in, just copy to dpb here
551
nr_blit_pixblock_pixblock(dpb, &ipb);
552
} else { // copy while multiplying by opacity
553
nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
549
556
nr_pixblock_release (&ipb);
550
if (dpb != pb) nr_pixblock_release (dpb);
551
item->state |= NR_ARENA_ITEM_STATE_INVALID;
556
if (item->clip || item->mask) {
557
/* Setup mask pixblock */
558
nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
559
mpb.visible_area = pb->visible_area;
560
/* Do clip if needed */
562
state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb);
563
if (state & NR_ARENA_ITEM_STATE_INVALID) {
564
/* Clean up and return error */
565
nr_pixblock_release (&mpb);
566
nr_pixblock_release (&ipb);
567
if (dpb != pb) nr_pixblock_release (dpb);
568
item->state |= NR_ARENA_ITEM_STATE_INVALID;
573
/* Do mask if needed */
576
/* Set up yet another temporary pixblock */
577
nr_pixblock_setup_fast (&tpb, NR_PIXBLOCK_MODE_R8G8B8A8N, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
578
tpb.visible_area = pb->visible_area;
579
state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (item->mask, &carea, &tpb, flags);
580
if (state & NR_ARENA_ITEM_STATE_INVALID) {
581
/* Clean up and return error */
582
nr_pixblock_release (&tpb);
583
nr_pixblock_release (&mpb);
584
nr_pixblock_release (&ipb);
585
if (dpb != pb) nr_pixblock_release (dpb);
586
item->state |= NR_ARENA_ITEM_STATE_INVALID;
589
/* Composite with clip */
592
for (y = carea.y0; y < carea.y1; y++) {
593
unsigned char *s, *d;
594
s = NR_PIXBLOCK_PX (&tpb) + (y - carea.y0) * tpb.rs;
595
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
596
for (x = carea.x0; x < carea.x1; x++) {
598
m = ((s[0] + s[1] + s[2]) * s[3] + 127) / (3 * 255);
599
d[0] = NR_PREMUL (d[0], m);
606
for (y = carea.y0; y < carea.y1; y++) {
607
unsigned char *s, *d;
608
s = NR_PIXBLOCK_PX (&tpb) + (y - carea.y0) * tpb.rs;
609
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
610
for (x = carea.x0; x < carea.x1; x++) {
612
m = ((s[0] + s[1] + s[2]) * s[3] + 127) / (3 * 255);
620
nr_pixblock_release (&tpb);
622
/* Multiply with opacity if needed */
623
if ((item->opacity != 255) && !item->render_opacity && item->arena->rendermode != RENDERMODE_OUTLINE) {
627
for (y = carea.y0; y < carea.y1; y++) {
629
d = NR_PIXBLOCK_PX (&mpb) + (y - carea.y0) * mpb.rs;
630
for (x = carea.x0; x < carea.x1; x++) {
631
d[0] = NR_PREMUL (d[0], a);
636
/* Compose rendering pixblock int destination */
637
nr_blit_pixblock_pixblock_mask (dpb, &ipb, &mpb);
638
nr_pixblock_release (&mpb);
641
nr_blit_pixblock_pixblock_alpha (dpb, &ipb, item->opacity);
643
nr_pixblock_release (&ipb);
558
/* This pointer wouldn't be valid outside this block, so clear it */
559
item->background_pb = NULL;
647
state = NR_ARENA_ITEM_VIRTUAL (item, render) (item, &carea, dpb, flags);
648
if (state & NR_ARENA_ITEM_STATE_INVALID) {
649
/* Clean up and return error */
650
if (dpb != pb) nr_pixblock_release (dpb);
651
item->state |= NR_ARENA_ITEM_STATE_INVALID;
562
unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, dpb, flags);
563
if (state & NR_ARENA_ITEM_STATE_INVALID) {
564
/* Clean up and return error */
566
nr_pixblock_release (dpb);
567
item->state |= NR_ARENA_ITEM_STATE_INVALID;
658
/* Have to blit from cache */
659
nr_blit_pixblock_pixblock (pb, dpb);
660
nr_pixblock_release (dpb);
662
item->state |= NR_ARENA_ITEM_STATE_IMAGE;
574
/* Have to blit from cache */
575
nr_blit_pixblock_pixblock (pb, dpb);
576
nr_pixblock_release (dpb);
578
item->state |= NR_ARENA_ITEM_STATE_IMAGE;
665
return item->state | NR_ARENA_ITEM_STATE_RENDER;
581
return item->state | NR_ARENA_ITEM_STATE_RENDER;
669
585
nr_arena_item_invoke_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
671
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
672
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NR_ARENA_ITEM_STATE_INVALID);
673
/* we originally short-circuited if the object state included
674
* NR_ARENA_ITEM_STATE_CLIP (and showed a warning on the console);
675
* anyone know why we stopped doing so?
677
nr_return_val_if_fail ((pb->area.x1 - pb->area.x0) >= (area->x1 - area->x0), NR_ARENA_ITEM_STATE_INVALID);
678
nr_return_val_if_fail ((pb->area.y1 - pb->area.y0) >= (area->y1 - area->y0), NR_ARENA_ITEM_STATE_INVALID);
587
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
588
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
589
NR_ARENA_ITEM_STATE_INVALID);
590
/* we originally short-circuited if the object state included
591
* NR_ARENA_ITEM_STATE_CLIP (and showed a warning on the console);
592
* anyone know why we stopped doing so?
594
nr_return_val_if_fail ((pb->area.x1 - pb->area.x0) >=
595
(area->x1 - area->x0),
596
NR_ARENA_ITEM_STATE_INVALID);
597
nr_return_val_if_fail ((pb->area.y1 - pb->area.y0) >=
598
(area->y1 - area->y0),
599
NR_ARENA_ITEM_STATE_INVALID);
680
601
#ifdef NR_ARENA_ITEM_VERBOSE
681
printf ("Invoke clip by %p: %d %d - %d %d, item bbox %d %d - %d %d\n", item, area->x0, area->y0, area->x1, area->y1, (&item->bbox)->x0, (&item->bbox)->y0, (&item->bbox)->x1, (&item->bbox)->y1);
602
printf ("Invoke clip by %p: %d %d - %d %d, item bbox %d %d - %d %d\n",
603
item, area->x0, area->y0, area->x1, area->y1, (&item->bbox)->x0,
604
(&item->bbox)->y0, (&item->bbox)->x1, (&item->bbox)->y1);
684
if (item->visible && nr_rect_l_test_intersect (area, &item->bbox)) {
685
/* Need render that item */
686
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip) {
687
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS(item))->clip (item, area, pb);
607
if (item->visible && nr_rect_l_test_intersect (area, &item->bbox)) {
608
/* Need render that item */
609
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip) {
610
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
611
clip (item, area, pb);
695
nr_arena_item_invoke_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
619
nr_arena_item_invoke_pick (NRArenaItem *item, NR::Point p, double delta,
697
nr_return_val_if_fail (item != NULL, NULL);
698
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
700
// Sometimes there's no BBOX in item->state, reason unknown (bug 992817); I made this not an assert to remove the warning
701
if (!(item->state & NR_ARENA_ITEM_STATE_BBOX) || !(item->state & NR_ARENA_ITEM_STATE_PICK))
704
if (!sticky && !(item->visible && item->sensitive)) return NULL;
706
// TODO: rewrite using NR::Rect
707
const double x = p[NR::X];
708
const double y = p[NR::Y];
710
if (((x + delta) >= item->bbox.x0) &&
711
((x - delta) < item->bbox.x1) &&
712
((y + delta) >= item->bbox.y0) &&
713
((y - delta) < item->bbox.y1)) {
714
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
715
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick (item, p, delta, sticky);
622
nr_return_val_if_fail (item != NULL, NULL);
623
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
625
// Sometimes there's no BBOX in item->state, reason unknown (bug 992817); I made this not an assert to remove the warning
626
if (!(item->state & NR_ARENA_ITEM_STATE_BBOX)
627
|| !(item->state & NR_ARENA_ITEM_STATE_PICK))
630
if (!sticky && !(item->visible && item->sensitive))
633
// TODO: rewrite using NR::Rect
634
const double x = p[NR::X];
635
const double y = p[NR::Y];
637
if (((x + delta) >= item->bbox.x0) &&
638
((x - delta) < item->bbox.x1) &&
639
((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1)) {
640
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
641
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
642
pick (item, p, delta, sticky);
722
nr_arena_item_request_update (NRArenaItem *item, unsigned int reset, unsigned int propagate)
649
nr_arena_item_request_update (NRArenaItem *item, unsigned int reset,
650
unsigned int propagate)
724
nr_return_if_fail (item != NULL);
725
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
726
nr_return_if_fail (!(reset & NR_ARENA_ITEM_STATE_INVALID));
728
if (propagate && !item->propagate) item->propagate = TRUE;
730
if (item->state & reset) {
731
item->state &= ~reset;
733
nr_arena_item_request_update (item->parent, reset, FALSE);
735
nr_arena_request_update (item->arena, item);
652
nr_return_if_fail (item != NULL);
653
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
654
nr_return_if_fail (!(reset & NR_ARENA_ITEM_STATE_INVALID));
656
if (propagate && !item->propagate)
657
item->propagate = TRUE;
659
if (item->state & reset) {
660
item->state &= ~reset;
662
nr_arena_item_request_update (item->parent, reset, FALSE);
664
nr_arena_request_update (item->arena, item);
741
670
nr_arena_item_request_render (NRArenaItem *item)
743
nr_return_if_fail (item != NULL);
744
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
672
nr_return_if_fail (item != NULL);
673
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
746
nr_arena_request_render_rect (item->arena, &item->bbox);
675
nr_arena_request_render_rect (item->arena, &item->bbox);
752
681
nr_arena_item_unparent (NRArenaItem *item)
754
nr_return_val_if_fail (item != NULL, NULL);
755
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
757
nr_arena_item_request_render (item);
760
nr_arena_item_remove_child (item->parent, item);
683
nr_return_val_if_fail (item != NULL, NULL);
684
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
686
nr_arena_item_request_render (item);
689
nr_arena_item_remove_child (item->parent, item);
767
696
nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child)
769
nr_return_if_fail (parent != NULL);
770
nr_return_if_fail (NR_IS_ARENA_ITEM (parent));
771
nr_return_if_fail (child != NULL);
772
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
773
nr_return_if_fail (parent->arena == child->arena);
774
nr_return_if_fail (child->parent == NULL);
775
nr_return_if_fail (child->prev == NULL);
776
nr_return_if_fail (child->next == NULL);
778
nr_arena_item_add_child (parent, child, nr_arena_item_last_child (parent));
782
nr_arena_item_set_transform(NRArenaItem *item, NR::Matrix const &transform)
784
NRMatrix const t(transform);
785
nr_arena_item_set_transform(item, &t);
789
nr_arena_item_set_transform(NRArenaItem *item, NRMatrix const *transform)
791
const NRMatrix *ms, *md;
793
nr_return_if_fail (item != NULL);
794
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
796
if (!transform && !item->transform) return;
798
md = (item->transform) ? item->transform : &NR_MATRIX_IDENTITY;
799
ms = (transform) ? transform : &NR_MATRIX_IDENTITY;
801
if (!NR_MATRIX_DF_TEST_CLOSE (md, ms, NR_EPSILON)) {
802
nr_arena_item_request_render (item);
803
if (!transform || nr_matrix_test_identity (transform, NR_EPSILON)) {
804
/* Set to identity affine */
805
item->transform = NULL;
807
if (!item->transform) item->transform = new (GC::ATOMIC) NRMatrix();
808
*item->transform = *transform;
810
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
698
nr_return_if_fail (parent != NULL);
699
nr_return_if_fail (NR_IS_ARENA_ITEM (parent));
700
nr_return_if_fail (child != NULL);
701
nr_return_if_fail (NR_IS_ARENA_ITEM (child));
702
nr_return_if_fail (parent->arena == child->arena);
703
nr_return_if_fail (child->parent == NULL);
704
nr_return_if_fail (child->prev == NULL);
705
nr_return_if_fail (child->next == NULL);
707
nr_arena_item_add_child (parent, child, nr_arena_item_last_child (parent));
711
nr_arena_item_set_transform (NRArenaItem *item, NR::Matrix const &transform)
713
NRMatrix const t (transform);
714
nr_arena_item_set_transform (item, &t);
718
nr_arena_item_set_transform (NRArenaItem *item, NRMatrix const *transform)
720
nr_return_if_fail (item != NULL);
721
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
723
if (!transform && !item->transform)
726
const NRMatrix *md = (item->transform) ? item->transform : &NR_MATRIX_IDENTITY;
727
const NRMatrix *ms = (transform) ? transform : &NR_MATRIX_IDENTITY;
729
if (!NR_MATRIX_DF_TEST_CLOSE (md, ms, NR_EPSILON)) {
730
nr_arena_item_request_render (item);
731
if (!transform || nr_matrix_test_identity (transform, NR_EPSILON)) {
732
/* Set to identity affine */
733
item->transform = NULL;
735
if (!item->transform)
736
item->transform = new (GC::ATOMIC) NRMatrix ();
737
*item->transform = *transform;
739
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
815
744
nr_arena_item_set_opacity (NRArenaItem *item, double opacity)
817
nr_return_if_fail (item != NULL);
818
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
820
nr_arena_item_request_render (item);
822
item->opacity = (unsigned int) (opacity * 255.9999);
746
nr_return_if_fail (item != NULL);
747
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
749
nr_arena_item_request_render (item);
751
item->opacity = (unsigned int) (opacity * 255.9999);
826
755
nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive)
828
nr_return_if_fail (item != NULL);
829
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
831
/* fixme: mess with pick/repick... */
833
item->sensitive = sensitive;
757
nr_return_if_fail (item != NULL);
758
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
760
/* fixme: mess with pick/repick... */
762
item->sensitive = sensitive;
837
766
nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible)
839
nr_return_if_fail (item != NULL);
840
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
842
item->visible = visible;
844
nr_arena_item_request_render (item);
768
nr_return_if_fail (item != NULL);
769
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
771
item->visible = visible;
773
nr_arena_item_request_render (item);
848
777
nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip)
850
nr_return_if_fail (item != NULL);
851
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
852
nr_return_if_fail (!clip || NR_IS_ARENA_ITEM (clip));
779
nr_return_if_fail (item != NULL);
780
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
781
nr_return_if_fail (!clip || NR_IS_ARENA_ITEM (clip));
854
if (clip != item->clip) {
855
nr_arena_item_request_render (item);
856
if (item->clip) item->clip = nr_arena_item_detach (item, item->clip);
857
if (clip) item->clip = nr_arena_item_attach (item, clip, NULL, NULL);
858
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
783
if (clip != item->clip) {
784
nr_arena_item_request_render (item);
786
item->clip = nr_arena_item_detach (item, item->clip);
788
item->clip = nr_arena_item_attach (item, clip, NULL, NULL);
789
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
863
794
nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask)
865
nr_return_if_fail (item != NULL);
866
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
867
nr_return_if_fail (!mask || NR_IS_ARENA_ITEM (mask));
796
nr_return_if_fail (item != NULL);
797
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
798
nr_return_if_fail (!mask || NR_IS_ARENA_ITEM (mask));
869
if (mask != item->mask) {
870
nr_arena_item_request_render (item);
871
if (item->mask) item->mask = nr_arena_item_detach (item, item->mask);
872
if (mask) item->mask = nr_arena_item_attach (item, mask, NULL, NULL);
873
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
800
if (mask != item->mask) {
801
nr_arena_item_request_render (item);
803
item->mask = nr_arena_item_detach (item, item->mask);
805
item->mask = nr_arena_item_attach (item, mask, NULL, NULL);
806
nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
878
811
nr_arena_item_set_order (NRArenaItem *item, int order)
880
NRArenaItem *children, *child, *ref;
883
nr_return_if_fail (item != NULL);
884
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
886
if (!item->parent) return;
888
children = nr_arena_item_children (item->parent);
892
for (child = children; child != NULL; child = child->next) {
893
if (pos >= order) break;
900
nr_arena_item_set_child_position (item->parent, item, ref);
813
nr_return_if_fail (item != NULL);
814
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
819
NRArenaItem *children = nr_arena_item_children (item->parent);
821
NRArenaItem *ref = NULL;
823
for (NRArenaItem *child = children; child != NULL; child = child->next) {
832
nr_arena_item_set_child_position (item->parent, item, ref);
836
nr_arena_item_set_item_bbox (NRArenaItem *item, NR::Maybe<NR::Rect> &bbox)
838
nr_return_if_fail(item != NULL);
839
nr_return_if_fail(NR_IS_ARENA_ITEM(item));
841
item->item_bbox = bbox;
844
/** Returns a background image for use with filter effects. */
846
nr_arena_item_get_background (NRArenaItem const *item, int depth)
849
if (!item->background_pb)
851
if (item->background_new) {
852
pb = new NRPixBlock ();
853
nr_pixblock_setup_fast (pb, item->background_pb->mode,
854
item->background_pb->area.x0,
855
item->background_pb->area.y0,
856
item->background_pb->area.x1,
857
item->background_pb->area.y1, true);
858
if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) // allocation failed
860
} else if (item->parent) {
861
pb = nr_arena_item_get_background (item->parent, depth + 1);
866
nr_blit_pixblock_pixblock (pb, item->background_pb);
906
nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child, NRArenaItem *prev, NRArenaItem *next)
874
nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child,
875
NRArenaItem *prev, NRArenaItem *next)
908
nr_return_val_if_fail (parent != NULL, NULL);
909
nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
910
nr_return_val_if_fail (child != NULL, NULL);
911
nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
912
nr_return_val_if_fail (child->parent == NULL, NULL);
913
nr_return_val_if_fail (child->prev == NULL, NULL);
914
nr_return_val_if_fail (child->next == NULL, NULL);
915
nr_return_val_if_fail (!prev || NR_IS_ARENA_ITEM (prev), NULL);
916
nr_return_val_if_fail (!prev || (prev->parent == parent), NULL);
917
nr_return_val_if_fail (!prev || (prev->next == next), NULL);
918
nr_return_val_if_fail (!next || NR_IS_ARENA_ITEM (next), NULL);
919
nr_return_val_if_fail (!next || (next->parent == parent), NULL);
920
nr_return_val_if_fail (!next || (next->prev == prev), NULL);
922
child->parent = parent;
926
if (prev) prev->next = child;
927
if (next) next->prev = child;
877
nr_return_val_if_fail (parent != NULL, NULL);
878
nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
879
nr_return_val_if_fail (child != NULL, NULL);
880
nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
881
nr_return_val_if_fail (child->parent == NULL, NULL);
882
nr_return_val_if_fail (child->prev == NULL, NULL);
883
nr_return_val_if_fail (child->next == NULL, NULL);
884
nr_return_val_if_fail (!prev || NR_IS_ARENA_ITEM (prev), NULL);
885
nr_return_val_if_fail (!prev || (prev->parent == parent), NULL);
886
nr_return_val_if_fail (!prev || (prev->next == next), NULL);
887
nr_return_val_if_fail (!next || NR_IS_ARENA_ITEM (next), NULL);
888
nr_return_val_if_fail (!next || (next->parent == parent), NULL);
889
nr_return_val_if_fail (!next || (next->prev == prev), NULL);
891
child->parent = parent;
933
904
nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child)
935
NRArenaItem *prev, *next;
937
nr_return_val_if_fail (parent != NULL, NULL);
938
nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
939
nr_return_val_if_fail (child != NULL, NULL);
940
nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
941
nr_return_val_if_fail (child->parent == parent, NULL);
946
child->parent = NULL;
950
if (prev) prev->next = next;
951
if (next) next->prev = prev;
906
nr_return_val_if_fail (parent != NULL, NULL);
907
nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
908
nr_return_val_if_fail (child != NULL, NULL);
909
nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
910
nr_return_val_if_fail (child->parent == parent, NULL);
912
NRArenaItem *prev = child->prev;
913
NRArenaItem *next = child->next;
915
child->parent = NULL;
962
#ifdef arena_item_tile_cache
963
typedef struct cache_entry {
974
int hash_max=2048,hash_fill=1024;
979
int nbEnt=0,maxEnt=0;
980
cache_entry* entries=NULL;
982
//#define tile_cache_stats
983
#ifdef tile_cache_stats
984
double hits=0,misses=0;
988
int hash_that(NRArenaItem* owner,int th,int tv)
990
int res=GPOINTER_TO_INT(owner);
996
if ( res < 0 ) res=-res;
1001
bool test_cache(NRArenaItem* owner,int th,int tv,NRPixBlock &ipb,NRPixBlock &mpb,bool &hasMask)
1003
if ( keys == NULL ) {
1004
hash_max = prefs_get_int_attribute ("options.arenatilescachesize", "value", 2048);
1005
hash_fill=(hash_max*3)/4;
1006
keys=(int*)malloc(hash_max*sizeof(int));
1007
for (int i=0;i<hash_max;i++) keys[i]=-1;
1009
int key=hash_that(owner,th,tv);
1010
if ( keys[key] < 0 ) {
1011
#ifdef tile_cache_stats
1017
while ( cur >= 0 && cur < nbEnt ) {
1018
if ( entries[cur].owner == owner && entries[cur].th == th && entries[cur].tv == tv ) {
1019
hasMask=entries[cur].hasMask;
1020
ipb=entries[cur].ipb;
1021
mpb=entries[cur].mpb;
1022
#ifdef tile_cache_stats
1027
cur=entries[cur].next;
1029
#ifdef tile_cache_stats
1034
void remove_one_cache(int no)
1036
if ( no < 0 || no >= nbEnt ) return;
1038
nr_pixblock_release(&entries[no].ipb);
1039
if ( entries[no].hasMask ) nr_pixblock_release(&entries[no].mpb);
1041
if ( entries[no].prev >= 0 ) entries[entries[no].prev].next=entries[no].next;
1042
if ( entries[no].next >= 0 ) entries[entries[no].next].prev=entries[no].prev;
1043
if ( entries[no].prev < 0 ) keys[entries[no].key]=entries[no].next;
1044
entries[no].prev=entries[no].next=entries[no].key=-1;
1046
if ( no == nbEnt-1 ) {
1050
entries[no]=entries[--nbEnt];
1051
if ( entries[no].prev >= 0 ) entries[entries[no].prev].next=no;
1052
if ( entries[no].next >= 0 ) entries[entries[no].next].prev=no;
1053
if ( entries[no].prev < 0 ) keys[entries[no].key]=no;
1055
void remove_caches(NRArenaItem* owner)
1057
if ( keys == NULL ) {
1058
hash_max = prefs_get_int_attribute ("options.arenatilescachesize", "value", 2048);
1059
hash_fill=(hash_max*3)/4;
1060
keys=(int*)malloc(hash_max*sizeof(int));
1061
for (int i=0;i<hash_max;i++) keys[i]=-1;
1063
for (int i=nbEnt-1;i>=0;i--) {
1064
if ( entries[i].owner == owner ) {
1065
remove_one_cache(i);
1069
void age_cache(void)
1071
for (int i=0;i<nbEnt;i++) entries[i].score*=0.95;
1073
bool insert_cache(NRArenaItem* owner,int th,int tv,NRPixBlock *ipb,NRPixBlock *mpb,double activity,double duration)
1075
if ( keys == NULL ) {
1076
hash_max = prefs_get_int_attribute ("options.arenatilescachesize", "value", 2048);
1077
hash_fill=(hash_max*3)/4;
1078
keys=(int*)malloc(hash_max*sizeof(int));
1079
for (int i=0;i<hash_max;i++) keys[i]=-1;
1081
for (int i=0;i<nbEnt;i++) entries[i].score*=0.95;
1082
#ifdef tile_cache_stats
1086
if ( hitMissCount > 100 ) {
1088
printf("hit/miss = %f used/total=%i/%i\n",(misses>0.001)?hits/misses:100000.0,nbEnt,hash_max); // localizing ok
1091
int key=hash_that(owner,th,tv);
1092
double nScore=/*activity**/duration;
1094
if ( keys[key] >= 0 ) {
1096
while ( cur >= 0 && cur < nbEnt ) {
1097
if ( entries[cur].owner == owner && entries[cur].th == th && entries[cur].tv == tv ) {
1098
remove_one_cache(cur);
1101
cur=entries[cur].next;
1106
if ( nbEnt < hash_fill ) {
1109
double worstS=entries[0].score;
1111
for (int i=1;i<nbEnt;i++) {
1112
if ( entries[i].score < worstS ) {
1113
worstS=entries[i].score;
1117
if ( worstS < nScore ) {
1119
remove_one_cache(worstE);
1122
if ( doAdd == false ) return false;
1123
if ( nbEnt >= maxEnt ) {
1125
entries=(cache_entry*)realloc(entries,maxEnt*sizeof(cache_entry));
1127
entries[nbEnt].key=key;
1128
entries[nbEnt].score=nScore;
1129
entries[nbEnt].owner=owner;
1130
entries[nbEnt].th=th;
1131
entries[nbEnt].tv=tv;
1132
entries[nbEnt].prev=entries[nbEnt].next=-1;
1133
entries[nbEnt].ipb=*ipb;
1135
entries[nbEnt].hasMask=true;
1136
entries[nbEnt].mpb=*mpb;
1138
entries[nbEnt].hasMask=false;
1140
entries[nbEnt].next=keys[key];
1141
if ( entries[nbEnt].next >= 0 ) entries[entries[nbEnt].next].prev=nbEnt;
930
c-file-style:"stroustrup"
931
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
936
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :