083e7a7f4a7b35e36179c16cd27f67a970ed1c7d
1 #define __NR_ARENA_GLYPHS_C__
3 /*
4 * RGBA display list system for inkscape
5 *
6 * Author:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 2002 Lauris Kaplinski
10 *
11 * Released under GNU GPL
12 *
13 */
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
19 #include <libnr/nr-blit.h>
20 #include <libnr/nr-path.h>
21 #include "../style.h"
22 #include "nr-arena.h"
23 #include "nr-arena-glyphs.h"
25 #ifdef test_glyph_liv
26 #include "../display/canvas-bpath.h"
27 #include <libnrtype/font-instance.h>
28 #include <libnrtype/raster-glyph.h>
29 #include <libnrtype/RasterFont.h>
31 // defined in nr-arena-shape.cpp
32 void nr_pixblock_render_shape_mask_or(NRPixBlock &m, Shape *theS);
33 #endif
35 static void nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass);
36 static void nr_arena_glyphs_init(NRArenaGlyphs *glyphs);
37 static void nr_arena_glyphs_finalize(NRObject *object);
39 static guint nr_arena_glyphs_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
40 static guint nr_arena_glyphs_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
41 static NRArenaItem *nr_arena_glyphs_pick(NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
43 static NRArenaItemClass *glyphs_parent_class;
45 NRType
46 nr_arena_glyphs_get_type(void)
47 {
48 static NRType type = 0;
49 if (!type) {
50 type = nr_object_register_type(NR_TYPE_ARENA_ITEM,
51 "NRArenaGlyphs",
52 sizeof(NRArenaGlyphsClass),
53 sizeof(NRArenaGlyphs),
54 (void (*)(NRObjectClass *)) nr_arena_glyphs_class_init,
55 (void (*)(NRObject *)) nr_arena_glyphs_init);
56 }
57 return type;
58 }
60 static void
61 nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass)
62 {
63 NRObjectClass *object_class;
64 NRArenaItemClass *item_class;
66 object_class = (NRObjectClass *) klass;
67 item_class = (NRArenaItemClass *) klass;
69 glyphs_parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
71 object_class->finalize = nr_arena_glyphs_finalize;
72 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphs>;
74 item_class->update = nr_arena_glyphs_update;
75 item_class->clip = nr_arena_glyphs_clip;
76 item_class->pick = nr_arena_glyphs_pick;
77 }
79 static void
80 nr_arena_glyphs_init(NRArenaGlyphs *glyphs)
81 {
82 glyphs->style = NULL;
83 nr_matrix_set_identity(&glyphs->g_transform);
84 glyphs->font = NULL;
85 glyphs->glyph = 0;
87 glyphs->rfont = NULL;
88 glyphs->sfont = NULL;
89 glyphs->x = glyphs->y = 0.0;
90 }
92 static void
93 nr_arena_glyphs_finalize(NRObject *object)
94 {
95 NRArenaGlyphs *glyphs = static_cast<NRArenaGlyphs *>(object);
97 if (glyphs->rfont) {
98 glyphs->rfont->Unref();
99 glyphs->rfont=NULL;
100 }
101 if (glyphs->sfont) {
102 glyphs->sfont->Unref();
103 glyphs->sfont=NULL;
104 }
106 if (glyphs->font) {
107 glyphs->font->Unref();
108 glyphs->font=NULL;
109 }
111 if (glyphs->style) {
112 sp_style_unref(glyphs->style);
113 glyphs->style = NULL;
114 }
116 ((NRObjectClass *) glyphs_parent_class)->finalize(object);
117 }
119 static guint
120 nr_arena_glyphs_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset)
121 {
122 NRArenaGlyphs *glyphs;
123 raster_font *rfont;
125 glyphs = NR_ARENA_GLYPHS(item);
127 if (!glyphs->font || !glyphs->style) return NR_ARENA_ITEM_STATE_ALL;
128 if ((glyphs->style->fill.type == SP_PAINT_TYPE_NONE) && (glyphs->style->stroke.type == SP_PAINT_TYPE_NONE)) return NR_ARENA_ITEM_STATE_ALL;
130 NRRect bbox;
131 bbox.x0 = bbox.y0 = NR_HUGE;
132 bbox.x1 = bbox.y1 = -NR_HUGE;
134 float const scale = NR_MATRIX_DF_EXPANSION(&gc->transform);
136 if (glyphs->style->fill.type != SP_PAINT_TYPE_NONE) {
137 NRMatrix t;
138 nr_matrix_multiply(&t, &glyphs->g_transform, &gc->transform);
139 glyphs->x = t.c[4];
140 glyphs->y = t.c[5];
141 t.c[4]=0;
142 t.c[5]=0;
143 rfont = glyphs->font->RasterFont(t, 0);
144 if (glyphs->rfont) glyphs->rfont->Unref();
145 glyphs->rfont = rfont;
147 if (glyphs->style->stroke.type == SP_PAINT_TYPE_NONE || fabs(glyphs->style->stroke_width.computed * scale) <= 0.01) { // Optimization: do fill bbox only if there's no stroke
148 NRRect narea;
149 if ( glyphs->rfont ) glyphs->rfont->BBox(glyphs->glyph, &narea);
150 bbox.x0 = narea.x0 + glyphs->x;
151 bbox.y0 = narea.y0 + glyphs->y;
152 bbox.x1 = narea.x1 + glyphs->x;
153 bbox.y1 = narea.y1 + glyphs->y;
154 }
155 }
157 if (glyphs->style->stroke.type != SP_PAINT_TYPE_NONE) {
158 /* Build state data */
159 NRMatrix t;
160 nr_matrix_multiply(&t, &glyphs->g_transform, &gc->transform);
161 glyphs->x = t.c[4];
162 glyphs->y = t.c[5];
163 t.c[4]=0;
164 t.c[5]=0;
166 if ( fabs(glyphs->style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
167 font_style nstyl;
168 nstyl.transform = t;
169 nstyl.stroke_width=MAX(0.125, glyphs->style->stroke_width.computed * scale);
170 if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_BUTT ) nstyl.stroke_cap=butt_straight;
171 if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_ROUND ) nstyl.stroke_cap=butt_round;
172 if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_SQUARE ) nstyl.stroke_cap=butt_square;
173 if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_MITER ) nstyl.stroke_join=join_pointy;
174 if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_ROUND ) nstyl.stroke_join=join_round;
175 if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_BEVEL ) nstyl.stroke_join=join_straight;
176 nstyl.stroke_miter_limit = glyphs->style->stroke_miterlimit.value;
177 nstyl.nbDash=0;
178 nstyl.dashes=NULL;
179 if ( glyphs->style->stroke_dash.n_dash > 0 ) {
180 nstyl.nbDash=glyphs->style->stroke_dash.n_dash;
181 nstyl.dashes=(double*)malloc(nstyl.nbDash*sizeof(double));
182 for (int i = 0; i < nstyl.nbDash; i++) nstyl.dashes[i]= glyphs->style->stroke_dash.dash[i] * scale;
183 }
184 rfont = glyphs->font->RasterFont( nstyl);
185 if ( nstyl.dashes ) free(nstyl.dashes);
186 if (glyphs->sfont) glyphs->sfont->Unref();
187 glyphs->sfont = rfont;
189 NRRect narea;
190 if ( glyphs->sfont ) glyphs->sfont->BBox(glyphs->glyph, &narea);
191 narea.x0-=nstyl.stroke_width;
192 narea.y0-=nstyl.stroke_width;
193 narea.x1+=nstyl.stroke_width;
194 narea.y1+=nstyl.stroke_width;
195 bbox.x0 = narea.x0 + glyphs->x;
196 bbox.y0 = narea.y0 + glyphs->y;
197 bbox.x1 = narea.x1 + glyphs->x;
198 bbox.y1 = narea.y1 + glyphs->y;
199 }
200 }
201 if (nr_rect_d_test_empty(&bbox)) return NR_ARENA_ITEM_STATE_ALL;
203 item->bbox.x0 = (gint32)(bbox.x0 - 1.0);
204 item->bbox.y0 = (gint32)(bbox.y0 - 1.0);
205 item->bbox.x1 = (gint32)(bbox.x1 + 1.0);
206 item->bbox.y1 = (gint32)(bbox.y1 + 1.0);
207 nr_arena_request_render_rect(item->arena, &item->bbox);
209 return NR_ARENA_ITEM_STATE_ALL;
210 }
212 static guint
213 nr_arena_glyphs_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
214 {
215 NRArenaGlyphs *glyphs;
217 glyphs = NR_ARENA_GLYPHS(item);
219 if (!glyphs->font ) return item->state;
221 /* TODO : render to greyscale pixblock provided for clipping */
223 return item->state;
224 }
226 static NRArenaItem *
227 nr_arena_glyphs_pick(NRArenaItem *item, NR::Point p, gdouble delta, unsigned int sticky)
228 {
229 NRArenaGlyphs *glyphs;
231 glyphs = NR_ARENA_GLYPHS(item);
233 if (!glyphs->font ) return NULL;
234 if (!glyphs->style) return NULL;
236 double const x = p[NR::X];
237 double const y = p[NR::Y];
238 /* With text we take a simple approach: pick if the point is in a characher bbox */
239 if ((x >= item->bbox.x0) && (y >= item->bbox.y0) && (x <= item->bbox.x1) && (y <= item->bbox.y1)) return item;
241 return NULL;
242 }
244 void
245 nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve *curve, unsigned int lieutenant, font_instance *font, gint glyph, NRMatrix const *transform)
246 {
247 nr_return_if_fail(glyphs != NULL);
248 nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
250 nr_arena_item_request_render(NR_ARENA_ITEM(glyphs));
252 if (transform) {
253 glyphs->g_transform = *transform;
254 } else {
255 nr_matrix_set_identity(&glyphs->g_transform);
256 }
258 if (font) font->Ref();
259 if (glyphs->font) glyphs->font->Unref();
260 glyphs->font=font;
261 glyphs->glyph = glyph;
263 nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
264 }
266 void
267 nr_arena_glyphs_set_style(NRArenaGlyphs *glyphs, SPStyle *style)
268 {
269 nr_return_if_fail(glyphs != NULL);
270 nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
272 if (style) sp_style_ref(style);
273 if (glyphs->style) sp_style_unref(glyphs->style);
274 glyphs->style = style;
276 nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
277 }
279 static guint
280 nr_arena_glyphs_fill_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m)
281 {
282 /* fixme: area == m->area, so merge these */
284 NRArenaItem *item = NR_ARENA_ITEM(glyphs);
286 if (glyphs->rfont && nr_rect_l_test_intersect(area, &item->bbox)) {
287 raster_glyph *g = glyphs->rfont->GetGlyph(glyphs->glyph);
288 if ( g ) g->Blit(NR::Point(glyphs->x, glyphs->y), *m);
289 }
291 return item->state;
292 }
294 static guint
295 nr_arena_glyphs_stroke_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m)
296 {
297 NRArenaItem *item = NR_ARENA_ITEM(glyphs);
298 if (glyphs->sfont && nr_rect_l_test_intersect(area, &item->bbox)) {
299 raster_glyph *g=glyphs->sfont->GetGlyph(glyphs->glyph);
300 if ( g ) g->Blit(NR::Point(glyphs->x, glyphs->y),*m);
301 }
303 return item->state;
304 }
306 static void nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass);
307 static void nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group);
308 static void nr_arena_glyphs_group_finalize(NRObject *object);
310 static guint nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset);
311 static unsigned int nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
312 static unsigned int nr_arena_glyphs_group_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
313 static NRArenaItem *nr_arena_glyphs_group_pick(NRArenaItem *item, NR::Point p, gdouble delta, unsigned int sticky);
315 static NRArenaGroupClass *group_parent_class;
317 NRType
318 nr_arena_glyphs_group_get_type(void)
319 {
320 static NRType type = 0;
321 if (!type) {
322 type = nr_object_register_type(NR_TYPE_ARENA_GROUP,
323 "NRArenaGlyphsGroup",
324 sizeof(NRArenaGlyphsGroupClass),
325 sizeof(NRArenaGlyphsGroup),
326 (void (*)(NRObjectClass *)) nr_arena_glyphs_group_class_init,
327 (void (*)(NRObject *)) nr_arena_glyphs_group_init);
328 }
329 return type;
330 }
332 static void
333 nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass)
334 {
335 NRObjectClass *object_class;
336 NRArenaItemClass *item_class;
338 object_class = (NRObjectClass *) klass;
339 item_class = (NRArenaItemClass *) klass;
341 group_parent_class = (NRArenaGroupClass *) ((NRObjectClass *) klass)->parent;
343 object_class->finalize = nr_arena_glyphs_group_finalize;
344 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphsGroup>;
346 item_class->update = nr_arena_glyphs_group_update;
347 item_class->render = nr_arena_glyphs_group_render;
348 item_class->clip = nr_arena_glyphs_group_clip;
349 item_class->pick = nr_arena_glyphs_group_pick;
350 }
352 static void
353 nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group)
354 {
355 group->style = NULL;
356 group->paintbox.x0 = group->paintbox.y0 = 0.0F;
357 group->paintbox.x1 = group->paintbox.y1 = 1.0F;
359 group->fill_painter = NULL;
360 group->stroke_painter = NULL;
361 }
363 static void
364 nr_arena_glyphs_group_finalize(NRObject *object)
365 {
366 NRArenaGlyphsGroup *group=static_cast<NRArenaGlyphsGroup *>(object);
368 if (group->fill_painter) {
369 sp_painter_free(group->fill_painter);
370 group->fill_painter = NULL;
371 }
373 if (group->stroke_painter) {
374 sp_painter_free(group->stroke_painter);
375 group->stroke_painter = NULL;
376 }
378 if (group->style) {
379 sp_style_unref(group->style);
380 group->style = NULL;
381 }
383 ((NRObjectClass *) group_parent_class)->finalize(object);
384 }
386 static guint
387 nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset)
388 {
389 NRArenaGlyphsGroup *group = NR_ARENA_GLYPHS_GROUP(item);
391 if (group->fill_painter) {
392 sp_painter_free(group->fill_painter);
393 group->fill_painter = NULL;
394 }
396 if (group->stroke_painter) {
397 sp_painter_free(group->stroke_painter);
398 group->stroke_painter = NULL;
399 }
401 item->render_opacity = TRUE;
402 if (group->style->fill.type == SP_PAINT_TYPE_PAINTSERVER) {
403 group->fill_painter = sp_paint_server_painter_new(SP_STYLE_FILL_SERVER(group->style),
404 NR::Matrix(&gc->transform), NR::Matrix(&gc->parent->transform),
405 &group->paintbox);
406 item->render_opacity = FALSE;
407 }
409 if (group->style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) {
410 group->stroke_painter = sp_paint_server_painter_new(SP_STYLE_STROKE_SERVER(group->style),
411 NR::Matrix(&gc->transform), NR::Matrix(&gc->parent->transform),
412 &group->paintbox);
413 item->render_opacity = FALSE;
414 }
416 if ( item->render_opacity == TRUE && group->style->stroke.type != SP_PAINT_TYPE_NONE && group->style->fill.type != SP_PAINT_TYPE_NONE ) {
417 item->render_opacity=FALSE;
418 }
420 if (((NRArenaItemClass *) group_parent_class)->update)
421 return ((NRArenaItemClass *) group_parent_class)->update(item, area, gc, state, reset);
423 return NR_ARENA_ITEM_STATE_ALL;
424 }
426 /* This sucks - as soon, as we have inheritable renderprops, do something with that opacity */
428 static unsigned int
429 nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
430 {
431 NRArenaItem *child;
433 NRArenaGroup *group = NR_ARENA_GROUP(item);
434 NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
435 SPStyle const *style = ggroup->style;
437 guint ret = item->state;
439 /* Fill */
440 if (style->fill.type != SP_PAINT_TYPE_NONE || item->arena->rendermode == RENDERMODE_OUTLINE) {
441 NRPixBlock m;
442 nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
443 m.visible_area = pb->visible_area;
445 /* Render children fill mask */
446 for (child = group->children; child != NULL; child = child->next) {
447 ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, &m);
448 if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) {
449 nr_pixblock_release(&m);
450 return ret;
451 }
452 }
454 /* Composite into buffer */
455 if (style->fill.type == SP_PAINT_TYPE_COLOR || item->arena->rendermode == RENDERMODE_OUTLINE) {
456 guint32 rgba;
457 if (item->arena->rendermode == RENDERMODE_OUTLINE) {
458 // In outline mode, render fill only, using outlinecolor
459 rgba = item->arena->outlinecolor;
460 } else if ( item->render_opacity ) {
461 rgba = sp_color_get_rgba32_falpha(&style->fill.value.color,
462 SP_SCALE24_TO_FLOAT(style->fill_opacity.value) *
463 SP_SCALE24_TO_FLOAT(style->opacity.value));
464 } else {
465 rgba = sp_color_get_rgba32_falpha(&style->fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value));
466 }
467 nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
468 pb->empty = FALSE;
469 } else if (style->fill.type == SP_PAINT_TYPE_PAINTSERVER) {
470 if (ggroup->fill_painter) {
471 nr_arena_render_paintserver_fill(pb, area, ggroup->fill_painter, SP_SCALE24_TO_FLOAT(style->fill_opacity.value), &m);
472 }
473 }
475 nr_pixblock_release(&m);
476 }
478 /* Stroke */
479 if (style->stroke.type != SP_PAINT_TYPE_NONE && !(item->arena->rendermode == RENDERMODE_OUTLINE)) {
480 NRPixBlock m;
481 guint32 rgba;
482 nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
483 m.visible_area = pb->visible_area;
484 /* Render children stroke mask */
485 for (child = group->children; child != NULL; child = child->next) {
486 ret = nr_arena_glyphs_stroke_mask(NR_ARENA_GLYPHS(child), area, &m);
487 if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) {
488 nr_pixblock_release(&m);
489 return ret;
490 }
491 }
492 /* Composite into buffer */
493 switch (style->stroke.type) {
494 case SP_PAINT_TYPE_COLOR:
495 if ( item->render_opacity ) {
496 rgba = sp_color_get_rgba32_falpha(&style->stroke.value.color,
497 SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) *
498 SP_SCALE24_TO_FLOAT(style->opacity.value));
499 } else {
500 rgba = sp_color_get_rgba32_falpha(&style->stroke.value.color,
501 SP_SCALE24_TO_FLOAT(style->stroke_opacity.value));
502 }
503 nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
504 pb->empty = FALSE;
505 break;
506 case SP_PAINT_TYPE_PAINTSERVER:
507 if (ggroup->stroke_painter) {
508 nr_arena_render_paintserver_fill(pb, area, ggroup->stroke_painter, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value), &m);
509 }
510 break;
511 default:
512 break;
513 }
514 nr_pixblock_release(&m);
515 }
517 return ret;
518 }
520 static unsigned int
521 nr_arena_glyphs_group_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
522 {
523 NRArenaGroup *group = NR_ARENA_GROUP(item);
525 guint ret = item->state;
527 /* Render children fill mask */
528 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
529 ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, pb);
530 if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) return ret;
531 }
533 return ret;
534 }
536 static NRArenaItem *
537 nr_arena_glyphs_group_pick(NRArenaItem *item, NR::Point p, gdouble delta, unsigned int sticky)
538 {
539 NRArenaItem *picked = NULL;
541 if (((NRArenaItemClass *) group_parent_class)->pick)
542 picked = ((NRArenaItemClass *) group_parent_class)->pick(item, p, delta, sticky);
544 if (picked) picked = item;
546 return picked;
547 }
549 void
550 nr_arena_glyphs_group_clear(NRArenaGlyphsGroup *sg)
551 {
552 NRArenaGroup *group = NR_ARENA_GROUP(sg);
554 nr_arena_item_request_render(NR_ARENA_ITEM(group));
556 while (group->children) {
557 nr_arena_item_remove_child(NR_ARENA_ITEM(group), group->children);
558 }
559 }
561 void
562 nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, NRMatrix const *transform)
563 {
564 NRArenaGroup *group;
565 NRBPath bpath;
567 group = NR_ARENA_GROUP(sg);
569 bpath.path = ( font
570 ? (NArtBpath *) font->ArtBPath(glyph)
571 : NULL );
572 if ( bpath.path ) {
574 nr_arena_item_request_render(NR_ARENA_ITEM(group));
576 NRArenaItem *new_arena = NRArenaGlyphs::create(group->arena);
577 nr_arena_item_append_child(NR_ARENA_ITEM(group), new_arena);
578 nr_arena_item_unref(new_arena);
579 nr_arena_glyphs_set_path(NR_ARENA_GLYPHS(new_arena), NULL, FALSE, font, glyph, transform);
580 nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(new_arena), sg->style);
581 }
582 }
584 void
585 nr_arena_glyphs_group_set_style(NRArenaGlyphsGroup *sg, SPStyle *style)
586 {
587 nr_return_if_fail(sg != NULL);
588 nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(sg));
590 NRArenaGroup *group = NR_ARENA_GROUP(sg);
592 if (style) sp_style_ref(style);
593 if (sg->style) sp_style_unref(sg->style);
594 sg->style = style;
596 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
597 nr_return_if_fail(NR_IS_ARENA_GLYPHS(child));
598 nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(child), sg->style);
599 }
601 nr_arena_item_request_update(NR_ARENA_ITEM(sg), NR_ARENA_ITEM_STATE_ALL, FALSE);
602 }
604 void
605 nr_arena_glyphs_group_set_paintbox(NRArenaGlyphsGroup *gg, NRRect const *pbox)
606 {
607 nr_return_if_fail(gg != NULL);
608 nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(gg));
609 nr_return_if_fail(pbox != NULL);
611 if ((pbox->x0 < pbox->x1) && (pbox->y0 < pbox->y1)) {
612 gg->paintbox.x0 = pbox->x0;
613 gg->paintbox.y0 = pbox->y0;
614 gg->paintbox.x1 = pbox->x1;
615 gg->paintbox.y1 = pbox->y1;
616 } else {
617 /* fixme: We kill warning, although not sure what to do here (Lauris) */
618 gg->paintbox.x0 = gg->paintbox.y0 = 0.0F;
619 gg->paintbox.x1 = gg->paintbox.y1 = 256.0F;
620 }
622 nr_arena_item_request_update(NR_ARENA_ITEM(gg), NR_ARENA_ITEM_STATE_ALL, FALSE);
623 }
626 /*
627 Local Variables:
628 mode:c++
629 c-file-style:"stroustrup"
630 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
631 indent-tabs-mode:nil
632 fill-column:99
633 End:
634 */
635 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :