19
19
#include <libnr/nr-blit.h>
20
20
#include <libnr/nr-path.h>
21
#include <libnr/n-art-bpath.h>
22
#include <libnr/nr-matrix-ops.h>
23
#include <libnr/nr-matrix-fns.h>
21
24
#include "../style.h"
22
25
#include "nr-arena.h"
23
26
#include "nr-arena-glyphs.h"
28
#include "inkscape-cairo.h"
25
30
#ifdef test_glyph_liv
26
31
#include "../display/canvas-bpath.h"
120
nr_arena_glyphs_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, guint reset)
125
nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*state*/, guint /*reset*/)
122
127
NRArenaGlyphs *glyphs;
123
128
raster_font *rfont;
125
130
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;
132
if (!glyphs->font || !glyphs->style)
133
return NR_ARENA_ITEM_STATE_ALL;
134
if ((glyphs->style->fill.isNone()) && (glyphs->style->stroke.isNone()))
135
return NR_ARENA_ITEM_STATE_ALL;
131
138
bbox.x0 = bbox.y0 = NR_HUGE;
144
151
if (glyphs->rfont) glyphs->rfont->Unref();
145
152
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
154
if (glyphs->style->stroke.isNone() || fabs(glyphs->style->stroke_width.computed * scale) <= 0.01) { // Optimization: do fill bbox only if there's no stroke
149
156
if ( glyphs->rfont ) glyphs->rfont->BBox(glyphs->glyph, &narea);
150
157
bbox.x0 = narea.x0 + glyphs->x;
152
159
bbox.x1 = narea.x1 + glyphs->x;
153
160
bbox.y1 = narea.y1 + glyphs->y;
157
if (glyphs->style->stroke.type != SP_PAINT_TYPE_NONE) {
164
if (!glyphs->style->stroke.isNone()) {
158
165
/* Build state data */
160
167
nr_matrix_multiply(&t, &glyphs->g_transform, &gc->transform);
245
nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve *curve, unsigned int lieutenant, font_instance *font, gint glyph, NRMatrix const *transform)
253
nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, NRMatrix const *transform)
247
255
nr_return_if_fail(glyphs != NULL);
248
256
nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
250
258
nr_arena_item_request_render(NR_ARENA_ITEM(glyphs));
253
261
glyphs->g_transform = *transform;
255
263
nr_matrix_set_identity(&glyphs->g_transform);
258
266
if (font) font->Ref();
259
267
if (glyphs->font) glyphs->font->Unref();
260
268
glyphs->font=font;
308
316
static void nr_arena_glyphs_group_finalize(NRObject *object);
310
318
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);
319
static unsigned int nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
312
320
static unsigned int nr_arena_glyphs_group_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
313
321
static NRArenaItem *nr_arena_glyphs_group_pick(NRArenaItem *item, NR::Point p, gdouble delta, unsigned int sticky);
401
409
item->render_opacity = TRUE;
402
if (group->style->fill.type == SP_PAINT_TYPE_PAINTSERVER) {
410
if (group->style->fill.isPaintserver()) {
403
411
group->fill_painter = sp_paint_server_painter_new(SP_STYLE_FILL_SERVER(group->style),
404
412
NR::Matrix(&gc->transform), NR::Matrix(&gc->parent->transform),
405
413
&group->paintbox);
406
414
item->render_opacity = FALSE;
409
if (group->style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) {
417
if (group->style->stroke.isPaintserver()) {
410
418
group->stroke_painter = sp_paint_server_painter_new(SP_STYLE_STROKE_SERVER(group->style),
411
419
NR::Matrix(&gc->transform), NR::Matrix(&gc->parent->transform),
412
420
&group->paintbox);
413
421
item->render_opacity = FALSE;
416
if ( item->render_opacity == TRUE && group->style->stroke.type != SP_PAINT_TYPE_NONE && group->style->fill.type != SP_PAINT_TYPE_NONE ) {
424
if ( item->render_opacity == TRUE && !group->style->stroke.isNone() && !group->style->fill.isNone() ) {
417
425
item->render_opacity=FALSE;
423
431
return NR_ARENA_ITEM_STATE_ALL;
426
/* This sucks - as soon, as we have inheritable renderprops, do something with that opacity */
428
435
static unsigned int
429
nr_arena_glyphs_group_render(NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
436
nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int /*flags*/)
431
438
NRArenaItem *child;
437
444
guint ret = item->state;
446
if (item->arena->rendermode == RENDERMODE_OUTLINE) {
451
guint32 rgba = item->arena->outlinecolor;
452
// FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat
453
// by setting color channels in the "wrong" order
454
cairo_set_source_rgba(ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba));
455
cairo_set_tolerance(ct, 1.25); // low quality, but good enough for outline mode
457
for (child = group->children; child != NULL; child = child->next) {
458
NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
460
NArtBpath *bpath = (NArtBpath *) g->font->ArtBPath(g->glyph);
463
NR::Matrix g_t(g->g_transform);
464
feed_curve_to_cairo (ct, bpath, g_t * group->ctm, (pb->area).upgrade(), false, 0);
440
if (style->fill.type != SP_PAINT_TYPE_NONE || item->arena->rendermode == RENDERMODE_OUTLINE) {
475
if (!style->fill.isNone() || item->arena->rendermode == RENDERMODE_OUTLINE) {
442
477
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;
479
// if memory allocation failed, abort
480
if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
481
nr_pixblock_release (&m);
482
return (item->state);
485
m.visible_area = pb->visible_area;
445
487
/* Render children fill mask */
446
488
for (child = group->children; child != NULL; child = child->next) {
454
496
/* Composite into buffer */
455
if (style->fill.type == SP_PAINT_TYPE_COLOR || item->arena->rendermode == RENDERMODE_OUTLINE) {
497
if (style->fill.isPaintserver()) {
498
if (ggroup->fill_painter) {
499
nr_arena_render_paintserver_fill(pb, area, ggroup->fill_painter, SP_SCALE24_TO_FLOAT(style->fill_opacity.value), &m);
501
} else if (style->fill.isColor() || item->arena->rendermode == RENDERMODE_OUTLINE) {
457
503
if (item->arena->rendermode == RENDERMODE_OUTLINE) {
458
504
// In outline mode, render fill only, using outlinecolor
459
505
rgba = item->arena->outlinecolor;
460
506
} 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));
507
rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) *
508
SP_SCALE24_TO_FLOAT(style->opacity.value) );
465
rgba = sp_color_get_rgba32_falpha(&style->fill.value.color, SP_SCALE24_TO_FLOAT(style->fill_opacity.value));
510
rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) );
467
512
nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
468
513
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);
475
516
nr_pixblock_release(&m);
479
if (style->stroke.type != SP_PAINT_TYPE_NONE && !(item->arena->rendermode == RENDERMODE_OUTLINE)) {
520
if (!style->stroke.isNone() && !(item->arena->rendermode == RENDERMODE_OUTLINE)) {
482
523
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;
525
// if memory allocation failed, abort
526
if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) {
527
nr_pixblock_release (&m);
528
return (item->state);
531
m.visible_area = pb->visible_area;
484
532
/* Render children stroke mask */
485
533
for (child = group->children; child != NULL; child = child->next) {
486
534
ret = nr_arena_glyphs_stroke_mask(NR_ARENA_GLYPHS(child), area, &m);
492
540
/* 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));
500
rgba = sp_color_get_rgba32_falpha(&style->stroke.value.color,
501
SP_SCALE24_TO_FLOAT(style->stroke_opacity.value));
503
nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
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);
541
if (style->stroke.isPaintserver()) {
542
if (ggroup->stroke_painter) {
543
nr_arena_render_paintserver_fill(pb, area, ggroup->stroke_painter, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value), &m);
545
} else if (style->stroke.isColor()) {
546
if ( item->render_opacity ) {
547
rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) *
548
SP_SCALE24_TO_FLOAT(style->opacity.value) );
550
rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) );
552
nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
514
557
nr_pixblock_release(&m);