diff options
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/Makefile_insert | 110 | ||||
| -rw-r--r-- | src/display/nr-arena-glyphs.cpp | 357 | ||||
| -rw-r--r-- | src/display/nr-arena-glyphs.h | 28 | ||||
| -rw-r--r-- | src/display/nr-arena-item.cpp | 4 | ||||
| -rw-r--r-- | src/display/nr-arena-shape.cpp | 237 | ||||
| -rw-r--r-- | src/display/nr-arena-shape.h | 110 | ||||
| -rw-r--r-- | src/display/nr-style.cpp | 218 | ||||
| -rw-r--r-- | src/display/nr-style.h | 82 |
8 files changed, 466 insertions, 680 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 7660d2c70..c6cdcbb6d 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -4,37 +4,22 @@ display/canvas-arena.$(OBJEXT): helper/sp-marshal.h display/sp-canvas.$(OBJEXT): helper/sp-marshal.h ink_common_sources += \ - display/nr-3dutils.h \ - display/nr-3dutils.cpp \ - display/nr-arena-forward.h \ - display/nr-arena.cpp \ - display/nr-arena.h \ - display/nr-arena-item.cpp \ - display/nr-arena-item.h \ - display/nr-arena-group.cpp \ - display/nr-arena-group.h \ - display/nr-arena-image.cpp \ - display/nr-arena-image.h \ - display/nr-arena-shape.cpp \ - display/nr-arena-shape.h \ - display/nr-arena-glyphs.cpp \ - display/nr-arena-glyphs.h \ + display/cairo-utils.cpp \ + display/cairo-utils.h \ display/canvas-arena.cpp \ display/canvas-arena.h \ + display/canvas-axonomgrid.cpp \ + display/canvas-axonomgrid.h \ display/canvas-bpath.cpp \ display/canvas-bpath.h \ display/canvas-grid.cpp \ display/canvas-grid.h \ - display/canvas-axonomgrid.cpp \ - display/canvas-axonomgrid.h \ display/canvas-temporary-item.cpp \ display/canvas-temporary-item.h \ display/canvas-temporary-item-list.cpp \ display/canvas-temporary-item-list.h \ - display/canvas-text.h \ display/canvas-text.cpp \ - display/cairo-utils.h \ - display/cairo-utils.cpp \ + display/canvas-text.h \ display/curve.cpp \ display/curve.h \ display/display-forward.h \ @@ -42,41 +27,34 @@ ink_common_sources += \ display/gnome-canvas-acetate.h \ display/guideline.cpp \ display/guideline.h \ - display/nr-plain-stuff-gdk.cpp \ - display/nr-plain-stuff-gdk.h \ - display/nr-plain-stuff.cpp \ - display/nr-plain-stuff.h \ - display/nr-svgfonts.cpp \ - display/nr-svgfonts.h \ - display/rendermode.h \ - display/snap-indicator.cpp \ - display/snap-indicator.h \ - display/sodipodi-ctrl.cpp \ - display/sodipodi-ctrl.h \ - display/sodipodi-ctrlrect.cpp \ - display/sodipodi-ctrlrect.h \ - display/sp-canvas-util.cpp \ - display/sp-canvas-util.h \ - display/sp-canvas.cpp \ - display/sp-canvas.h \ - display/sp-ctrlline.cpp \ - display/sp-ctrlline.h \ - display/sp-ctrlpoint.cpp \ - display/sp-ctrlpoint.h \ - display/sp-ctrlquadr.cpp \ - display/sp-ctrlquadr.h \ - display/nr-filter.cpp \ - display/nr-filter.h \ + display/inkscape-cairo.cpp \ + display/inkscape-cairo.h \ + display/nr-3dutils.cpp \ + display/nr-3dutils.h \ + display/nr-arena.cpp \ + display/nr-arena-forward.h \ + display/nr-arena-glyphs.cpp \ + display/nr-arena-glyphs.h \ + display/nr-arena-group.cpp \ + display/nr-arena-group.h \ + display/nr-arena.h \ + display/nr-arena-image.cpp \ + display/nr-arena-image.h \ + display/nr-arena-item.cpp \ + display/nr-arena-item.h \ + display/nr-arena-shape.cpp \ + display/nr-arena-shape.h \ display/nr-filter-blend.cpp \ display/nr-filter-blend.h \ display/nr-filter-colormatrix.cpp \ display/nr-filter-colormatrix.h \ display/nr-filter-component-transfer.cpp \ display/nr-filter-component-transfer.h \ - display/nr-filter-composite.h \ display/nr-filter-composite.cpp \ + display/nr-filter-composite.h \ display/nr-filter-convolve-matrix.cpp \ display/nr-filter-convolve-matrix.h \ + display/nr-filter.cpp \ display/nr-filter-diffuselighting.cpp \ display/nr-filter-diffuselighting.h \ display/nr-filter-displacement-map.cpp \ @@ -87,6 +65,7 @@ ink_common_sources += \ display/nr-filter-gaussian.h \ display/nr-filter-getalpha.cpp \ display/nr-filter-getalpha.h \ + display/nr-filter.h \ display/nr-filter-image.cpp \ display/nr-filter-image.h \ display/nr-filter-merge.cpp \ @@ -95,6 +74,7 @@ ink_common_sources += \ display/nr-filter-morphology.h \ display/nr-filter-offset.cpp \ display/nr-filter-offset.h \ + display/nr-filter-pixops.h \ display/nr-filter-primitive.cpp \ display/nr-filter-primitive.h \ display/nr-filter-slot.cpp \ @@ -105,21 +85,43 @@ ink_common_sources += \ display/nr-filter-tile.h \ display/nr-filter-turbulence.cpp \ display/nr-filter-turbulence.h \ - display/nr-filter-pixops.h \ display/nr-filter-types.h \ - display/nr-filter-units.h \ display/nr-filter-units.cpp \ - display/nr-filter-utils.h \ + display/nr-filter-units.h \ display/nr-filter-utils.cpp \ + display/nr-filter-utils.h \ + display/nr-light.cpp \ + display/nr-light.h \ + display/nr-light-types.h \ + display/nr-plain-stuff.cpp \ + display/nr-plain-stuff-gdk.cpp \ + display/nr-plain-stuff-gdk.h \ + display/nr-plain-stuff.h \ + display/nr-style.cpp \ + display/nr-style.h \ + display/nr-svgfonts.cpp \ + display/nr-svgfonts.h \ display/pixblock-scaler.cpp \ display/pixblock-scaler.h \ display/pixblock-transform.cpp \ display/pixblock-transform.h \ - display/inkscape-cairo.cpp \ - display/inkscape-cairo.h \ - display/nr-light.h \ - display/nr-light.cpp \ - display/nr-light-types.h + display/rendermode.h \ + display/snap-indicator.cpp \ + display/snap-indicator.h \ + display/sodipodi-ctrl.cpp \ + display/sodipodi-ctrl.h \ + display/sodipodi-ctrlrect.cpp \ + display/sodipodi-ctrlrect.h \ + display/sp-canvas.cpp \ + display/sp-canvas.h \ + display/sp-canvas-util.cpp \ + display/sp-canvas-util.h \ + display/sp-ctrlline.cpp \ + display/sp-ctrlline.h \ + display/sp-ctrlpoint.cpp \ + display/sp-ctrlpoint.h \ + display/sp-ctrlquadr.cpp \ + display/sp-ctrlquadr.h # ###################### # ### CxxTest stuff #### diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index d229157ed..8e1b659c7 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -24,6 +24,7 @@ #include "nr-arena-glyphs.h" #include <cairo.h> #include "inkscape-cairo.h" +#include "helper/geom.h" #ifdef test_glyph_liv #include "../display/canvas-bpath.h" @@ -86,13 +87,9 @@ nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass) static void nr_arena_glyphs_init(NRArenaGlyphs *glyphs) { - glyphs->style = NULL; glyphs->g_transform.setIdentity(); glyphs->font = NULL; glyphs->glyph = 0; - - glyphs->rfont = NULL; - glyphs->sfont = NULL; glyphs->x = glyphs->y = 0.0; } @@ -101,120 +98,58 @@ nr_arena_glyphs_finalize(NRObject *object) { NRArenaGlyphs *glyphs = static_cast<NRArenaGlyphs *>(object); - if (glyphs->rfont) { - glyphs->rfont->Unref(); - glyphs->rfont=NULL; - } - if (glyphs->sfont) { - glyphs->sfont->Unref(); - glyphs->sfont=NULL; - } - if (glyphs->font) { glyphs->font->Unref(); glyphs->font=NULL; } - if (glyphs->style) { - sp_style_unref(glyphs->style); - glyphs->style = NULL; - } - ((NRObjectClass *) glyphs_parent_class)->finalize(object); } static guint nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*state*/, guint /*reset*/) { - NRArenaGlyphs *glyphs; - raster_font *rfont; + NRArenaGlyphs *glyphs = NR_ARENA_GLYPHS(item); + NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item->parent); - glyphs = NR_ARENA_GLYPHS(item); - - if (!glyphs->font || !glyphs->style) + if (!glyphs->font || !ggroup->style) return NR_ARENA_ITEM_STATE_ALL; - if ((glyphs->style->fill.isNone()) && (glyphs->style->stroke.isNone())) + if (ggroup->nrstyle.fill.type == NRStyle::PAINT_NONE && ggroup->nrstyle.stroke.type == NRStyle::PAINT_NONE) return NR_ARENA_ITEM_STATE_ALL; - NRRect bbox; - bbox.x0 = bbox.y0 = NR_HUGE; - bbox.x1 = bbox.y1 = -NR_HUGE; - - float const scale = gc->transform.descrim(); - - if (!glyphs->style->fill.isNone()) { - Geom::Matrix t; - t = glyphs->g_transform * gc->transform; - glyphs->x = t[4]; - glyphs->y = t[5]; - t[4]=0; - t[5]=0; - rfont = glyphs->font->RasterFont(t, 0); - if (glyphs->rfont) glyphs->rfont->Unref(); - glyphs->rfont = rfont; - - if (glyphs->style->stroke.isNone() || fabs(glyphs->style->stroke_width.computed * scale) <= 0.01) { // Optimization: do fill bbox only if there's no stroke - NRRect narea; - if ( glyphs->rfont ) glyphs->rfont->BBox(glyphs->glyph, &narea); - bbox.x0 = narea.x0 + glyphs->x; - bbox.y0 = narea.y0 + glyphs->y; - bbox.x1 = narea.x1 + glyphs->x; - bbox.y1 = narea.y1 + glyphs->y; + Geom::OptRect b; + Geom::Matrix t = glyphs->g_transform * gc->transform; + glyphs->x = t[4]; + glyphs->y = t[5]; + + b = bounds_exact_transformed(*glyphs->font->PathVector(glyphs->glyph), t); + if (b && ggroup->nrstyle.stroke.type != NRStyle::PAINT_NONE) { + float width, scale; + scale = gc->transform.descrim(); + width = MAX(0.125, ggroup->nrstyle.stroke_width * scale); + if ( fabs(ggroup->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true + b->expandBy(width); } - } - - if (!glyphs->style->stroke.isNone()) { - /* Build state data */ - Geom::Matrix t; - t = glyphs->g_transform * gc->transform; - glyphs->x = t[4]; - glyphs->y = t[5]; - t[4]=0; - t[5]=0; - - if ( fabs(glyphs->style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord - font_style nstyl; - nstyl.transform = t; - nstyl.stroke_width=MAX(0.125, glyphs->style->stroke_width.computed * scale); - if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_BUTT ) nstyl.stroke_cap=butt_straight; - if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_ROUND ) nstyl.stroke_cap=butt_round; - if ( glyphs->style->stroke_linecap.computed == SP_STROKE_LINECAP_SQUARE ) nstyl.stroke_cap=butt_square; - if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_MITER ) nstyl.stroke_join=join_pointy; - if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_ROUND ) nstyl.stroke_join=join_round; - if ( glyphs->style->stroke_linejoin.computed == SP_STROKE_LINEJOIN_BEVEL ) nstyl.stroke_join=join_straight; - nstyl.stroke_miter_limit = glyphs->style->stroke_miterlimit.value; - nstyl.nbDash=0; - nstyl.dash_offset = 0; - nstyl.dashes=NULL; - if ( glyphs->style->stroke_dash.n_dash > 0 ) { - nstyl.dash_offset = glyphs->style->stroke_dash.offset * scale; - nstyl.nbDash=glyphs->style->stroke_dash.n_dash; - nstyl.dashes=(double*)malloc(nstyl.nbDash*sizeof(double)); - for (int i = 0; i < nstyl.nbDash; i++) nstyl.dashes[i]= glyphs->style->stroke_dash.dash[i] * scale; - } - rfont = glyphs->font->RasterFont( nstyl); - if ( nstyl.dashes ) free(nstyl.dashes); - if (glyphs->sfont) glyphs->sfont->Unref(); - glyphs->sfont = rfont; - - NRRect narea; - if ( glyphs->sfont ) glyphs->sfont->BBox(glyphs->glyph, &narea); - narea.x0-=nstyl.stroke_width; - narea.y0-=nstyl.stroke_width; - narea.x1+=nstyl.stroke_width; - narea.y1+=nstyl.stroke_width; - bbox.x0 = narea.x0 + glyphs->x; - bbox.y0 = narea.y0 + glyphs->y; - bbox.x1 = narea.x1 + glyphs->x; - bbox.y1 = narea.y1 + glyphs->y; + // those pesky miters, now + float miterMax = width * ggroup->nrstyle.miter_limit; + if ( miterMax > 0.01 ) { + // grunt mode. we should compute the various miters instead + // (one for each point on the curve) + b->expandBy(miterMax); } } - if (nr_rect_d_test_empty(bbox)) return NR_ARENA_ITEM_STATE_ALL; - item->bbox.x0 = static_cast<NR::ICoord>(floor(bbox.x0)); - item->bbox.y0 = static_cast<NR::ICoord>(floor(bbox.y0)); - item->bbox.x1 = static_cast<NR::ICoord>(ceil (bbox.x1)); - item->bbox.y1 = static_cast<NR::ICoord>(ceil (bbox.y1)); + if (b) { + item->bbox.x0 = static_cast<NR::ICoord>(floor(b->left())); + item->bbox.y0 = static_cast<NR::ICoord>(floor(b->top())); + item->bbox.x1 = static_cast<NR::ICoord>(ceil (b->right())); + item->bbox.y1 = static_cast<NR::ICoord>(ceil (b->bottom())); + } else { + item->bbox.x0 = 0; + item->bbox.y0 = 0; + item->bbox.x1 = -1; + item->bbox.y1 = -1; + } return NR_ARENA_ITEM_STATE_ALL; } @@ -226,7 +161,7 @@ nr_arena_glyphs_clip(cairo_t *ct, NRArenaItem *item, NRRectL */*area*/) glyphs = NR_ARENA_GLYPHS(item); - if (!glyphs->font ) return item->state; + if (!glyphs->font) return item->state; /* TODO : render to greyscale pixblock provided for clipping */ @@ -241,7 +176,6 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned i glyphs = NR_ARENA_GLYPHS(item); if (!glyphs->font ) return NULL; - if (!glyphs->style) return NULL; double const x = p[Geom::X]; double const y = p[Geom::Y]; @@ -273,46 +207,6 @@ nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE); } -void -nr_arena_glyphs_set_style(NRArenaGlyphs *glyphs, SPStyle *style) -{ - nr_return_if_fail(glyphs != NULL); - nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs)); - - if (style) sp_style_ref(style); - if (glyphs->style) sp_style_unref(glyphs->style); - glyphs->style = style; - - nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE); -} - -static guint -nr_arena_glyphs_fill_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m) -{ - /* fixme: area == m->area, so merge these */ - - NRArenaItem *item = NR_ARENA_ITEM(glyphs); - - if (glyphs->rfont && nr_rect_l_test_intersect_ptr(area, &item->bbox)) { - raster_glyph *g = glyphs->rfont->GetGlyph(glyphs->glyph); - if ( g ) g->Blit(Geom::Point(glyphs->x, glyphs->y), *m); - } - - return item->state; -} - -static guint -nr_arena_glyphs_stroke_mask(NRArenaGlyphs *glyphs, NRRectL *area, NRPixBlock *m) -{ - NRArenaItem *item = NR_ARENA_ITEM(glyphs); - if (glyphs->sfont && nr_rect_l_test_intersect_ptr(area, &item->bbox)) { - raster_glyph *g=glyphs->sfont->GetGlyph(glyphs->glyph); - if ( g ) g->Blit(Geom::Point(glyphs->x, glyphs->y),*m); - } - - return item->state; -} - static void nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass); static void nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group); static void nr_arena_glyphs_group_finalize(NRObject *object); @@ -364,10 +258,7 @@ nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group) { group->style = NULL; group->paintbox.x0 = group->paintbox.y0 = 0.0F; - group->paintbox.x1 = group->paintbox.y1 = 1.0F; - - group->fill_painter = NULL; - group->stroke_painter = NULL; + group->paintbox.x1 = group->paintbox.y1 = -1.0F; } static void @@ -375,16 +266,6 @@ nr_arena_glyphs_group_finalize(NRObject *object) { NRArenaGlyphsGroup *group=static_cast<NRArenaGlyphsGroup *>(object); - if (group->fill_painter) { - sp_painter_free(group->fill_painter); - group->fill_painter = NULL; - } - - if (group->stroke_painter) { - sp_painter_free(group->stroke_painter); - group->stroke_painter = NULL; - } - if (group->style) { sp_style_unref(group->style); group->style = NULL; @@ -398,34 +279,7 @@ nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint s { NRArenaGlyphsGroup *group = NR_ARENA_GLYPHS_GROUP(item); - if (group->fill_painter) { - sp_painter_free(group->fill_painter); - group->fill_painter = NULL; - } - - if (group->stroke_painter) { - sp_painter_free(group->stroke_painter); - group->stroke_painter = NULL; - } - - item->render_opacity = TRUE; - if (group->style->fill.isPaintserver()) { - group->fill_painter = sp_paint_server_painter_new(SP_STYLE_FILL_SERVER(group->style), - gc->transform, gc->parent->transform, - &group->paintbox); - item->render_opacity = FALSE; - } - - if (group->style->stroke.isPaintserver()) { - group->stroke_painter = sp_paint_server_painter_new(SP_STYLE_STROKE_SERVER(group->style), - gc->transform, gc->parent->transform, - &group->paintbox); - item->render_opacity = FALSE; - } - - if ( item->render_opacity == TRUE && !group->style->stroke.isNone() && !group->style->fill.isNone() ) { - item->render_opacity=FALSE; - } + group->nrstyle.update(); if (((NRArenaItemClass *) group_parent_class)->update) return ((NRArenaItemClass *) group_parent_class)->update(item, area, gc, state, reset); @@ -441,16 +295,11 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi NRArenaGroup *group = NR_ARENA_GROUP(item); NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item); - SPStyle const *style = ggroup->style; - guint ret = item->state; - bool print_colors_preview = (item->arena->rendermode == Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW); + if (!ct) return item->state; if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) { - if (!ct) - return item->state; - guint32 rgba = item->arena->outlinecolor; // FIXME: we use RGBA buffers but cairo writes BGRA (on i386), so we must cheat // by setting color channels in the "wrong" order @@ -469,112 +318,59 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi pb->empty = FALSE; } - return ret; + return item->state; } + // NOTE: this is very similar to nr-arena-shape.cpp; the only difference is path feeding + bool needs_opacity = ((1.0 - ggroup->nrstyle.opacity) >= 0.01); + bool has_stroke, has_fill; + cairo_save(ct); + cairo_translate(ct, -area->x0, -area->y0); + ink_cairo_transform(ct, ggroup->ctm); - /* Fill */ - if (!style->fill.isNone() || item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) { - NRPixBlock m; - nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); + has_fill = ggroup->nrstyle.prepareFill(ct, &ggroup->paintbox); + has_stroke = ggroup->nrstyle.prepareStroke(ct, &ggroup->paintbox); - // if memory allocation failed, abort - if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) { - nr_pixblock_release (&m); - return (item->state); + if (has_fill || has_stroke) { + if (needs_opacity) { + cairo_push_group(ct); } - m.visible_area = pb->visible_area; + for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) { + NRArenaGlyphs *g = NR_ARENA_GLYPHS(child); + Geom::PathVector const &pathv = *g->font->PathVector(g->glyph); - /* Render children fill mask */ - for (child = group->children; child != NULL; child = child->next) { - ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, &m); - if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) { - nr_pixblock_release(&m); - return ret; - } + cairo_save(ct); + ink_cairo_transform(ct, g->g_transform); + feed_pathvector_to_cairo(ct, pathv); + cairo_restore(ct); } - /* Composite into buffer */ - if (style->fill.isPaintserver()) { - if (ggroup->fill_painter) { - nr_arena_render_paintserver_fill(pb, area, ggroup->fill_painter, SP_SCALE24_TO_FLOAT(style->fill_opacity.value), &m); - } - } else if (style->fill.isColor() || item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) { - guint32 rgba; - if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) { - // In outline mode, render fill only, using outlinecolor - rgba = item->arena->outlinecolor; - } else if ( item->render_opacity ) { - rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) * - SP_SCALE24_TO_FLOAT(style->opacity.value) ); - } else { - rgba = style->fill.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->fill_opacity.value) ); - } - - if (print_colors_preview) - nr_arena_separate_color_plates(&rgba); - - nr_blit_pixblock_mask_rgba32(pb, &m, rgba); - pb->empty = FALSE; + if (has_fill) { + ggroup->nrstyle.applyFill(ct); + cairo_fill_preserve(ct); } - - nr_pixblock_release(&m); - } - - /* Stroke */ - if (!style->stroke.isNone() && !(item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE)) { - NRPixBlock m; - guint32 rgba; - nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE); - - // if memory allocation failed, abort - if (m.size != NR_PIXBLOCK_SIZE_TINY && m.data.px == NULL) { - nr_pixblock_release (&m); - return (item->state); + if (has_stroke) { + ggroup->nrstyle.applyStroke(ct); + cairo_stroke_preserve(ct); } + cairo_new_path(ct); // clear path - m.visible_area = pb->visible_area; - /* Render children stroke mask */ - for (child = group->children; child != NULL; child = child->next) { - ret = nr_arena_glyphs_stroke_mask(NR_ARENA_GLYPHS(child), area, &m); - if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) { - nr_pixblock_release(&m); - return ret; - } - } - /* Composite into buffer */ - if (style->stroke.isPaintserver()) { - if (ggroup->stroke_painter) { - nr_arena_render_paintserver_fill(pb, area, ggroup->stroke_painter, SP_SCALE24_TO_FLOAT(style->stroke_opacity.value), &m); - } - } else if (style->stroke.isColor()) { - if ( item->render_opacity ) { - rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) * - SP_SCALE24_TO_FLOAT(style->opacity.value) ); - } else { - rgba = style->stroke.value.color.toRGBA32( SP_SCALE24_TO_FLOAT(style->stroke_opacity.value) ); - } - - if (print_colors_preview) - nr_arena_separate_color_plates(&rgba); - - nr_blit_pixblock_mask_rgba32(pb, &m, rgba); - pb->empty = FALSE; - } else { - // nothing + if (needs_opacity) { + cairo_pop_group_to_source(ct); + cairo_paint_with_alpha(ct, ggroup->nrstyle.opacity); } - nr_pixblock_release(&m); - } + } // has fill or stroke pattern + cairo_restore(ct); - return ret; + return item->state; } static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL *area) { - NRArenaGroup *group = NR_ARENA_GROUP(item); + //NRArenaGroup *group = NR_ARENA_GROUP(item); guint ret = item->state; @@ -630,7 +426,6 @@ nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, nr_arena_item_append_child(NR_ARENA_ITEM(group), new_arena); nr_arena_item_unref(new_arena); nr_arena_glyphs_set_path(NR_ARENA_GLYPHS(new_arena), NULL, FALSE, font, glyph, &transform); - nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(new_arena), sg->style); } } @@ -640,16 +435,11 @@ nr_arena_glyphs_group_set_style(NRArenaGlyphsGroup *sg, SPStyle *style) nr_return_if_fail(sg != NULL); nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(sg)); - NRArenaGroup *group = NR_ARENA_GROUP(sg); - if (style) sp_style_ref(style); if (sg->style) sp_style_unref(sg->style); sg->style = style; - for (NRArenaItem *child = group->children; child != NULL; child = child->next) { - nr_return_if_fail(NR_IS_ARENA_GLYPHS(child)); - nr_arena_glyphs_set_style(NR_ARENA_GLYPHS(child), sg->style); - } + sg->nrstyle.set(style); nr_arena_item_request_update(NR_ARENA_ITEM(sg), NR_ARENA_ITEM_STATE_ALL, FALSE); } @@ -667,9 +457,8 @@ nr_arena_glyphs_group_set_paintbox(NRArenaGlyphsGroup *gg, NRRect const *pbox) gg->paintbox.x1 = pbox->x1; gg->paintbox.y1 = pbox->y1; } else { - /* fixme: We kill warning, although not sure what to do here (Lauris) */ gg->paintbox.x0 = gg->paintbox.y0 = 0.0F; - gg->paintbox.x1 = gg->paintbox.y1 = 256.0F; + gg->paintbox.x1 = gg->paintbox.y1 = -1.0F; } nr_arena_item_request_update(NR_ARENA_ITEM(gg), NR_ARENA_ITEM_STATE_ALL, FALSE); diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h index 5bf94f3fc..f0580282f 100644 --- a/src/display/nr-arena-glyphs.h +++ b/src/display/nr-arena-glyphs.h @@ -17,12 +17,12 @@ #define NR_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS, NRArenaGlyphs)) #define NR_IS_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS)) -#include <libnrtype/nrtype-forward.h> - -#include <display/display-forward.h> -#include <forward.h> -#include <sp-paint-server.h> -#include <display/nr-arena-item.h> +#include "libnrtype/nrtype-forward.h" +#include "display/display-forward.h" +#include "forward.h" +#include "sp-paint-server.h" +#include "display/nr-arena-item.h" +#include "display/nr-style.h" #define test_glyph_liv @@ -32,22 +32,11 @@ NRType nr_arena_glyphs_get_type (void); struct NRArenaGlyphs : public NRArenaItem { /* Glyphs data */ - SPStyle *style; Geom::Matrix g_transform; font_instance *font; gint glyph; - - raster_font *rfont; - raster_font *sfont; float x, y; -// Geom::Matrix cached_tr; -// Shape *cached_shp; -// bool cached_shp_dirty; -// bool cached_style_dirty; - -// Shape *stroke_shp; - static NRArenaGlyphs *create(NRArena *arena) { NRArenaGlyphs *obj=reinterpret_cast<NRArenaGlyphs *>(nr_object_new(NR_TYPE_ARENA_GLYPHS)); obj->init(arena); @@ -79,11 +68,8 @@ typedef struct NRArenaGlyphsGroupClass NRArenaGlyphsGroupClass; NRType nr_arena_glyphs_group_get_type (void); struct NRArenaGlyphsGroup : public NRArenaGroup { - //SPStyle *style; NRRect paintbox; - /* State data */ - SPPainter *fill_painter; - SPPainter *stroke_painter; + NRStyle nrstyle; static NRArenaGlyphsGroup *create(NRArena *arena) { NRArenaGlyphsGroup *obj=reinterpret_cast<NRArenaGlyphsGroup *>(nr_object_new(NR_TYPE_ARENA_GLYPHS_GROUP)); diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index 8f11db191..ca9528f16 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -565,8 +565,8 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area unsigned int state; Cairo::Context cct(ct); Cairo::RefPtr<Cairo::Pattern> mask; - CairoSave clipsave(ct); - CairoGroup maskgroup(ct); + CairoSave clipsave(ct); // RAII for save / restore + CairoGroup maskgroup(ct); // RAII for push_group / pop_group CairoGroup drawgroup(ct); if (item->clip) { diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 548a17127..f0a621bf0 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -23,6 +23,7 @@ #include <libnr/nr-convert2geom.h> #include <2geom/pathvector.h> #include <2geom/curves.h> +#include <livarot/Shape.h> #include <livarot/Path.h> #include <livarot/float-line.h> #include <livarot/int-line.h> @@ -110,20 +111,14 @@ nr_arena_shape_init(NRArenaShape *shape) shape->style = NULL; shape->paintbox.x0 = shape->paintbox.y0 = 0.0F; shape->paintbox.x1 = shape->paintbox.y1 = 256.0F; - shape->ctm.setIdentity(); - shape->delayed_shp = false; - - shape->fill_pattern = NULL; - shape->stroke_pattern = NULL; shape->path = NULL; shape->approx_bbox.x0 = shape->approx_bbox.y0 = 0; shape->approx_bbox.x1 = shape->approx_bbox.y1 = 0; shape->markers = NULL; - shape->last_pick = NULL; shape->repick_after = 0; } @@ -133,10 +128,7 @@ nr_arena_shape_finalize(NRObject *object) { NRArenaShape *shape = (NRArenaShape *) object; - if (shape->fill_pattern) cairo_pattern_destroy(shape->fill_pattern); - if (shape->stroke_pattern) cairo_pattern_destroy(shape->stroke_pattern); if (shape->path) cairo_path_destroy(shape->path); - if (shape->style) sp_style_unref(shape->style); if (shape->curve) shape->curve->unref(); @@ -267,14 +259,7 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE); // clear Cairo data to force update - if (shape->fill_pattern) { - cairo_pattern_destroy(shape->fill_pattern); - shape->fill_pattern = NULL; - } - if (shape->stroke_pattern) { - cairo_pattern_destroy(shape->stroke_pattern); - shape->stroke_pattern = NULL; - } + shape->nrstyle.update(); if (shape->path) { cairo_path_destroy(shape->path); shape->path = NULL; @@ -283,17 +268,18 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g if (shape->curve) { boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform); - if (boundingbox && (shape->_stroke.paint.type() != NRArenaShape::Paint::NONE || outline)) { + if (boundingbox && (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) { float width, scale; scale = gc->transform.descrim(); - width = MAX(0.125, shape->_stroke.width * scale); - if ( fabs(shape->_stroke.width * scale) > 0.01 ) { + width = MAX(0.125, shape->nrstyle.stroke_width * scale); + if ( fabs(shape->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true boundingbox->expandBy(width); } // those pesky miters, now - float miterMax=width*shape->_stroke.mitre_limit; + float miterMax = width * shape->nrstyle.miter_limit; if ( miterMax > 0.01 ) { - // grunt mode. we should compute the various miters instead (one for each point on the curve) + // grunt mode. we should compute the various miters instead + // (one for each point on the curve) boundingbox->expandBy(miterMax); } } @@ -316,8 +302,8 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g if (!shape->curve || !shape->style || shape->curve->is_empty() || - (( shape->_fill.paint.type() == NRArenaShape::Paint::NONE ) && - ( shape->_stroke.paint.type() == NRArenaShape::Paint::NONE && !outline) )) + (( shape->nrstyle.fill.type != NRStyle::PAINT_NONE ) && + ( shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) )) { //item->bbox = shape->approx_bbox; return NR_ARENA_ITEM_STATE_ALL; @@ -384,12 +370,8 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret; } else { - SPStyle const *style = shape->style; - - // set up context and feed path - float opacity = SP_SCALE24_TO_FLOAT(shape->style->opacity.value); - bool needs_opacity = ((1.0 - opacity) >= 1e-3); - + bool needs_opacity = ((1.0 - shape->nrstyle.opacity) >= 0.01); + bool has_stroke, has_fill; // we assume the context has no path cairo_save(ct); cairo_translate(ct, -area->x0, -area->y0); @@ -398,76 +380,33 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock // update fill and stroke paints. // this cannot be done during nr_arena_shape_update, because we need a Cairo context // to render svg:pattern - if (!shape->fill_pattern) { - switch (shape->_fill.paint.type()) { - case NRArenaShape::Paint::SERVER: { - SPPaintServer *ps = shape->_fill.paint.server(); - shape->fill_pattern = sp_paint_server_create_pattern(ps, ct, &shape->paintbox, shape->_fill.opacity); - } break; - case NRArenaShape::Paint::COLOR: { - SPColor const &c = shape->_fill.paint.color(); - shape->fill_pattern = cairo_pattern_create_rgba( - c.v.c[0], c.v.c[1], c.v.c[2], shape->_fill.opacity); - } break; - default: break; - } - } - - if (!shape->stroke_pattern) { - switch (shape->_stroke.paint.type()) { - case NRArenaShape::Paint::SERVER: { - SPPaintServer *ps = shape->_stroke.paint.server(); - shape->stroke_pattern = sp_paint_server_create_pattern(ps, ct, &shape->paintbox, shape->_stroke.opacity); - } break; - case NRArenaShape::Paint::COLOR: { - SPColor const &c = shape->_stroke.paint.color(); - shape->stroke_pattern = cairo_pattern_create_rgba( - c.v.c[0], c.v.c[1], c.v.c[2], shape->_stroke.opacity); - } break; - default: break; - } - } - - if (shape->fill_pattern || shape->stroke_pattern) { + has_fill = shape->nrstyle.prepareFill(ct, &shape->paintbox); + has_stroke = shape->nrstyle.prepareStroke(ct, &shape->paintbox); + if (has_fill || has_stroke) { if (needs_opacity) { cairo_push_group(ct); } // TODO: remove segments outside of bbox when no dashes present feed_pathvector_to_cairo(ct, shape->curve->get_pathvector()); - - if (shape->fill_pattern) { - cairo_set_fill_rule(ct, shape->_fill.rule); - cairo_set_source(ct, shape->fill_pattern); + if (has_fill) { + shape->nrstyle.applyFill(ct); cairo_fill_preserve(ct); } - - if (shape->stroke_pattern) { - cairo_set_line_width(ct, shape->_stroke.width); - cairo_set_line_cap(ct, shape->_stroke.cap); - cairo_set_line_join(ct, shape->_stroke.join); - cairo_set_miter_limit (ct, style->stroke_miterlimit.value); - - // dashes - if (style->stroke_dash.n_dash) { - cairo_set_dash (ct, style->stroke_dash.dash, style->stroke_dash.n_dash, - style->stroke_dash.offset); - } - cairo_set_source(ct, shape->stroke_pattern); + if (has_stroke) { + shape->nrstyle.applyStroke(ct); cairo_stroke_preserve(ct); } cairo_new_path(ct); // clear path if (needs_opacity) { cairo_pop_group_to_source(ct); - cairo_paint_with_alpha(ct, opacity); + cairo_paint_with_alpha(ct, shape->nrstyle.opacity); } } // has fill or stroke pattern - cairo_restore(ct); - - } // non-cairo non-outline branch + } /* Render markers into parent buffer */ for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) { @@ -522,17 +461,17 @@ nr_arena_shape_pick(NRArenaItem *item, Geom::Point p, double delta, unsigned int double width; if (outline) { width = 0.5; - } else if (shape->_stroke.paint.type() != NRArenaShape::Paint::NONE && shape->_stroke.opacity > 1e-3) { + } else if (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && shape->nrstyle.stroke.opacity > 1e-3) { float const scale = shape->ctm.descrim(); - width = MAX(0.125, shape->_stroke.width * scale) / 2; + width = MAX(0.125, shape->nrstyle.stroke_width * scale) / 2; } else { width = 0; } double dist = NR_HUGE; int wind = 0; - bool needfill = (shape->_fill.paint.type() != NRArenaShape::Paint::NONE - && shape->_fill.opacity > 1e-3 && !outline); + bool needfill = (shape->nrstyle.fill.type != NRStyle::PAINT_NONE + && shape->nrstyle.fill.opacity > 1e-3 && !outline); if (item->arena->canvasarena) { Geom::Rect viewbox = item->arena->canvasarena->item.canvas->getViewbox(); @@ -614,61 +553,6 @@ void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve,bool justTrans) nr_arena_item_request_update(NR_ARENA_ITEM(shape), NR_ARENA_ITEM_STATE_ALL, FALSE); } -void NRArenaShape::setFill(SPPaintServer *server) { - _fill.paint.set(server); - _invalidateCachedFill(); -} - -void NRArenaShape::setFill(SPColor const &color) { - _fill.paint.set(color); - _invalidateCachedFill(); -} - -void NRArenaShape::setFillOpacity(double opacity) { - _fill.opacity = opacity; - _invalidateCachedFill(); -} - -void NRArenaShape::setFillRule(cairo_fill_rule_t rule) { - _fill.rule = rule; - _invalidateCachedFill(); -} - -void NRArenaShape::setStroke(SPPaintServer *server) { - _stroke.paint.set(server); - _invalidateCachedStroke(); -} - -void NRArenaShape::setStroke(SPColor const &color) { - _stroke.paint.set(color); - _invalidateCachedStroke(); -} - -void NRArenaShape::setStrokeOpacity(double opacity) { - _stroke.opacity = opacity; - _invalidateCachedStroke(); -} - -void NRArenaShape::setStrokeWidth(double width) { - _stroke.width = width; - _invalidateCachedStroke(); -} - -void NRArenaShape::setMitreLimit(double limit) { - _stroke.mitre_limit = limit; - _invalidateCachedStroke(); -} - -void NRArenaShape::setLineCap(cairo_line_cap_t cap) { - _stroke.cap = cap; - _invalidateCachedStroke(); -} - -void NRArenaShape::setLineJoin(cairo_line_join_t join) { - _stroke.join = join; - _invalidateCachedStroke(); -} - /** nr_arena_shape_set_style * * Unrefs any existing style and ref's to the given one, then requests an update of the arena @@ -683,76 +567,7 @@ nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style) if (shape->style) sp_style_unref(shape->style); shape->style = style; - if ( style->fill.isPaintserver() ) { - shape->setFill(style->getFillPaintServer()); - } else if ( style->fill.isColor() ) { - shape->setFill(style->fill.value.color); - } else if ( style->fill.isNone() ) { - shape->setFill(NULL); - } else { - g_assert_not_reached(); - } - shape->setFillOpacity(SP_SCALE24_TO_FLOAT(style->fill_opacity.value)); - switch (style->fill_rule.computed) { - case SP_WIND_RULE_EVENODD: { - shape->setFillRule(CAIRO_FILL_RULE_EVEN_ODD); - break; - } - case SP_WIND_RULE_NONZERO: { - shape->setFillRule(CAIRO_FILL_RULE_WINDING); - break; - } - default: { - g_assert_not_reached(); - } - } - - if ( style->stroke.isPaintserver() ) { - shape->setStroke(style->getStrokePaintServer()); - } else if ( style->stroke.isColor() ) { - shape->setStroke(style->stroke.value.color); - } else if ( style->stroke.isNone() ) { - shape->setStroke(NULL); - } else { - g_assert_not_reached(); - } - shape->setStrokeWidth(style->stroke_width.computed); - shape->setStrokeOpacity(SP_SCALE24_TO_FLOAT(style->stroke_opacity.value)); - switch (style->stroke_linecap.computed) { - case SP_STROKE_LINECAP_ROUND: { - shape->setLineCap(CAIRO_LINE_CAP_ROUND); - break; - } - case SP_STROKE_LINECAP_SQUARE: { - shape->setLineCap(CAIRO_LINE_CAP_SQUARE); - break; - } - case SP_STROKE_LINECAP_BUTT: { - shape->setLineCap(CAIRO_LINE_CAP_BUTT); - break; - } - default: { - g_assert_not_reached(); - } - } - switch (style->stroke_linejoin.computed) { - case SP_STROKE_LINEJOIN_ROUND: { - shape->setLineJoin(CAIRO_LINE_JOIN_ROUND); - break; - } - case SP_STROKE_LINEJOIN_BEVEL: { - shape->setLineJoin(CAIRO_LINE_JOIN_BEVEL); - break; - } - case SP_STROKE_LINEJOIN_MITER: { - shape->setLineJoin(CAIRO_LINE_JOIN_MITER); - break; - } - default: { - g_assert_not_reached(); - } - } - shape->setMitreLimit(style->stroke_miterlimit.value); + shape->nrstyle.set(style); //if shape has a filter if (style->filter.set && style->getFilter()) { diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h index 97001c82d..66c8bc344 100644 --- a/src/display/nr-arena-shape.h +++ b/src/display/nr-arena-shape.h @@ -19,88 +19,21 @@ #include <cairo.h> #include "display/display-forward.h" -#include "display/canvas-bpath.h" #include "forward.h" -#include "sp-paint-server.h" #include "nr-arena-item.h" - -#include "../color.h" - -#include "../livarot/Shape.h" +#include "nr-style.h" NRType nr_arena_shape_get_type (void); struct NRArenaShape : public NRArenaItem { - class Paint { - public: - enum Type { - NONE, - COLOR, - SERVER - }; - - Paint() : _type(NONE), _color(0), _server(NULL) {} - Paint(Paint const &p) { _assign(p); } - virtual ~Paint() { clear(); } - - Type type() const { return _type; } - SPPaintServer *server() const { return _server; } - SPColor const &color() const { return _color; } - - Paint &operator=(Paint const &p) { - set(p); - return *this; - } - - void set(Paint const &p) { - clear(); - _assign(p); - } - void set(SPColor const &color) { - clear(); - _type = COLOR; - _color = color; - } - void set(SPPaintServer *server) { - clear(); - if (server) { - _type = SERVER; - _server = server; - sp_object_ref(_server, NULL); - } - } - void clear() { - if ( _type == SERVER ) { - sp_object_unref(_server, NULL); - _server = NULL; - } - _type = NONE; - } - - private: - Type _type; - SPColor _color; - SPPaintServer *_server; - - void _assign(Paint const &p) { - _type = p._type; - _server = p._server; - _color = p._color; - if (_server) { - sp_object_ref(_server, NULL); - } - } - }; - /* Shape data */ SPCurve *curve; SPStyle *style; + NRStyle nrstyle; NRRect paintbox; /* State data */ Geom::Matrix ctm; - cairo_pattern_t *fill_pattern; - cairo_pattern_t *stroke_pattern; cairo_path_t *path; // delayed_shp=true means the *_shp polygons are not computed yet @@ -123,46 +56,7 @@ struct NRArenaShape : public NRArenaItem { return obj; } - void setFill(SPPaintServer *server); - void setFill(SPColor const &color); - void setFillOpacity(double opacity); - void setFillRule(cairo_fill_rule_t rule); - - void setStroke(SPPaintServer *server); - void setStroke(SPColor const &color); - void setStrokeOpacity(double opacity); - void setStrokeWidth(double width); - void setLineCap(cairo_line_cap_t cap); - void setLineJoin(cairo_line_join_t join); - void setMitreLimit(double limit); - void setPaintBox(Geom::Rect const &pbox); - - void _invalidateCachedFill() { - } - void _invalidateCachedStroke() { - } - - struct Style { - Style() : opacity(0.0) {} - Paint paint; - double opacity; - }; - struct FillStyle : public Style { - FillStyle() : rule(CAIRO_FILL_RULE_EVEN_ODD) {} - cairo_fill_rule_t rule; - } _fill; - struct StrokeStyle : public Style { - StrokeStyle() - : cap(CAIRO_LINE_CAP_ROUND), join(CAIRO_LINE_JOIN_ROUND), - width(0.0), mitre_limit(0.0) - {} - - cairo_line_cap_t cap; - cairo_line_join_t join; - double width; - double mitre_limit; - } _stroke; }; struct NRArenaShapeClass { diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp new file mode 100644 index 000000000..c15dd78a3 --- /dev/null +++ b/src/display/nr-style.cpp @@ -0,0 +1,218 @@ +/** + * @file + * @brief Style information for rendering + *//* + * Authors: + * Krzysztof Kosiński <tweenk.pl@gmail.com> + * + * Copyright (C) 2010 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-style.h" +#include "style.h" +#include "sp-paint-server.h" +#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!) + +void NRStyle::Paint::clear() +{ + if (server) { + sp_object_unref(server, NULL); + server = NULL; + } + type = PAINT_NONE; +} + +void NRStyle::Paint::set(SPColor const &c) +{ + clear(); + type = PAINT_COLOR; + color = c; +} + +void NRStyle::Paint::set(SPPaintServer *ps) +{ + clear(); + if (ps) { + type = PAINT_SERVER; + server = ps; + sp_object_ref(server, NULL); + } +} + +NRStyle::NRStyle() + : fill() + , stroke() + , stroke_width(0.0) + , miter_limit(0.0) + , n_dash(0) + , dash(NULL) + , dash_offset(0.0) + , fill_rule(CAIRO_FILL_RULE_EVEN_ODD) + , line_cap(CAIRO_LINE_CAP_BUTT) + , line_join(CAIRO_LINE_JOIN_MITER) +{} + +NRStyle::~NRStyle() +{ + cairo_pattern_destroy(fill_pattern); + cairo_pattern_destroy(stroke_pattern); + if (dash) delete dash; +} + +void NRStyle::set(SPStyle *style) +{ + if ( style->fill.isPaintserver() ) { + fill.set(style->getFillPaintServer()); + } else if ( style->fill.isColor() ) { + fill.set(style->fill.value.color); + } else if ( style->fill.isNone() ) { + fill.clear(); + } else { + g_assert_not_reached(); + } + fill.opacity = SP_SCALE24_TO_FLOAT(style->fill_opacity.value); + + switch (style->fill_rule.computed) { + case SP_WIND_RULE_EVENODD: + fill_rule = CAIRO_FILL_RULE_EVEN_ODD; + break; + case SP_WIND_RULE_NONZERO: + fill_rule = CAIRO_FILL_RULE_WINDING; + break; + default: + g_assert_not_reached(); + } + + if ( style->stroke.isPaintserver() ) { + stroke.set(style->getStrokePaintServer()); + } else if ( style->stroke.isColor() ) { + stroke.set(style->stroke.value.color); + } else if ( style->stroke.isNone() ) { + stroke.clear(); + } else { + g_assert_not_reached(); + } + stroke.opacity = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); + stroke_width = style->stroke_width.computed; + switch (style->stroke_linecap.computed) { + case SP_STROKE_LINECAP_ROUND: + line_cap = CAIRO_LINE_CAP_ROUND; + break; + case SP_STROKE_LINECAP_SQUARE: + line_cap = CAIRO_LINE_CAP_SQUARE; + break; + case SP_STROKE_LINECAP_BUTT: + line_cap = CAIRO_LINE_CAP_BUTT; + break; + default: + g_assert_not_reached(); + } + switch (style->stroke_linejoin.computed) { + case SP_STROKE_LINEJOIN_ROUND: + line_join = CAIRO_LINE_JOIN_ROUND; + break; + case SP_STROKE_LINEJOIN_BEVEL: + line_join = CAIRO_LINE_JOIN_BEVEL; + break; + case SP_STROKE_LINEJOIN_MITER: + line_join = CAIRO_LINE_JOIN_MITER; + break; + default: + g_assert_not_reached(); + } + miter_limit = style->stroke_miterlimit.value; + + delete [] dash; + + n_dash = style->stroke_dash.n_dash; + if (n_dash != 0) { + dash_offset = style->stroke_dash.offset; + dash = new double[n_dash]; + for (unsigned int i = 0; i < n_dash; ++i) { + dash[i] = style->stroke_dash.dash[i]; + } + } else { + dash_offset = 0.0; + dash = NULL; + } + + opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); + + update(); +} + +bool NRStyle::prepareFill(cairo_t *ct, NRRect *paintbox) +{ + // update fill pattern + if (!fill_pattern) { + switch (fill.type) { + case PAINT_SERVER: + fill_pattern = sp_paint_server_create_pattern(fill.server, ct, paintbox, fill.opacity); + break; + case PAINT_COLOR: { + SPColor const &c = fill.color; + fill_pattern = cairo_pattern_create_rgba( + c.v.c[0], c.v.c[1], c.v.c[2], fill.opacity); + } break; + default: break; + } + } + if (!fill_pattern) return false; + return true; +} + +void NRStyle::applyFill(cairo_t *ct) +{ + cairo_set_source(ct, fill_pattern); + cairo_set_fill_rule(ct, fill_rule); +} + +bool NRStyle::prepareStroke(cairo_t *ct, NRRect *paintbox) +{ + if (!stroke_pattern) { + switch (stroke.type) { + case PAINT_SERVER: + stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct, paintbox, stroke.opacity); + break; + case PAINT_COLOR: { + SPColor const &c = stroke.color; + stroke_pattern = cairo_pattern_create_rgba( + c.v.c[0], c.v.c[1], c.v.c[2], stroke.opacity); + } break; + default: break; + } + } + if (!stroke_pattern) return false; + return true; +} + +void NRStyle::applyStroke(cairo_t *ct) +{ + cairo_set_source(ct, stroke_pattern); + cairo_set_line_width(ct, stroke_width); + cairo_set_line_cap(ct, line_cap); + cairo_set_line_join(ct, line_join); + cairo_set_miter_limit(ct, miter_limit); + cairo_set_dash(ct, dash, n_dash, dash_offset); +} + +void NRStyle::update() +{ + // force pattern update + cairo_pattern_destroy(fill_pattern); + cairo_pattern_destroy(stroke_pattern); + fill_pattern = NULL; + stroke_pattern = NULL; +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-style.h b/src/display/nr-style.h new file mode 100644 index 000000000..b2116a6c5 --- /dev/null +++ b/src/display/nr-style.h @@ -0,0 +1,82 @@ +/** + * @file + * @brief Style information for rendering + *//* + * Authors: + * Krzysztof Kosiński <tweenk.pl@gmail.com> + * + * Copyright (C) 2010 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_INKSCAPE_DISPLAY_NR_ARENA_STYLE_H +#define SEEN_INKSCAPE_DISPLAY_NR_ARENA_STYLE_H + +#include <cairo.h> +#include "color.h" + +class SPColor; +class SPPaintServer; +class SPStyle; +struct NRRect; + +struct NRStyle { + NRStyle(); + ~NRStyle(); + + void set(SPStyle *); + bool prepareFill(cairo_t *ct, NRRect *paintbox); + bool prepareStroke(cairo_t *ct, NRRect *paintbox); + void applyFill(cairo_t *ct); + void applyStroke(cairo_t *ct); + void update(); + + enum PaintType { + PAINT_NONE, + PAINT_COLOR, + PAINT_SERVER + }; + + struct Paint { + Paint() : type(PAINT_NONE), color(0), server(NULL), opacity(1.0) {} + ~Paint() { clear(); } + + PaintType type; + SPColor color; + SPPaintServer *server; + float opacity; + + void clear(); + void set(SPColor const &c); + void set(SPPaintServer *ps); + }; + + Paint fill; + Paint stroke; + float stroke_width; + float miter_limit; + float opacity; + unsigned int n_dash; + double *dash; + float dash_offset; + cairo_fill_rule_t fill_rule; + cairo_line_cap_t line_cap; + cairo_line_join_t line_join; + + cairo_pattern_t *fill_pattern; + cairo_pattern_t *stroke_pattern; +}; + +#endif + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : |
