From 917de2bab458d51b4149a1b794cbb1b6b9562171 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 22 Jun 2010 23:36:47 +0200 Subject: Initial Cairo rendering commit: solid shapes, gradients, opacity and patterns (bzr r9508.1.1) --- src/sp-pattern.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index ec0d0d576..8d1e8dab5 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -23,6 +23,7 @@ #include <2geom/transforms.h> #include "macros.h" #include "svg/svg.h" +#include "display/inkscape-cairo.h" #include "display/nr-arena.h" #include "display/nr-arena-group.h" #include "attributes.h" @@ -76,6 +77,7 @@ static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter); +static cairo_pattern_t *sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity); static SPPaintServerClass * pattern_parent_class; @@ -123,6 +125,7 @@ sp_pattern_class_init (SPPatternClass *klass) ps_class->painter_new = sp_pattern_painter_new; ps_class->painter_free = sp_pattern_painter_free; + ps_class->pattern_new = sp_pattern_create_pattern; } static void @@ -1016,3 +1019,128 @@ sp_pat_fill (SPPainter *painter, NRPixBlock *pb) } } } + +static cairo_pattern_t * +sp_pattern_create_pattern(SPPaintServer *ps, + cairo_t *base_ct, + NRRect const *bbox, + double opacity) +{ + SPPattern *pat = SP_PATTERN (ps); + Geom::Matrix ps2user; + bool needs_opacity = (1.0 - opacity) >= 1e-3; + bool visible = opacity >= 1e-3; + + if (!visible) + return NULL; + + if (pat->viewBox_set) { + gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0); + gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); + + // FIXME: preserveAspectRatio must be taken into account here too! + Geom::Matrix vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); + + ps2user = vb2ps * pattern_patternTransform(pat); + } else { + /* No viewbox, have to parse units */ + ps2user = pattern_patternTransform(pat); + if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { + /* BBox to user coordinate system */ + Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + ps2user *= bbox2user; + } + ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; + } + + /* Create arena */ + NRArena *arena = NRArena::create(); + unsigned int dkey = sp_item_display_key_new (1); + NRArenaGroup *root = NRArenaGroup::create(arena); + + /* Show items */ + for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + // find the first one with item children + if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { + for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + if (SP_IS_ITEM (child)) { + // for each item in pattern, show it on our arena, add to the group, + // and connect to the release signal in case the item gets deleted + NRArenaItem *cai; + cai = sp_item_invoke_show (SP_ITEM (child), arena, dkey, SP_ITEM_REFERENCE_FLAGS); + nr_arena_item_append_child (root, cai); + } + } + break; // do not go further up the chain if children are found + } + } + + double x = pattern_x(pat); + double y = pattern_y(pat); + double w = pattern_width(pat); + double h = pattern_height(pat); + + cairo_matrix_t cm; + cairo_get_matrix(base_ct, &cm); + Geom::Matrix full(cm.xx, cm.yx, cm.xy, cm.yy, 0, 0); + + // oversample the pattern slightly + // TODO: find optimum value. Maybe sqrt(2)? + Geom::Point c(Geom::Point(w, h)*ps2user.descrim()*full.descrim()*1.2); + c[Geom::X] = ceil(c[Geom::X]); + c[Geom::Y] = ceil(c[Geom::Y]); + Geom::Matrix t = Geom::Scale(c[Geom::X]/w, c[Geom::Y]/h); + + NRRectL one_tile; + one_tile.x0 = (int) floor(x); + one_tile.y0 = (int) floor(y); + one_tile.x1 = (int) ceil(x+w); + one_tile.y1 = (int) ceil(y+h); + + cairo_surface_t *target = cairo_get_target(base_ct); + cairo_surface_t *temp = cairo_surface_create_similar(target, CAIRO_CONTENT_COLOR_ALPHA, + c[Geom::X], c[Geom::Y]); + cairo_t *ct = cairo_create(temp); + ink_cairo_transform(ct, t); + + // render pattern. + if (needs_opacity) { + cairo_push_group(ct); // this group is for pattern + opacity + } + + // TODO: make sure there are no leaks. + NRPixBlock pb; + nr_pixblock_setup (&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, one_tile.x0, one_tile.y0, + one_tile.x1, one_tile.y1, TRUE); + NRGC gc(NULL); + gc.transform = Geom::identity(); + nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); + nr_arena_item_invoke_render (ct, root, &one_tile, &pb, 0); + nr_object_unref(arena); + nr_pixblock_release(&pb); + + if (needs_opacity) { + cairo_pop_group_to_source(ct); // pop raw pattern + cairo_paint_with_alpha(ct, opacity); // apply opacity + } + + cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp); + cairo_surface_destroy(temp); + + // Apply transformation to user space. Also compensate for oversampling. + ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * t); + cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT); + + return cp; +} + +/* + 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 : -- cgit v1.2.3 From 13b15b7b977eecbededd1734f5ab001f0c44d21f Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 30 Jun 2010 00:41:48 +0200 Subject: Consolidate Cairo utils in display/cairo-utils.h. Fix icons harder. (bzr r9508.1.8) --- src/sp-pattern.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 8d1e8dab5..5f0c4aebd 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -23,7 +23,7 @@ #include <2geom/transforms.h> #include "macros.h" #include "svg/svg.h" -#include "display/inkscape-cairo.h" +#include "display/cairo-utils.h" #include "display/nr-arena.h" #include "display/nr-arena-group.h" #include "attributes.h" -- cgit v1.2.3 From 9df97c14c5c6bf51e1312190c02b8e408aa82ed7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 4 Aug 2010 00:27:38 +0200 Subject: Fix catastrophic memory leak when rendering a pattern (bzr r9508.1.42) --- src/sp-pattern.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 5f0c4aebd..314eada01 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -1067,7 +1067,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, // for each item in pattern, show it on our arena, add to the group, // and connect to the release signal in case the item gets deleted NRArenaItem *cai; - cai = sp_item_invoke_show (SP_ITEM (child), arena, dkey, SP_ITEM_REFERENCE_FLAGS); + cai = sp_item_invoke_show (SP_ITEM (child), arena, dkey, SP_ITEM_SHOW_DISPLAY); nr_arena_item_append_child (root, cai); } } @@ -1109,15 +1109,11 @@ sp_pattern_create_pattern(SPPaintServer *ps, } // TODO: make sure there are no leaks. - NRPixBlock pb; - nr_pixblock_setup (&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, one_tile.x0, one_tile.y0, - one_tile.x1, one_tile.y1, TRUE); NRGC gc(NULL); gc.transform = Geom::identity(); nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); - nr_arena_item_invoke_render (ct, root, &one_tile, &pb, 0); + nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0); nr_object_unref(arena); - nr_pixblock_release(&pb); if (needs_opacity) { cairo_pop_group_to_source(ct); // pop raw pattern @@ -1125,6 +1121,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, } cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp); + cairo_destroy(ct); cairo_surface_destroy(temp); // Apply transformation to user space. Also compensate for oversampling. -- cgit v1.2.3 From 6e5865f22577b2aea99ec3f78d9b869bc367da28 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 4 Aug 2010 00:39:37 +0200 Subject: Fix pattern viewBox (bzr r9508.1.43) --- src/sp-pattern.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 314eada01..074873d5b 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -1028,6 +1028,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, { SPPattern *pat = SP_PATTERN (ps); Geom::Matrix ps2user; + Geom::Matrix vb2ps = Geom::identity(); bool needs_opacity = (1.0 - opacity) >= 1e-3; bool visible = opacity >= 1e-3; @@ -1039,19 +1040,16 @@ sp_pattern_create_pattern(SPPaintServer *ps, gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); // FIXME: preserveAspectRatio must be taken into account here too! - Geom::Matrix vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); - - ps2user = vb2ps * pattern_patternTransform(pat); - } else { - /* No viewbox, have to parse units */ - ps2user = pattern_patternTransform(pat); - if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - /* BBox to user coordinate system */ - Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - ps2user *= bbox2user; - } - ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; + vb2ps = Geom::Matrix(tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); + } + + ps2user = pattern_patternTransform(pat); + if (!pat->viewBox_set && pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { + /* BBox to user coordinate system */ + Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + ps2user *= bbox2user; } + ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; /* Create arena */ NRArena *arena = NRArena::create(); @@ -1110,7 +1108,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, // TODO: make sure there are no leaks. NRGC gc(NULL); - gc.transform = Geom::identity(); + gc.transform = vb2ps;//Geom::identity(); nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0); nr_object_unref(arena); -- cgit v1.2.3 From 30884b9e814d7baaa2299803e8cb76cf203ca084 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 4 Aug 2010 05:45:58 +0200 Subject: Wholesale cruft removal part 1 (bzr r9508.1.44) --- src/sp-pattern.cpp | 447 +---------------------------------------------------- 1 file changed, 1 insertion(+), 446 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 074873d5b..b2c718e3b 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -39,44 +39,18 @@ * Pattern */ -class SPPatPainter; - -struct SPPatPainter { - SPPainter painter; - SPPattern *pat; - - Geom::Matrix ps2px; - Geom::Matrix px2ps; - Geom::Matrix pcs2px; - - NRArena *arena; - unsigned int dkey; - NRArenaItem *root; - - bool use_cached_tile; - Geom::Matrix ca2pa; - Geom::Matrix pa2ca; - NRRectL cached_bbox; - NRPixBlock cached_tile; - - std::map *_release_connections; -}; - static void sp_pattern_class_init (SPPatternClass *klass); static void sp_pattern_init (SPPattern *gr); static void sp_pattern_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static void sp_pattern_release (SPObject *object); static void sp_pattern_set (SPObject *object, unsigned int key, const gchar *value); -static void sp_pattern_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref); static void sp_pattern_update (SPObject *object, SPCtx *ctx, unsigned int flags); static void sp_pattern_modified (SPObject *object, unsigned int flags); static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat); static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern); -static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); -static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter); static cairo_pattern_t *sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity); static SPPaintServerClass * pattern_parent_class; @@ -117,14 +91,11 @@ sp_pattern_class_init (SPPatternClass *klass) sp_object_class->build = sp_pattern_build; sp_object_class->release = sp_pattern_release; sp_object_class->set = sp_pattern_set; - sp_object_class->child_added = sp_pattern_child_added; sp_object_class->update = sp_pattern_update; sp_object_class->modified = sp_pattern_modified; // do we need _write? seems to work without it - ps_class->painter_new = sp_pattern_painter_new; - ps_class->painter_free = sp_pattern_painter_free; ps_class->pattern_new = sp_pattern_create_pattern; } @@ -318,34 +289,6 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value) } } -static void -sp_pattern_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref) -{ - SPPattern *pat = SP_PATTERN (object); - - if (((SPObjectClass *) (pattern_parent_class))->child_added) - (* ((SPObjectClass *) (pattern_parent_class))->child_added) (object, child, ref); - - SPObject *ochild = sp_object_get_child_by_repr(object, child); - if (SP_IS_ITEM (ochild)) { - - SPPaintServer *ps = SP_PAINT_SERVER (pat); - unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild)); - - for (SPPainter *p = ps->painters; p != NULL; p = p->next) { - - SPPatPainter *pp = (SPPatPainter *) p; - NRArenaItem *ai = sp_item_invoke_show (SP_ITEM (ochild), pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS); - - if (ai) { - nr_arena_item_add_child (pp->root, ai, NULL); - nr_arena_item_set_order (ai, position); - nr_arena_item_unref (ai); - } - } - } -} - /* TODO: do we need a ::remove_child handler? */ /* fixme: We need ::order_changed handler too (Lauris) */ @@ -632,394 +575,6 @@ bool pattern_hasItemChildren (SPPattern *pat) return false; } - - -/* Painter */ - -static void sp_pat_fill (SPPainter *painter, NRPixBlock *pb); - -// item in this pattern is about to be deleted, hide it on our arena and disconnect -void -sp_pattern_painter_release (SPObject *obj, SPPatPainter *painter) -{ - std::map::iterator iter = painter->_release_connections->find(obj); - if (iter != painter->_release_connections->end()) { - iter->second.disconnect(); - painter->_release_connections->erase(obj); - } - - sp_item_invoke_hide(SP_ITEM(obj), painter->dkey); -} - -/** -Creates a painter (i.e. the thing that does actual filling at the given zoom). -See (*) below for why the parent_transform may be necessary. -*/ -static SPPainter * -sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &/*parent_transform*/, const NRRect *bbox) -{ - SPPattern *pat = SP_PATTERN (ps); - SPPatPainter *pp = g_new (SPPatPainter, 1); - - pp->painter.type = SP_PAINTER_IND; - pp->painter.fill = sp_pat_fill; - - pp->pat = pat; - - if (pattern_patternUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - /* BBox to user coordinate system */ - Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - - // the final patternTransform, taking into account bbox - Geom::Matrix const ps2user(pattern_patternTransform(pat) * bbox2user); - - // see (*) comment below - pp->ps2px = ps2user * full_transform; - } else { - /* Problem: What to do, if we have mixed lengths and percentages? */ - /* Currently we do ignore percentages at all, but that is not good (lauris) */ - - /* fixme: We may try to normalize here too, look at linearGradient (Lauris) */ - - // (*) The spec says, "This additional transformation matrix [patternTransform] is - // post-multiplied to (i.e., inserted to the right of) any previously defined - // transformations, including the implicit transformation necessary to convert from - // object bounding box units to user space." To me, this means that the order should be: - // item_transform * patternTransform * parent_transform - // However both Batik and Adobe plugin use: - // patternTransform * item_transform * parent_transform - // So here I comply with the majority opinion, but leave my interpretation commented out below. - // (To get item_transform, I subtract parent from full.) - - //pp->ps2px = (full_transform / parent_transform) * pattern_patternTransform(pat) * parent_transform; - pp->ps2px = pattern_patternTransform(pat) * full_transform; - } - - pp->px2ps = pp->ps2px.inverse(); - - if (pat->viewBox_set) { - gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0); - gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); - - // FIXME: preserveAspectRatio must be taken into account here too! - Geom::Matrix vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); - - Geom::Matrix vb2us = vb2ps * pattern_patternTransform(pat); - - // see (*) - pp->pcs2px = vb2us * full_transform; - } else { - /* No viewbox, have to parse units */ - if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - /* BBox to user coordinate system */ - Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - - Geom::Matrix pcs2user = pattern_patternTransform(pat) * bbox2user; - - // see (*) - pp->pcs2px = pcs2user * full_transform; - } else { - // see (*) - //pcs2px = (full_transform / parent_transform) * pattern_patternTransform(pat) * parent_transform; - pp->pcs2px = pattern_patternTransform(pat) * full_transform; - } - - pp->pcs2px = Geom::Translate (pattern_x (pat), pattern_y (pat)) * pp->pcs2px; - } - - /* Create arena */ - pp->arena = NRArena::create(); - - pp->dkey = sp_item_display_key_new (1); - - /* Create group */ - pp->root = NRArenaGroup::create(pp->arena); - - /* Show items */ - pp->_release_connections = new std::map; - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children - for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { - if (SP_IS_ITEM (child)) { - // for each item in pattern, - NRArenaItem *cai; - // show it on our arena, - cai = sp_item_invoke_show (SP_ITEM (child), pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS); - // add to the group, - nr_arena_item_append_child (pp->root, cai); - // and connect to the release signal in case the item gets deleted - pp->_release_connections->insert(std::make_pair(child, child->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_pattern_painter_release), pp)))); - } - } - break; // do not go further up the chain if children are found - } - } - - { - NRRect one_tile,tr_tile; - one_tile.x0=pattern_x(pp->pat); - one_tile.y0=pattern_y(pp->pat); - one_tile.x1=one_tile.x0+pattern_width (pp->pat); - one_tile.y1=one_tile.y0+pattern_height (pp->pat); - // TODO: remove ps2px_nr after converting to 2geom - NR::Matrix ps2px_nr = from_2geom(pp->ps2px); - nr_rect_d_matrix_transform (&tr_tile, &one_tile, &ps2px_nr); - int tr_width=(int)ceil(1.3*(tr_tile.x1-tr_tile.x0)); - int tr_height=(int)ceil(1.3*(tr_tile.y1-tr_tile.y0)); -// if ( tr_width < 10000 && tr_height < 10000 && tr_width*tr_height < 1000000 ) { - pp->use_cached_tile=false;//true; - if ( tr_width > 1000 ) tr_width=1000; - if ( tr_height > 1000 ) tr_height=1000; - pp->cached_bbox.x0=0; - pp->cached_bbox.y0=0; - pp->cached_bbox.x1=tr_width; - pp->cached_bbox.y1=tr_height; - - if (pp->use_cached_tile) { - nr_pixblock_setup (&pp->cached_tile,NR_PIXBLOCK_MODE_R8G8B8A8N, pp->cached_bbox.x0, pp->cached_bbox.y0, pp->cached_bbox.x1, pp->cached_bbox.y1,TRUE); - } - - pp->pa2ca[0]=((double)tr_width)/(one_tile.x1-one_tile.x0); - pp->pa2ca[1]=0; - pp->pa2ca[2]=0; - pp->pa2ca[3]=((double)tr_height)/(one_tile.y1-one_tile.y0); - pp->pa2ca[4]=-one_tile.x0*pp->pa2ca[0]; - pp->pa2ca[5]=-one_tile.y0*pp->pa2ca[1]; - pp->ca2pa[0]=(one_tile.x1-one_tile.x0)/((double)tr_width); - pp->ca2pa[1]=0; - pp->ca2pa[2]=0; - pp->ca2pa[3]=(one_tile.y1-one_tile.y0)/((double)tr_height); - pp->ca2pa[4]=one_tile.x0; - pp->ca2pa[5]=one_tile.y0; -// } else { -// pp->use_cached_tile=false; -// } - } - - NRGC gc(NULL); - if ( pp->use_cached_tile ) { - gc.transform=pp->pa2ca; - } else { - gc.transform = pp->pcs2px; - } - nr_arena_item_invoke_update (pp->root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); - if ( pp->use_cached_tile ) { - nr_arena_item_invoke_render (NULL, pp->root, &pp->cached_bbox, &pp->cached_tile, 0); - } else { - // nothing to do now - } - - return (SPPainter *) pp; -} - - -static void -sp_pattern_painter_free (SPPaintServer */*ps*/, SPPainter *painter) -{ - SPPatPainter *pp = (SPPatPainter *) painter; - // free our arena - if (pp->arena) { - ((NRObject *) pp->arena)->unreference(); - pp->arena = NULL; - } - - // disconnect all connections - std::map::iterator iter; - for (iter = pp->_release_connections->begin() ; iter!=pp->_release_connections->end() ; iter++) { - iter->second.disconnect(); - } - pp->_release_connections->clear(); - delete pp->_release_connections; - - if ( pp->use_cached_tile ) nr_pixblock_release(&pp->cached_tile); - g_free (pp); -} - -void -get_cached_tile_pixel(SPPatPainter* pp,double x,double y,unsigned char &r,unsigned char &g,unsigned char &b,unsigned char &a) -{ - int ca_h=(int)floor(x); - int ca_v=(int)floor(y); - int r_x=(int)floor(16*(x-floor(x))); - int r_y=(int)floor(16*(y-floor(y))); - unsigned int tl_m=(16-r_x)*(16-r_y); - unsigned int bl_m=(16-r_x)*r_y; - unsigned int tr_m=r_x*(16-r_y); - unsigned int br_m=r_x*r_y; - int cb_h=ca_h+1; - int cb_v=ca_v+1; - if ( cb_h >= pp->cached_bbox.x1 ) cb_h=0; - if ( cb_v >= pp->cached_bbox.y1 ) cb_v=0; - - unsigned char* tlx=NR_PIXBLOCK_PX(&pp->cached_tile)+(ca_v*pp->cached_tile.rs)+4*ca_h; - unsigned char* trx=NR_PIXBLOCK_PX(&pp->cached_tile)+(ca_v*pp->cached_tile.rs)+4*cb_h; - unsigned char* blx=NR_PIXBLOCK_PX(&pp->cached_tile)+(cb_v*pp->cached_tile.rs)+4*ca_h; - unsigned char* brx=NR_PIXBLOCK_PX(&pp->cached_tile)+(cb_v*pp->cached_tile.rs)+4*cb_h; - - unsigned int tl_c=tlx[0]; - unsigned int tr_c=trx[0]; - unsigned int bl_c=blx[0]; - unsigned int br_c=brx[0]; - unsigned int f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8; - r=f_c; - tl_c=tlx[1]; - tr_c=trx[1]; - bl_c=blx[1]; - br_c=brx[1]; - f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8; - g=f_c; - tl_c=tlx[2]; - tr_c=trx[2]; - bl_c=blx[2]; - br_c=brx[2]; - f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8; - b=f_c; - tl_c=tlx[3]; - tr_c=trx[3]; - bl_c=blx[3]; - br_c=brx[3]; - f_c=(tl_m*tl_c+tr_m*tr_c+bl_m*bl_c+br_m*br_c)>>8; - a=f_c; -} - -static void -sp_pat_fill (SPPainter *painter, NRPixBlock *pb) -{ - SPPatPainter *pp; - NRRect ba, psa; - NRRectL area; - double x, y; - - pp = (SPPatPainter *) painter; - - if (pattern_width (pp->pat) < NR_EPSILON) return; - if (pattern_height (pp->pat) < NR_EPSILON) return; - - /* Find buffer area in gradient space */ - /* fixme: This is suboptimal (Lauris) */ - - if ( pp->use_cached_tile ) { - double pat_w=pattern_width (pp->pat); - double pat_h=pattern_height (pp->pat); - if ( pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N || pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8P ) { // same thing because it's filling an empty pixblock - unsigned char* lpx=NR_PIXBLOCK_PX(pb); - double px_y=pb->area.y0; - for (int j=pb->area.y0;jarea.y1;j++) { - unsigned char* cpx=lpx; - double px_x = pb->area.x0; - - double ps_x=pp->px2ps[0]*px_x+pp->px2ps[2]*px_y+pp->px2ps[4]; - double ps_y=pp->px2ps[1]*px_x+pp->px2ps[3]*px_y+pp->px2ps[5]; - for (int i=pb->area.x0;iarea.x1;i++) { - while ( ps_x > pat_w ) ps_x-=pat_w; - while ( ps_x < 0 ) ps_x+=pat_w; - while ( ps_y > pat_h ) ps_y-=pat_h; - while ( ps_y < 0 ) ps_y+=pat_h; - double ca_x=pp->pa2ca[0]*ps_x+pp->pa2ca[2]*ps_y+pp->pa2ca[4]; - double ca_y=pp->pa2ca[1]*ps_x+pp->pa2ca[3]*ps_y+pp->pa2ca[5]; - unsigned char n_a,n_r,n_g,n_b; - get_cached_tile_pixel(pp,ca_x,ca_y,n_r,n_g,n_b,n_a); - cpx[0]=n_r; - cpx[1]=n_g; - cpx[2]=n_b; - cpx[3]=n_a; - - px_x+=1.0; - ps_x+=pp->px2ps[0]; - ps_y+=pp->px2ps[1]; - cpx+=4; - } - px_y+=1.0; - lpx+=pb->rs; - } - } else if ( pb->mode == NR_PIXBLOCK_MODE_R8G8B8 ) { - unsigned char* lpx=NR_PIXBLOCK_PX(pb); - double px_y=pb->area.y0; - for (int j=pb->area.y0;jarea.y1;j++) { - unsigned char* cpx=lpx; - double px_x = pb->area.x0; - - double ps_x=pp->px2ps[0]*px_x+pp->px2ps[2]*px_y+pp->px2ps[4]; - double ps_y=pp->px2ps[1]*px_x+pp->px2ps[3]*px_y+pp->px2ps[5]; - for (int i=pb->area.x0;iarea.x1;i++) { - while ( ps_x > pat_w ) ps_x-=pat_w; - while ( ps_x < 0 ) ps_x+=pat_w; - while ( ps_y > pat_h ) ps_y-=pat_h; - while ( ps_y < 0 ) ps_y+=pat_h; - double ca_x=pp->pa2ca[0]*ps_x+pp->pa2ca[2]*ps_y+pp->pa2ca[4]; - double ca_y=pp->pa2ca[1]*ps_x+pp->pa2ca[3]*ps_y+pp->pa2ca[5]; - unsigned char n_a,n_r,n_g,n_b; - get_cached_tile_pixel(pp,ca_x,ca_y,n_r,n_g,n_b,n_a); - cpx[0]=n_r; - cpx[1]=n_g; - cpx[2]=n_b; - - px_x+=1.0; - ps_x+=pp->px2ps[0]; - ps_y+=pp->px2ps[1]; - cpx+=4; - } - px_y+=1.0; - lpx+=pb->rs; - } - } - } else { - ba.x0 = pb->area.x0; - ba.y0 = pb->area.y0; - ba.x1 = pb->area.x1; - ba.y1 = pb->area.y1; - - // Trying to solve this bug: https://bugs.launchpad.net/inkscape/+bug/167416 - // Bail out if the transformation matrix has extreme values. If we bail out - // however, then something (which was meaningless anyway) won't be rendered, - // which is better than getting stuck in a virtually infinite loop - if (fabs(pp->px2ps[0]) < 1e6 && - fabs(pp->px2ps[3]) < 1e6 && - fabs(pp->px2ps[4]) < 1e6 && - fabs(pp->px2ps[5]) < 1e6) - { - // TODO: remove px2ps_nr after converting to 2geom - NR::Matrix px2ps_nr = from_2geom(pp->px2ps); - nr_rect_d_matrix_transform (&psa, &ba, &px2ps_nr); - - psa.x0 = floor ((psa.x0 - pattern_x (pp->pat)) / pattern_width (pp->pat)) -1; - psa.y0 = floor ((psa.y0 - pattern_y (pp->pat)) / pattern_height (pp->pat)) -1; - psa.x1 = ceil ((psa.x1 - pattern_x (pp->pat)) / pattern_width (pp->pat)) +1; - psa.y1 = ceil ((psa.y1 - pattern_y (pp->pat)) / pattern_height (pp->pat)) +1; - - // If psa is too wide or tall, then something must be wrong! This is due to - // nr_rect_d_matrix_transform (&psa, &ba, &pp->px2ps) using a weird transformation matrix pp->px2ps. - g_assert(std::abs(psa.x1 - psa.x0) < 1e6); - g_assert(std::abs(psa.y1 - psa.y0) < 1e6); - - for (y = psa.y0; y < psa.y1; y++) { - for (x = psa.x0; x < psa.x1; x++) { - NRPixBlock ppb; - double psx, psy; - - psx = x * pattern_width (pp->pat); - psy = y * pattern_height (pp->pat); - - area.x0 = (gint32)(pb->area.x0 - (pp->ps2px[0] * psx + pp->ps2px[2] * psy)); - area.y0 = (gint32)(pb->area.y0 - (pp->ps2px[1] * psx + pp->ps2px[3] * psy)); - area.x1 = area.x0 + pb->area.x1 - pb->area.x0; - area.y1 = area.y0 + pb->area.y1 - pb->area.y0; - - // We do not update here anymore - - // Set up buffer - // fixme: (Lauris) - nr_pixblock_setup_extern (&ppb, pb->mode, area.x0, area.y0, area.x1, area.y1, NR_PIXBLOCK_PX (pb), pb->rs, FALSE, FALSE); - - nr_arena_item_invoke_render (NULL, pp->root, &area, &ppb, 0); - - nr_pixblock_release (&ppb); - } - } - } - } -} - static cairo_pattern_t * sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *base_ct, @@ -1108,7 +663,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, // TODO: make sure there are no leaks. NRGC gc(NULL); - gc.transform = vb2ps;//Geom::identity(); + gc.transform = vb2ps; nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0); nr_object_unref(arena); -- cgit v1.2.3 From 57a6fee4d17b6049b95ccf2ef445ed18c8a2a841 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 4 Aug 2010 23:08:41 +0200 Subject: Wholesale cruft removal part 2 (bzr r9508.1.45) --- src/sp-pattern.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index b2c718e3b..a559a4a50 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -18,8 +18,6 @@ #include #include -#include -#include "libnr/nr-matrix-fns.h" #include <2geom/transforms.h> #include "macros.h" #include "svg/svg.h" @@ -111,7 +109,7 @@ sp_pattern_init (SPPattern *pat) pat->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE; pat->patternContentUnits_set = FALSE; - pat->patternTransform = NR::identity(); + pat->patternTransform = Geom::identity(); pat->patternTransform_set = FALSE; pat->x.unset(); @@ -207,7 +205,7 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value) pat->patternTransform = t; pat->patternTransform_set = TRUE; } else { - pat->patternTransform = NR::identity(); + pat->patternTransform = Geom::identity(); pat->patternTransform_set = FALSE; } object->requestModified(SP_OBJECT_MODIFIED_FLAG); -- cgit v1.2.3 From 267b81d9fd0d1254a80b008c26237fbe4bd93610 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 6 Aug 2010 01:23:28 +0200 Subject: Minor cleanups (bzr r9508.1.51) --- src/sp-pattern.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index a559a4a50..8d156bc77 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -610,9 +610,11 @@ sp_pattern_create_pattern(SPPaintServer *ps, NRArenaGroup *root = NRArenaGroup::create(arena); /* Show items */ + SPPattern *shown = NULL; for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { // find the first one with item children if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { + shown = pat_i; for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_ITEM (child)) { // for each item in pattern, show it on our arena, add to the group, @@ -664,6 +666,12 @@ sp_pattern_create_pattern(SPPaintServer *ps, gc.transform = vb2ps; nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0); + for (SPObject *child = sp_object_first_child(SP_OBJECT(shown)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + if (SP_IS_ITEM (child)) { + sp_item_invoke_hide(SP_ITEM (child), dkey); + } + } + nr_object_unref(root); nr_object_unref(arena); if (needs_opacity) { -- cgit v1.2.3 From 67a9706d3aff71597ac1d6d72e329b1a88d1d70e Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 13 Aug 2010 00:13:20 +0200 Subject: Fix crash on empty patterns (bzr r9508.1.62) --- src/sp-pattern.cpp | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 8d156bc77..e211203d4 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -588,6 +588,35 @@ sp_pattern_create_pattern(SPPaintServer *ps, if (!visible) return NULL; + /* Show items */ + SPPattern *shown = NULL; + for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + // find the first one with item children + if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { + shown = pat_i; + break; // do not go further up the chain if children are found + } + } + + if (!shown) { + return cairo_pattern_create_rgba(0,0,0,0); + } + + /* Create arena */ + NRArena *arena = NRArena::create(); + unsigned int dkey = sp_item_display_key_new (1); + NRArenaGroup *root = NRArenaGroup::create(arena); + + for (SPObject *child = sp_object_first_child(SP_OBJECT(shown)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + if (SP_IS_ITEM (child)) { + // for each item in pattern, show it on our arena, add to the group, + // and connect to the release signal in case the item gets deleted + NRArenaItem *cai; + cai = sp_item_invoke_show (SP_ITEM (child), arena, dkey, SP_ITEM_SHOW_DISPLAY); + nr_arena_item_append_child (root, cai); + } + } + if (pat->viewBox_set) { gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0); gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); @@ -604,30 +633,6 @@ sp_pattern_create_pattern(SPPaintServer *ps, } ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; - /* Create arena */ - NRArena *arena = NRArena::create(); - unsigned int dkey = sp_item_display_key_new (1); - NRArenaGroup *root = NRArenaGroup::create(arena); - - /* Show items */ - SPPattern *shown = NULL; - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - // find the first one with item children - if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { - shown = pat_i; - for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { - if (SP_IS_ITEM (child)) { - // for each item in pattern, show it on our arena, add to the group, - // and connect to the release signal in case the item gets deleted - NRArenaItem *cai; - cai = sp_item_invoke_show (SP_ITEM (child), arena, dkey, SP_ITEM_SHOW_DISPLAY); - nr_arena_item_append_child (root, cai); - } - } - break; // do not go further up the chain if children are found - } - } - double x = pattern_x(pat); double y = pattern_y(pat); double w = pattern_width(pat); -- cgit v1.2.3 From 2f3d79db2fad212c8aa1bff7bb13132a34541aff Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 15 Aug 2010 03:19:33 +0200 Subject: Make nr_arena_invoke_render expect an already transformed context, to remove a limitation to integer translations imposed by NRRectL (bzr r9508.1.68) --- src/sp-pattern.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index e211203d4..2f8c141bf 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -660,6 +660,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, c[Geom::X], c[Geom::Y]); cairo_t *ct = cairo_create(temp); ink_cairo_transform(ct, t); + cairo_translate(ct, -x, -y); // render pattern. if (needs_opacity) { -- cgit v1.2.3 From aa244fa35a3801b2fb11ec03ce4a2c51a9db1838 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 15 Aug 2010 04:15:10 +0200 Subject: Fix handling of x and y attributes of patterns (bzr r9508.1.69) --- src/sp-pattern.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 2f8c141bf..7fc4cb3f5 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -633,34 +633,39 @@ sp_pattern_create_pattern(SPPaintServer *ps, } ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; - double x = pattern_x(pat); - double y = pattern_y(pat); - double w = pattern_width(pat); - double h = pattern_height(pat); + Geom::Point p(pattern_x(pat), pattern_y(pat)); + Geom::Point pd(pattern_width(pat), pattern_height(pat)); + Geom::Rect pattern_tile(p, p + pd); + + if (pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { + // interpret x, y, width, height in relation to bbox + Geom::Matrix bbox2user(bbox->x1 - bbox->x0, 0,0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + pattern_tile = pattern_tile * bbox2user; + } cairo_matrix_t cm; cairo_get_matrix(base_ct, &cm); Geom::Matrix full(cm.xx, cm.yx, cm.xy, cm.yy, 0, 0); // oversample the pattern slightly - // TODO: find optimum value. Maybe sqrt(2)? - Geom::Point c(Geom::Point(w, h)*ps2user.descrim()*full.descrim()*1.2); + // TODO: find optimum value + Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.2); c[Geom::X] = ceil(c[Geom::X]); c[Geom::Y] = ceil(c[Geom::Y]); - Geom::Matrix t = Geom::Scale(c[Geom::X]/w, c[Geom::Y]/h); + Geom::Matrix t = Geom::Scale(c) * Geom::Scale(pattern_tile.dimensions()).inverse(); NRRectL one_tile; - one_tile.x0 = (int) floor(x); - one_tile.y0 = (int) floor(y); - one_tile.x1 = (int) ceil(x+w); - one_tile.y1 = (int) ceil(y+h); + one_tile.x0 = (int) floor(pattern_tile[Geom::X].min()); + one_tile.y0 = (int) floor(pattern_tile[Geom::Y].min()); + one_tile.x1 = (int) ceil(pattern_tile[Geom::X].max()); + one_tile.y1 = (int) ceil(pattern_tile[Geom::Y].max()); cairo_surface_t *target = cairo_get_target(base_ct); cairo_surface_t *temp = cairo_surface_create_similar(target, CAIRO_CONTENT_COLOR_ALPHA, c[Geom::X], c[Geom::Y]); cairo_t *ct = cairo_create(temp); + // scale into a coord system where the surface w,h are equal to tile w,h ink_cairo_transform(ct, t); - cairo_translate(ct, -x, -y); // render pattern. if (needs_opacity) { -- cgit v1.2.3 From aabb5bb05a97e7414fd6f0204178788800871151 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 28 May 2011 03:36:31 -0700 Subject: Port of 0.48.x branch revision 9781. Cleanup of legacy code and casting that was breaking 64-bit gradient use. Fixes bug #743530 and bug #778441. Fixed bugs: - https://launchpad.net/bugs/743530 - https://launchpad.net/bugs/778441 (bzr r10242) --- src/sp-pattern.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 9ea0ef891..0b2fe8389 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -78,7 +78,7 @@ static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox); static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter); -static SPPaintServerClass * pattern_parent_class; +static SPPaintServerClass * pattern_parent_class = 0; GType sp_pattern_get_type (void) @@ -105,13 +105,10 @@ sp_pattern_get_type (void) static void sp_pattern_class_init (SPPatternClass *klass) { - SPObjectClass *sp_object_class; - SPPaintServerClass *ps_class; + SPObjectClass *sp_object_class = SP_OBJECT_CLASS( klass ); + SPPaintServerClass *ps_class = SP_PAINT_SERVER_CLASS( klass ); - sp_object_class = (SPObjectClass *) klass; - ps_class = (SPPaintServerClass *) klass; - - pattern_parent_class = (SPPaintServerClass*)g_type_class_ref (SP_TYPE_PAINT_SERVER); + pattern_parent_class = SP_PAINT_SERVER_CLASS( g_type_class_ref(SP_TYPE_PAINT_SERVER) ); sp_object_class->build = sp_pattern_build; sp_object_class->release = sp_pattern_release; @@ -683,7 +680,7 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, G SPPattern *pat = SP_PATTERN (ps); SPPatPainter *pp = g_new (SPPatPainter, 1); - pp->painter.type = SP_PAINTER_IND; + pp->painter.server_type = G_OBJECT_TYPE(ps); pp->painter.fill = sp_pat_fill; pp->pat = pat; -- cgit v1.2.3 From 3638efba5bec8a6afc9211aa6bbe289767d20b38 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 3 Jun 2011 19:45:55 -0700 Subject: Removed outdated/unsafe SP_DOCUMENT_DEFS macro and reduced usage of SP_ROOT() gtk type function/macro. (bzr r10254) --- src/sp-pattern.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 0b2fe8389..d7522fce8 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -469,7 +469,7 @@ SPPattern *pattern_chain(SPPattern *pattern) { SPDocument *document = pattern->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); + Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("inkscape:collect", "always"); @@ -522,7 +522,7 @@ sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool se const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move) { Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); + Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("patternUnits", "userSpaceOnUse"); -- cgit v1.2.3 From 328fad57dbfb65e3bd31062021d5cc3081e68515 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 22 Jul 2011 04:09:27 +0200 Subject: Replace direct use of Cairo contexts and surfaces in the rendering tree with wrappers which keep some extra information about the surface, amd NRRect and NRRectL use with Geom::Rect and Geom::IntRect. Should simplify implementing filter primitive subregions. (bzr r10347.1.17) --- src/sp-pattern.cpp | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index d1e7671ed..3a3d01ebd 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -22,6 +22,8 @@ #include "macros.h" #include "svg/svg.h" #include "display/cairo-utils.h" +#include "display/drawing-context.h" +#include "display/drawing-surface.h" #include "display/nr-arena.h" #include "display/nr-arena-group.h" #include "attributes.h" @@ -658,9 +660,8 @@ sp_pattern_create_pattern(SPPaintServer *ps, } ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; - Geom::Point p(pattern_x(pat), pattern_y(pat)); - Geom::Point pd(pattern_width(pat), pattern_height(pat)); - Geom::Rect pattern_tile(p, p + pd); + Geom::Rect pattern_tile = Geom::Rect::from_xywh(pattern_x(pat), pattern_y(pat), + pattern_width(pat), pattern_height(pat)); if (pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { // interpret x, y, width, height in relation to bbox @@ -674,34 +675,24 @@ sp_pattern_create_pattern(SPPaintServer *ps, // oversample the pattern slightly // TODO: find optimum value - Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.2); + Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.1); c[Geom::X] = ceil(c[Geom::X]); c[Geom::Y] = ceil(c[Geom::Y]); - Geom::Affine t = Geom::Scale(c) * Geom::Scale(pattern_tile.dimensions()).inverse(); - - NRRectL one_tile; - one_tile.x0 = (int) floor(pattern_tile[Geom::X].min()); - one_tile.y0 = (int) floor(pattern_tile[Geom::Y].min()); - one_tile.x1 = (int) ceil(pattern_tile[Geom::X].max()); - one_tile.y1 = (int) ceil(pattern_tile[Geom::Y].max()); - - cairo_surface_t *target = cairo_get_target(base_ct); - cairo_surface_t *temp = cairo_surface_create_similar(target, CAIRO_CONTENT_COLOR_ALPHA, - c[Geom::X], c[Geom::Y]); - cairo_t *ct = cairo_create(temp); - // scale into a coord system where the surface w,h are equal to tile w,h - ink_cairo_transform(ct, t); + + Geom::IntRect one_tile = pattern_tile.roundOutwards(); + Inkscape::DrawingSurface temp(pattern_tile, c.ceil()); + Inkscape::DrawingContext ct(temp); // render pattern. if (needs_opacity) { - cairo_push_group(ct); // this group is for pattern + opacity + ct.pushGroup(); // this group is for pattern + opacity } // TODO: make sure there are no leaks. NRGC gc(NULL); gc.transform = vb2ps; - nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); - nr_arena_item_invoke_render (ct, root, &one_tile, NULL, 0); + nr_arena_item_invoke_update (root, Geom::IntRect::infinite(), &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); + nr_arena_item_invoke_render (ct, root, one_tile, 0); for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) { if (SP_IS_ITEM (child)) { SP_ITEM(child)->invoke_hide(dkey); @@ -711,16 +702,14 @@ sp_pattern_create_pattern(SPPaintServer *ps, nr_object_unref(arena); if (needs_opacity) { - cairo_pop_group_to_source(ct); // pop raw pattern - cairo_paint_with_alpha(ct, opacity); // apply opacity + ct.popGroupToSource(); // pop raw pattern + ct.paint(opacity); // apply opacity } - cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp); - cairo_destroy(ct); - cairo_surface_destroy(temp); + cairo_pattern_t *cp = cairo_pattern_create_for_surface(temp.raw()); // Apply transformation to user space. Also compensate for oversampling. - ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * t); + ink_cairo_pattern_set_matrix(cp, ps2user.inverse() * temp.drawingTransform()); cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT); return cp; -- cgit v1.2.3 From 4dd33aa4d5c57706c7f64f63391174954160a308 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 6 Aug 2011 14:18:32 +0200 Subject: Rewrite NRArenaItem hierarchy into C++ (bzr r10347.1.21) --- src/sp-pattern.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 3a3d01ebd..805a93267 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -25,10 +25,11 @@ #include "display/drawing-context.h" #include "display/drawing-surface.h" #include "display/nr-arena.h" -#include "display/nr-arena-group.h" +#include "display/drawing-group.h" #include "attributes.h" #include "document-private.h" #include "uri.h" +#include "style.h" #include "sp-pattern.h" #include "xml/repr.h" #include "display/grayscale.h" @@ -632,15 +633,15 @@ sp_pattern_create_pattern(SPPaintServer *ps, /* Create arena */ NRArena *arena = NRArena::create(); unsigned int dkey = SPItem::display_key_new (1); - NRArenaGroup *root = NRArenaGroup::create(arena); + Inkscape::DrawingGroup *root = new Inkscape::DrawingGroup(arena); for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext() ) { if (SP_IS_ITEM (child)) { // for each item in pattern, show it on our arena, add to the group, // and connect to the release signal in case the item gets deleted - NRArenaItem *cai; + Inkscape::DrawingItem *cai; cai = SP_ITEM(child)->invoke_show (arena, dkey, SP_ITEM_SHOW_DISPLAY); - nr_arena_item_append_child (root, cai); + root->appendChild(cai); } } @@ -689,17 +690,17 @@ sp_pattern_create_pattern(SPPaintServer *ps, } // TODO: make sure there are no leaks. - NRGC gc(NULL); - gc.transform = vb2ps; - nr_arena_item_invoke_update (root, Geom::IntRect::infinite(), &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_ALL); - nr_arena_item_invoke_render (ct, root, one_tile, 0); + Inkscape::UpdateContext ctx; + ctx.ctm = vb2ps; + root->update(Geom::IntRect::infinite(), ctx, Inkscape::DrawingItem::STATE_ALL, 0); + root->render(ct, one_tile, 0); for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) { if (SP_IS_ITEM (child)) { SP_ITEM(child)->invoke_hide(dkey); } } - nr_object_unref(root); nr_object_unref(arena); + delete root; if (needs_opacity) { ct.popGroupToSource(); // pop raw pattern -- cgit v1.2.3 From 75976ea07dba9b97186667524d0a76603de416af Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 7 Aug 2011 12:53:12 +0200 Subject: Rewrite NRArena -> Inkscape::Drawing. Call render and update methods on the Drawing rather than on the root DrawingItem. (bzr r10347.1.25) --- src/sp-pattern.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 805a93267..9aefdf6ff 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -24,7 +24,7 @@ #include "display/cairo-utils.h" #include "display/drawing-context.h" #include "display/drawing-surface.h" -#include "display/nr-arena.h" +#include "display/drawing.h" #include "display/drawing-group.h" #include "attributes.h" #include "document-private.h" @@ -630,17 +630,18 @@ sp_pattern_create_pattern(SPPaintServer *ps, return cairo_pattern_create_rgba(0,0,0,0); } - /* Create arena */ - NRArena *arena = NRArena::create(); + /* Create drawing for rendering */ + Inkscape::Drawing drawing; unsigned int dkey = SPItem::display_key_new (1); - Inkscape::DrawingGroup *root = new Inkscape::DrawingGroup(arena); + Inkscape::DrawingGroup *root = new Inkscape::DrawingGroup(drawing); + drawing.setRoot(root); for (SPObject *child = shown->firstChild(); child != NULL; child = child->getNext() ) { if (SP_IS_ITEM (child)) { - // for each item in pattern, show it on our arena, add to the group, + // for each item in pattern, show it on our drawing, add to the group, // and connect to the release signal in case the item gets deleted Inkscape::DrawingItem *cai; - cai = SP_ITEM(child)->invoke_show (arena, dkey, SP_ITEM_SHOW_DISPLAY); + cai = SP_ITEM(child)->invoke_show (drawing, dkey, SP_ITEM_SHOW_DISPLAY); root->appendChild(cai); } } @@ -676,7 +677,10 @@ sp_pattern_create_pattern(SPPaintServer *ps, // oversample the pattern slightly // TODO: find optimum value - Geom::Point c(pattern_tile.dimensions()*ps2user.descrim()*full.descrim()*1.1); + // TODO: this is lame. instead of using descrim(), we should extract + // the scaling component from the complete matrix and use it + // to find the optimum tile size for rendering + Geom::Point c(pattern_tile.dimensions()*vb2ps.descrim()*ps2user.descrim()*full.descrim()*1.1); c[Geom::X] = ceil(c[Geom::X]); c[Geom::Y] = ceil(c[Geom::Y]); @@ -692,15 +696,13 @@ sp_pattern_create_pattern(SPPaintServer *ps, // TODO: make sure there are no leaks. Inkscape::UpdateContext ctx; ctx.ctm = vb2ps; - root->update(Geom::IntRect::infinite(), ctx, Inkscape::DrawingItem::STATE_ALL, 0); - root->render(ct, one_tile, 0); + drawing.update(Geom::IntRect::infinite(), ctx); + drawing.render(ct, one_tile); for (SPObject *child = shown->firstChild() ; child != NULL; child = child->getNext() ) { if (SP_IS_ITEM (child)) { SP_ITEM(child)->invoke_hide(dkey); } } - nr_object_unref(arena); - delete root; if (needs_opacity) { ct.popGroupToSource(); // pop raw pattern -- cgit v1.2.3 From 79012ca437ff3d7c25e4d164b1b9c3dccc2b4b7f Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 27 Aug 2011 15:20:17 +0200 Subject: Remove NRRect from paint servers and temporary calculations (bzr r10582.1.4) --- src/sp-pattern.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 9aefdf6ff..b8ccf5648 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -53,7 +53,7 @@ static void sp_pattern_modified (SPObject *object, unsigned int flags); static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat); static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern); -static cairo_pattern_t *sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *ct, NRRect const *bbox, double opacity); +static cairo_pattern_t *sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *ct, Geom::OptRect const &bbox, double opacity); static SPPaintServerClass * pattern_parent_class; @@ -604,7 +604,7 @@ bool pattern_hasItemChildren (SPPattern *pat) static cairo_pattern_t * sp_pattern_create_pattern(SPPaintServer *ps, cairo_t *base_ct, - NRRect const *bbox, + Geom::OptRect const &bbox, double opacity) { SPPattern *pat = SP_PATTERN (ps); @@ -657,7 +657,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, ps2user = pattern_patternTransform(pat); if (!pat->viewBox_set && pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { /* BBox to user coordinate system */ - Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user (bbox->width(), 0.0, 0.0, bbox->height(), bbox->left(), bbox->top()); ps2user *= bbox2user; } ps2user = Geom::Translate (pattern_x (pat), pattern_y (pat)) * ps2user; @@ -667,7 +667,7 @@ sp_pattern_create_pattern(SPPaintServer *ps, if (pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { // interpret x, y, width, height in relation to bbox - Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0,0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user(bbox->width(), 0.0, 0.0, bbox->height(), bbox->left(), bbox->top()); pattern_tile = pattern_tile * bbox2user; } -- cgit v1.2.3 From 24526cceccb4ed103a6324756476c64efb3fb5dd Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 27 Aug 2011 16:58:22 +0200 Subject: Remove all NRRect use. (bzr r10582.1.5) --- src/sp-pattern.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src/sp-pattern.cpp') diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index b8ccf5648..03afc1bf3 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -245,11 +245,8 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value) height = g_ascii_strtod (eptr, &eptr); while (*eptr && ((*eptr == ',') || (*eptr == ' '))) eptr++; if ((width > 0) && (height > 0)) { - pat->viewBox.x0 = x; - pat->viewBox.y0 = y; - pat->viewBox.x1 = x + width; - pat->viewBox.y1 = y + height; - pat->viewBox_set = TRUE; + pat->viewBox = Geom::Rect::from_xywh(x, y, width, height); + pat->viewBox_set = TRUE; } else { pat->viewBox_set = FALSE; } @@ -581,13 +578,16 @@ gdouble pattern_height (SPPattern *pat) return 0; } -NRRect *pattern_viewBox (SPPattern *pat) +Geom::OptRect pattern_viewBox (SPPattern *pat) { - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { - if (pat_i->viewBox_set) - return &(pat_i->viewBox); - } - return &(pat->viewBox); + Geom::OptRect viewbox; + for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + if (pat_i->viewBox_set) { + viewbox = pat_i->viewBox; + break; + } + } + return viewbox; } bool pattern_hasItemChildren (SPPattern *pat) @@ -647,11 +647,12 @@ sp_pattern_create_pattern(SPPaintServer *ps, } if (pat->viewBox_set) { - gdouble tmp_x = pattern_width (pat) / (pattern_viewBox(pat)->x1 - pattern_viewBox(pat)->x0); - gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); + Geom::Rect vb = *pattern_viewBox(pat); + gdouble tmp_x = pattern_width (pat) / vb.width(); + gdouble tmp_y = pattern_height (pat) / vb.height(); // FIXME: preserveAspectRatio must be taken into account here too! - vb2ps = Geom::Affine(tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); + vb2ps = Geom::Affine(tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - vb.left() * tmp_x, pattern_y(pat) - vb.top() * tmp_y); } ps2user = pattern_patternTransform(pat); -- cgit v1.2.3