~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/display/nr-arena-glyphs.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#endif
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"
 
27
#include <cairo.h>
 
28
#include "inkscape-cairo.h"
24
29
 
25
30
#ifdef test_glyph_liv
26
31
#include "../display/canvas-bpath.h"
117
122
}
118
123
 
119
124
static guint
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*/)
121
126
{
122
127
    NRArenaGlyphs *glyphs;
123
128
    raster_font *rfont;
124
129
 
125
130
    glyphs = NR_ARENA_GLYPHS(item);
126
131
 
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;
129
136
 
130
137
    NRRect bbox;
131
138
    bbox.x0 = bbox.y0 = NR_HUGE;
133
140
 
134
141
    float const scale = NR_MATRIX_DF_EXPANSION(&gc->transform);
135
142
 
136
 
    if (glyphs->style->fill.type != SP_PAINT_TYPE_NONE) {
 
143
    if (!glyphs->style->fill.isNone()) {
137
144
        NRMatrix t;
138
145
        nr_matrix_multiply(&t, &glyphs->g_transform, &gc->transform);
139
146
        glyphs->x = t.c[4];
144
151
        if (glyphs->rfont) glyphs->rfont->Unref();
145
152
        glyphs->rfont = rfont;
146
153
 
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
148
155
            NRRect narea;
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;
154
161
        }
155
 
    }                               
 
162
    }
156
163
 
157
 
    if (glyphs->style->stroke.type != SP_PAINT_TYPE_NONE) {
 
164
    if (!glyphs->style->stroke.isNone()) {
158
165
        /* Build state data */
159
166
        NRMatrix t;
160
167
        nr_matrix_multiply(&t, &glyphs->g_transform, &gc->transform);
175
182
            if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_BEVEL ) nstyl.stroke_join=join_straight;
176
183
            nstyl.stroke_miter_limit = glyphs->style->stroke_miterlimit.value;
177
184
            nstyl.nbDash=0;
 
185
            nstyl.dash_offset=0;
178
186
            nstyl.dashes=NULL;
179
187
            if ( glyphs->style->stroke_dash.n_dash > 0 ) {
180
188
                nstyl.nbDash=glyphs->style->stroke_dash.n_dash;
210
218
}
211
219
 
212
220
static guint
213
 
nr_arena_glyphs_clip(NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
 
221
nr_arena_glyphs_clip(NRArenaItem *item, NRRectL */*area*/, NRPixBlock */*pb*/)
214
222
{
215
223
    NRArenaGlyphs *glyphs;
216
224
 
224
232
}
225
233
 
226
234
static NRArenaItem *
227
 
nr_arena_glyphs_pick(NRArenaItem *item, NR::Point p, gdouble delta, unsigned int sticky)
 
235
nr_arena_glyphs_pick(NRArenaItem *item, NR::Point p, gdouble /*delta*/, unsigned int /*sticky*/)
228
236
{
229
237
    NRArenaGlyphs *glyphs;
230
238
 
232
240
 
233
241
    if (!glyphs->font ) return NULL;
234
242
    if (!glyphs->style) return NULL;
235
 
        
 
243
 
236
244
    double const x = p[NR::X];
237
245
    double const y = p[NR::Y];
238
246
    /* With text we take a simple approach: pick if the point is in a characher bbox */
242
250
}
243
251
 
244
252
void
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)
246
254
{
247
255
    nr_return_if_fail(glyphs != NULL);
248
256
    nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
249
257
 
250
258
    nr_arena_item_request_render(NR_ARENA_ITEM(glyphs));
251
 
  
 
259
 
252
260
    if (transform) {
253
261
        glyphs->g_transform = *transform;
254
262
    } else {
255
263
        nr_matrix_set_identity(&glyphs->g_transform);
256
264
    }
257
 
                
 
265
 
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);
309
317
 
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);
314
322
 
399
407
    }
400
408
 
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;
407
415
    }
408
416
 
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;
414
422
    }
415
423
 
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;
418
426
    }
419
427
 
423
431
    return NR_ARENA_ITEM_STATE_ALL;
424
432
}
425
433
 
426
 
/* This sucks - as soon, as we have inheritable renderprops, do something with that opacity */
427
434
 
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*/)
430
437
{
431
438
    NRArenaItem *child;
432
439
 
436
443
 
437
444
    guint ret = item->state;
438
445
 
 
446
    if (item->arena->rendermode == RENDERMODE_OUTLINE) {
 
447
 
 
448
        if (!ct)
 
449
            return item->state;
 
450
 
 
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
 
456
 
 
457
        for (child = group->children; child != NULL; child = child->next) {
 
458
            NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
 
459
 
 
460
            NArtBpath *bpath = (NArtBpath *) g->font->ArtBPath(g->glyph);
 
461
 
 
462
            cairo_new_path(ct);
 
463
            NR::Matrix g_t(g->g_transform);
 
464
            feed_curve_to_cairo (ct, bpath, g_t * group->ctm, (pb->area).upgrade(), false, 0);
 
465
            cairo_fill(ct);
 
466
            pb->empty = FALSE;
 
467
        }
 
468
 
 
469
        return ret;
 
470
    }
 
471
 
 
472
 
 
473
 
439
474
    /* Fill */
440
 
    if (style->fill.type != SP_PAINT_TYPE_NONE || item->arena->rendermode == RENDERMODE_OUTLINE) {
 
475
    if (!style->fill.isNone() || item->arena->rendermode == RENDERMODE_OUTLINE) {
441
476
        NRPixBlock m;
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; 
 
478
 
 
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);
 
483
        }
 
484
 
 
485
        m.visible_area = pb->visible_area;
444
486
 
445
487
        /* Render children fill mask */
446
488
        for (child = group->children; child != NULL; child = child->next) {
452
494
        }
453
495
 
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);
 
500
            }
 
501
        } else if (style->fill.isColor() || item->arena->rendermode == RENDERMODE_OUTLINE) {
456
502
            guint32 rgba;
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) );
464
509
            } else {
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) );
466
511
            }
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);
472
 
            }
473
514
        }
474
515
 
475
516
        nr_pixblock_release(&m);
476
517
    }
477
518
 
478
519
    /* Stroke */
479
 
    if (style->stroke.type != SP_PAINT_TYPE_NONE && !(item->arena->rendermode == RENDERMODE_OUTLINE)) {
 
520
    if (!style->stroke.isNone() && !(item->arena->rendermode == RENDERMODE_OUTLINE)) {
480
521
        NRPixBlock m;
481
522
        guint32 rgba;
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; 
 
524
 
 
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);
 
529
        }
 
530
 
 
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);
490
538
            }
491
539
        }
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));
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;
 
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);
 
544
            }
 
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) );
 
549
            } else {
 
550
                rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) );
 
551
            }
 
552
            nr_blit_pixblock_mask_rgba32(pb, &m, rgba);
 
553
            pb->empty = FALSE;
 
554
        } else {
 
555
            // nothing
513
556
        }
514
557
        nr_pixblock_release(&m);
515
558
    }