diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2013-10-02 22:35:52 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2013-10-02 22:35:52 +0000 |
| commit | 9240dbde4547c7e7529f31645ea916faae72bafa (patch) | |
| tree | 82c7e2e222dd3bd92dea9a21ed60c0479f0149b8 /src | |
| parent | update to trunk (diff) | |
| parent | Fix segment welding in the node tool hanging when a two-point segment (diff) | |
| download | inkscape-9240dbde4547c7e7529f31645ea916faae72bafa.tar.gz inkscape-9240dbde4547c7e7529f31645ea916faae72bafa.zip | |
update to trunk
(bzr r12588.1.10)
Diffstat (limited to 'src')
65 files changed, 858 insertions, 925 deletions
diff --git a/src/arc-context.cpp b/src/arc-context.cpp index 350df908b..046541b9b 100644 --- a/src/arc-context.cpp +++ b/src/arc-context.cpp @@ -409,7 +409,7 @@ void SPArcContext::drag(Geom::Point pt, guint state) { } } - sp_arc_position_set(SP_ARC(this->arc), + this->arc->sp_arc_position_set( r.midpoint()[Geom::X], r.midpoint()[Geom::Y], r.dimensions()[Geom::X] / 2, r.dimensions()[Geom::Y] / 2); diff --git a/src/color-profile.cpp b/src/color-profile.cpp index e8a6a9c98..e6a9ac71c 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -829,7 +829,7 @@ std::vector<Glib::ustring> ColorProfile::getProfileFiles() for (gchar const *file = g_dir_read_name(dir); file != NULL; file = g_dir_read_name(dir)) { gchar *filepath = g_build_filename(it->c_str(), file, NULL); if ( g_file_test( filepath, G_FILE_TEST_IS_DIR ) ) { - sources.push_back(g_strdup(filepath)); + sources.push_back( filepath ); } else { if ( isIccFile( filepath ) ) { files.push_back( filepath ); diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp index 6d52b89fc..b5ce18891 100644 --- a/src/display/drawing-group.cpp +++ b/src/display/drawing-group.cpp @@ -28,6 +28,7 @@ DrawingGroup::~DrawingGroup() { if (_style) sp_style_unref(_style); + delete _child_transform; // delete NULL; is safe } /** diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp index 1af07cb44..71a7f8906 100644 --- a/src/display/drawing-item.cpp +++ b/src/display/drawing-item.cpp @@ -141,7 +141,14 @@ DrawingItem::appendChild(DrawingItem *item) assert(item->_child_type == CHILD_ORPHAN); item->_child_type = CHILD_NORMAL; _children.push_back(*item); - _markForUpdate(STATE_ALL, false); + + // This ensures that _markForUpdate() called on the child will recurse to this item + item->_state = STATE_ALL; + // Because _markForUpdate recurses through ancestors, we can simply call it + // on the just-added child. This has the additional benefit that we do not + // rely on the appended child being in the default non-updated state. + // We set propagate to true, because the child might have descendants of its own. + item->_markForUpdate(STATE_ALL, true); } void @@ -151,7 +158,9 @@ DrawingItem::prependChild(DrawingItem *item) assert(item->_child_type == CHILD_ORPHAN); item->_child_type = CHILD_NORMAL; _children.push_front(*item); - _markForUpdate(STATE_ALL, false); + // See appendChild for explanation + item->_state = STATE_ALL; + item->_markForUpdate(STATE_ALL, true); } /// Delete all regular children of this item (not mask or clip). @@ -281,17 +290,10 @@ DrawingItem::setZOrder(unsigned z) _markForRendering(); } -void DrawingItem::setItemBounds(Geom::OptRect const &bounds) -{ - if (!bounds) return; - Geom::IntRect copy = bounds->roundOutwards(); - if (_filter) _filter->area_enlarge(copy, this); - this->setFilterBounds(copy); -} - -void DrawingItem::setFilterBounds(Geom::OptRect const &bounds) +void +DrawingItem::setItemBounds(Geom::OptRect const &bounds) { - if (bounds) _filter_bbox = bounds; + _item_bbox = bounds; } /** @@ -359,10 +361,14 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne if (to_update & STATE_BBOX) { // compute drawbox - if (_filter && render_filters && _filter_bbox) { - Geom::OptRect enlarged = _filter_bbox; - *enlarged *= ctm(); - _drawbox = enlarged->roundOutwards(); + if (_filter && render_filters) { + Geom::OptRect enlarged = _filter->filter_effect_area(_item_bbox); + if (enlarged) { + *enlarged *= ctm(); + _drawbox = enlarged->roundOutwards(); + } else { + _drawbox = Geom::OptIntRect(); + } } else { _drawbox = _bbox; } @@ -714,8 +720,11 @@ DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags) { // Sometimes there's no BBOX in state, reason unknown (bug 992817) // I made this not an assert to remove the warning - if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) + if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) { + g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d", + _state & STATE_BBOX, _state & STATE_PICK); return NULL; + } // ignore invisible and insensitive items unless sticky if (!(flags & PICK_STICKY) && !(_visible && _sensitive)) return NULL; @@ -736,7 +745,10 @@ DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags) } Geom::OptIntRect box = (outline || (flags & PICK_AS_CLIP)) ? _bbox : _drawbox; - if (!box) return NULL; + if (!box) { + g_warning("bbox unset when picking"); + return NULL; + } Geom::Rect expanded = *box; expanded.expandBy(delta); @@ -756,6 +768,9 @@ DrawingItem::pick(Geom::Point const &p, double delta, unsigned flags) void DrawingItem::_markForRendering() { + // TODO: this function does too much work when a large subtree + // is invalidated - fix + bool outline = _drawing.outline(); Geom::OptIntRect dirty = outline ? _bbox : _drawbox; if (!dirty) return; @@ -807,8 +822,8 @@ DrawingItem::_invalidateFilterBackground(Geom::IntRect const &area) * all children should also have the corresponding flags unset before checking * whether they need to be traversed. This way there is one less traversal * of the tree. Without this we would need to unset state bits in all children. - * With _propagate we do this during the update call, when we have to traverse - * the tree anyway. + * With _propagate we do this during the update call, when we have to recurse + * into children anyway. */ void DrawingItem::_markForUpdate(unsigned flags, bool propagate) @@ -818,15 +833,31 @@ DrawingItem::_markForUpdate(unsigned flags, bool propagate) } if (_state & flags) { + unsigned oldstate = _state; _state &= ~flags; - if (_parent) { + if (oldstate != _state && _parent) { + // If we actually reset anything in state, recurse on the parent. _parent->_markForUpdate(flags, false); } else { + // If nothing changed, it means our ancestors are already invalidated + // up to the root. Do not bother recursing, because it won't change anything. + // Also do this if we are the root item, because we have no more ancestors + // to invalidate. _drawing.signal_request_update.emit(this); } } } +/** + * Process information related to the new style. + * + * This function is something of a hack to avoid creating an extra class in the hierarchy + * which would differ from DrawingItem only by having a _style member. + * This is mainly to the benefit of DrawingGlyphs, which use the style of their parent. + * This should probably be refactored some day, possibly by creating the relevant class + * or creating a more complex data model in DrawingText and removing DrawingGlyphs, + * which would cause every item to have a style. + */ void DrawingItem::_setStyleCommon(SPStyle *&_style, SPStyle *style) { @@ -834,7 +865,6 @@ DrawingItem::_setStyleCommon(SPStyle *&_style, SPStyle *style) if (_style) sp_style_unref(_style); _style = style; - // if group has a filter if (style->filter.set && style->getFilter()) { if (!_filter) { int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter())); diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h index c69b996b4..e03bbd0f7 100644 --- a/src/display/drawing-item.h +++ b/src/display/drawing-item.h @@ -89,7 +89,7 @@ public: Geom::OptIntRect geometricBounds() const { return _bbox; } Geom::OptIntRect visualBounds() const { return _drawbox; } - Geom::OptRect filterBounds() const { return _filter_bbox; } + Geom::OptRect itemBounds() const { return _item_bbox; } Geom::Affine ctm() const { return _ctm; } Geom::Affine transform() const { return _transform ? *_transform : Geom::identity(); } Drawing &drawing() const { return _drawing; } @@ -176,7 +176,9 @@ protected: Geom::Affine _ctm; ///< Total transform from item coords to display coords Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords including stroke Geom::OptIntRect _drawbox; ///< Full visual bounding box - enlarged by filters, shrunk by clips and masks - Geom::OptRect _filter_bbox; ///< Used by filters when settings bounds + Geom::OptRect _item_bbox; ///< Geometric bounding box in item's user space. + /// This is used to compute the filter effect region and render in + /// objectBoundingBox units. DrawingItem *_clip; DrawingItem *_mask; diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp index e689d0755..e80f12486 100644 --- a/src/display/drawing-shape.cpp +++ b/src/display/drawing-shape.cpp @@ -179,8 +179,8 @@ DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigne // update fill and stroke paints. // this cannot be done during nr_arena_shape_update, because we need a Cairo context // to render svg:pattern - has_fill = _nrstyle.prepareFill(ct, _bbox); - has_stroke = _nrstyle.prepareStroke(ct, _bbox); + has_fill = _nrstyle.prepareFill(ct, _item_bbox); + has_stroke = _nrstyle.prepareStroke(ct, _item_bbox); has_stroke &= (_nrstyle.stroke_width != 0); if (has_fill || has_stroke) { diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index fa9ce4ff8..55d54b770 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -398,8 +398,8 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are using Geom::X; using Geom::Y; - has_fill = _nrstyle.prepareFill( ct, _bbox); - has_stroke = _nrstyle.prepareStroke(ct, _bbox); + has_fill = _nrstyle.prepareFill( ct, _item_bbox); + has_stroke = _nrstyle.prepareStroke(ct, _item_bbox); if (has_fill || has_stroke) { Geom::Affine rotinv; diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp index f71bc82ef..55c1ee495 100644 --- a/src/display/guideline.cpp +++ b/src/display/guideline.cpp @@ -94,14 +94,20 @@ static void sp_guideline_destroy(SPCanvasItem *object) g_return_if_fail (SP_IS_GUIDELINE (object)); //g_return_if_fail (SP_GUIDELINE(object)->origin != NULL); //g_return_if_fail (SP_IS_CTRLPOINT(SP_GUIDELINE(object)->origin)); - - if (SP_GUIDELINE(object)->origin != NULL && SP_IS_CTRLPOINT(SP_GUIDELINE(object)->origin)) { - sp_canvas_item_destroy(SP_GUIDELINE(object)->origin); + + SPGuideLine *gl = SP_GUIDELINE(object); + + if (gl->origin != NULL && SP_IS_CTRLPOINT(gl->origin)) { + sp_canvas_item_destroy(gl->origin); } else { // FIXME: This branch shouldn't be reached (although it seems to be harmless). //g_error("Why can it be that gl->origin is not a valid SPCtrlPoint?\n"); } + if (gl->label) { + g_free(gl->label); + } + SP_CANVAS_ITEM_CLASS(parent_class)->destroy(object); } diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index c0044c5d8..af9c15cd8 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -114,14 +114,12 @@ int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, D Geom::Affine trans = item->ctm(); - // Get filter are, the filter_effect_area is already done in visualBounds - Geom::OptRect filter_area = item->filterBounds(); - // Use the geometricBounds as a backup solution + Geom::OptRect filter_area = filter_effect_area(item->itemBounds()); if (!filter_area) return 1; FilterUnits units(_filter_units, _primitive_units); units.set_ctm(trans); - units.set_item_bbox(filter_area); + units.set_item_bbox(item->itemBounds()); units.set_filter_area(*filter_area); std::pair<double,double> resolution @@ -201,7 +199,7 @@ void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item } Geom::Rect item_bbox; - Geom::OptRect maybe_bbox = item->geometricBounds(); + Geom::OptRect maybe_bbox = item->itemBounds(); if (maybe_bbox.isEmpty()) { // Code below needs a bounding box return; diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp index cd7e9575f..317f38635 100644 --- a/src/display/nr-style.cpp +++ b/src/display/nr-style.cpp @@ -77,6 +77,8 @@ NRStyle::~NRStyle() if (dash){ delete [] dash; } + fill.clear(); + stroke.clear(); } void NRStyle::set(SPStyle *style) diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp index 45dc38a37..3636319df 100644 --- a/src/display/sodipodi-ctrl.cpp +++ b/src/display/sodipodi-ctrl.cpp @@ -108,81 +108,50 @@ sp_ctrl_set_property(GObject *object, guint prop_id, const GValue *value, GParam ctrl = SP_CTRL (object); switch (prop_id) { - case ARG_SHAPE: { - ctrl->shape = (SPCtrlShapeType) g_value_get_int(value); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_MODE: { - ctrl->mode = (SPCtrlModeType) g_value_get_int(value); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_ANCHOR: { - ctrl->anchor = (SPAnchorType) g_value_get_int(value); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_SIZE: { - ctrl->span = (gint)((g_value_get_double(value) - 1.0) / 2.0 + 0.5); - ctrl->defined = (ctrl->span > 0); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_FILLED: { - ctrl->filled = g_value_get_boolean(value); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_FILL_COLOR: { - guint32 fill = g_value_get_int(value); - ctrl->fill_color = fill; - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_STROKED: { - ctrl->stroked = g_value_get_boolean(value); - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_STROKE_COLOR: { - guint32 stroke = g_value_get_int(value); - ctrl->stroke_color = stroke; - ctrl->build = FALSE; - sp_canvas_item_request_update(item); - } - break; - - case ARG_PIXBUF: { - pixbuf = (GdkPixbuf*) g_value_get_pointer(value); - if (gdk_pixbuf_get_has_alpha(pixbuf)) { - ctrl->pixbuf = pixbuf; - } else { - ctrl->pixbuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0); - g_object_unref(pixbuf); - } - ctrl->build = FALSE; - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; + case ARG_SHAPE: + ctrl->shape = (SPCtrlShapeType) g_value_get_int(value); + break; + case ARG_MODE: + ctrl->mode = (SPCtrlModeType) g_value_get_int(value); + break; + case ARG_ANCHOR: + ctrl->anchor = (SPAnchorType) g_value_get_int(value); + break; + case ARG_SIZE: + ctrl->width = (gint)(g_value_get_double(value) / 2.0); + ctrl->height = ctrl->width; + ctrl->defined = (ctrl->width > 0); + break; + case ARG_FILLED: + ctrl->filled = g_value_get_boolean(value); + break; + case ARG_FILL_COLOR: + ctrl->fill_color = (guint32)g_value_get_int(value); + break; + case ARG_STROKED: + ctrl->stroked = g_value_get_boolean(value); + break; + case ARG_STROKE_COLOR: + ctrl->stroke_color = (guint32)g_value_get_int(value); + break; + case ARG_PIXBUF: + pixbuf = (GdkPixbuf*) g_value_get_pointer(value); + // A pixbuf defines it's own size, don't mess about with size. + ctrl->width = gdk_pixbuf_get_width(pixbuf) / 2.0; + ctrl->height = gdk_pixbuf_get_height(pixbuf) / 2.0; + if (gdk_pixbuf_get_has_alpha(pixbuf)) { + ctrl->pixbuf = pixbuf; + } else { + ctrl->pixbuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0); + g_object_unref(pixbuf); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + return; // Do not do an update } + ctrl->build = FALSE; + sp_canvas_item_request_update(item); } static void @@ -206,7 +175,7 @@ sp_ctrl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec break; case ARG_SIZE: - g_value_set_double(value, ctrl->span); + g_value_set_double(value, ctrl->width); break; case ARG_FILLED: @@ -241,7 +210,8 @@ sp_ctrl_init (SPCtrl *ctrl) ctrl->shape = SP_CTRL_SHAPE_SQUARE; ctrl->mode = SP_CTRL_MODE_COLOR; ctrl->anchor = SP_ANCHOR_CENTER; - ctrl->span = 3; + ctrl->width = 3; + ctrl->height = 3; ctrl->defined = TRUE; ctrl->shown = FALSE; ctrl->build = FALSE; @@ -250,12 +220,6 @@ sp_ctrl_init (SPCtrl *ctrl) ctrl->fill_color = 0x000000ff; ctrl->stroke_color = 0x000000ff; - // This way we make sure that the first sp_ctrl_update() call finishes properly; - // in subsequent calls it will not update anything it the control hasn't moved - // Consider for example the case in which a snap indicator is drawn at (0, 0); - // If moveto() is called then it will not set _moved to true because we're initially already at (0, 0) - ctrl->_moved = true; // Is this flag ever going to be set back to false? I can't find where that is supposed to happen - new (&ctrl->box) Geom::IntRect(0,0,0,0); ctrl->cache = NULL; ctrl->pixbuf = NULL; @@ -292,16 +256,14 @@ sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int fla sp_canvas_item_reset_bounds (item); - if (!ctrl->_moved) return; - if (ctrl->shown) { item->canvas->requestRedraw(ctrl->box.left(), ctrl->box.top(), ctrl->box.right() + 1, ctrl->box.bottom() + 1); } if (!ctrl->defined) return; - x = (gint) ((affine[4] > 0) ? (affine[4] + 0.5) : (affine[4] - 0.5)) - ctrl->span; - y = (gint) ((affine[5] > 0) ? (affine[5] + 0.5) : (affine[5] - 0.5)) - ctrl->span; + x = (gint) ((affine[4] > 0) ? (affine[4] + 0.5) : (affine[4] - 0.5)) - ctrl->width; + y = (gint) ((affine[5] > 0) ? (affine[5] + 0.5) : (affine[5] - 0.5)) - ctrl->height; switch (ctrl->anchor) { case SP_ANCHOR_N: @@ -312,13 +274,13 @@ sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int fla case SP_ANCHOR_NW: case SP_ANCHOR_W: case SP_ANCHOR_SW: - x += ctrl->span; + x += ctrl->width; break; case SP_ANCHOR_NE: case SP_ANCHOR_E: case SP_ANCHOR_SE: - x -= (ctrl->span + 1); + x -= (ctrl->width + 1); break; } @@ -331,17 +293,17 @@ sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int fla case SP_ANCHOR_NW: case SP_ANCHOR_N: case SP_ANCHOR_NE: - y += ctrl->span; + y += ctrl->height; break; case SP_ANCHOR_SW: case SP_ANCHOR_S: case SP_ANCHOR_SE: - y -= (ctrl->span + 1); + y -= (ctrl->height + 1); break; } - ctrl->box = Geom::IntRect::from_xywh(x, y, 2*ctrl->span, 2*ctrl->span); + ctrl->box = Geom::IntRect::from_xywh(x, y, 2*ctrl->width, 2*ctrl->height); sp_canvas_update_bbox (item, ctrl->box.left(), ctrl->box.top(), ctrl->box.right() + 1, ctrl->box.bottom() + 1); } @@ -360,7 +322,7 @@ static void sp_ctrl_build_cache (SPCtrl *ctrl) { guint32 *p, *q; - gint size, x, y, z, s, a, side, c; + gint size, x, y, z, s, a, width, height, c; guint32 stroke_color, fill_color; if (ctrl->filled) { @@ -382,11 +344,11 @@ sp_ctrl_build_cache (SPCtrl *ctrl) stroke_color = fill_color; } - - side = (ctrl->span * 2 +1); - c = ctrl->span; - size = side * side; - if (side < 2) return; + width = (ctrl->width * 2 +1); + height = (ctrl->height * 2 +1); + c = ctrl->width; // Only used for pre-set square drawing + size = width * height; + if (width < 2) return; if (ctrl->cache) delete[] ctrl->cache; ctrl->cache = new guint32[size]; @@ -395,19 +357,19 @@ sp_ctrl_build_cache (SPCtrl *ctrl) case SP_CTRL_SHAPE_SQUARE: p = ctrl->cache; // top edge - for (x=0; x < side; x++) { + for (x=0; x < width; x++) { *p++ = stroke_color; } // middle - for (y = 2; y < side; y++) { + for (y = 2; y < height; y++) { *p++ = stroke_color; // stroke at first and last pixel - for (x=2; x < side; x++) { + for (x=2; x < width; x++) { *p++ = fill_color; // fill in the middle } *p++ = stroke_color; } // bottom edge - for (x=0; x < side; x++) { + for (x=0; x < width; x++) { *p++ = stroke_color; } ctrl->build = TRUE; @@ -415,19 +377,19 @@ sp_ctrl_build_cache (SPCtrl *ctrl) case SP_CTRL_SHAPE_DIAMOND: p = ctrl->cache; - for (y = 0; y < side; y++) { + for (y = 0; y < height; y++) { z = abs (c - y); for (x = 0; x < z; x++) { *p++ = 0; } *p++ = stroke_color; x++; - for (; x < side - z -1; x++) { + for (; x < width - z -1; x++) { *p++ = fill_color; } if (z != c) { *p++ = stroke_color; x++; } - for (; x < side; x++) { + for (; x < width; x++) { *p++ = 0; } } @@ -462,7 +424,7 @@ sp_ctrl_build_cache (SPCtrl *ctrl) *q-- = stroke_color; x++; } while (x <= c+z); - while (x < side) { + while (x < width) { *p++ = 0; *q-- = 0; x++; @@ -474,7 +436,7 @@ sp_ctrl_build_cache (SPCtrl *ctrl) case SP_CTRL_SHAPE_CROSS: p = ctrl->cache; - for (y = 0; y < side; y++) { + for (y = 0; y < height; y++) { z = abs (c - y); for (x = 0; x < c-z; x++) { *p++ = 0; @@ -486,7 +448,7 @@ sp_ctrl_build_cache (SPCtrl *ctrl) if (z != 0) { *p++ = stroke_color; x++; } - for (; x < side; x++) { + for (; x < width; x++) { *p++ = 0; } } @@ -499,12 +461,12 @@ sp_ctrl_build_cache (SPCtrl *ctrl) unsigned int rs; px = gdk_pixbuf_get_pixels (ctrl->pixbuf); rs = gdk_pixbuf_get_rowstride (ctrl->pixbuf); - for (y = 0; y < side; y++){ + for (y = 0; y < height; y++){ guint32 *d; unsigned char *s; s = px + y * rs; - d = ctrl->cache + side * y; - for (x = 0; x < side; x++) { + d = ctrl->cache + height * y; + for (x = 0; x < width; x++) { if (s[3] < 0x80) { *d++ = 0; } else if (s[0] < 0x80) { @@ -527,9 +489,9 @@ sp_ctrl_build_cache (SPCtrl *ctrl) guint32 *px; guchar *data = gdk_pixbuf_get_pixels (ctrl->pixbuf); p = ctrl->cache; - for (y = 0; y < side; y++){ + for (y = 0; y < height; y++){ px = reinterpret_cast<guint32*>(data + y * r); - for (x = 0; x < side; x++) { + for (x = 0; x < width; x++) { *p++ = *px++; } } @@ -566,8 +528,8 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf) sp_ctrl_build_cache (ctrl); } - int w, h; - w = h = (ctrl->span * 2 +1); + int w = (ctrl->width * 2 + 1); + int h = (ctrl->height * 2 + 1); // The code below works even when the target is not an image surface if (ctrl->mode == SP_CTRL_MODE_XOR) { @@ -627,7 +589,6 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf) void SPCtrl::moveto (Geom::Point const p) { if (p != _point) { sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), Geom::Affine(Geom::Translate (p))); - _moved = true; } _point = p; } diff --git a/src/display/sodipodi-ctrl.h b/src/display/sodipodi-ctrl.h index cd0fcadf1..ecdb896a7 100644 --- a/src/display/sodipodi-ctrl.h +++ b/src/display/sodipodi-ctrl.h @@ -37,7 +37,8 @@ struct SPCtrl : public SPCanvasItem { SPCtrlShapeType shape; SPCtrlModeType mode; SPAnchorType anchor; - gint span; + gint width; + gint height; guint defined : 1; guint shown : 1; guint build : 1; @@ -45,7 +46,6 @@ struct SPCtrl : public SPCanvasItem { guint stroked : 1; guint32 fill_color; guint32 stroke_color; - bool _moved; Geom::IntRect box; /* NB! x1 & y1 are included */ guint32 *cache; diff --git a/src/document.cpp b/src/document.cpp index 800f2f33d..b94b72bda 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -139,8 +139,6 @@ SPDocument::SPDocument() : } SPDocument::~SPDocument() { - collectOrphans(); - // kill/unhook this first if ( profileManager ) { delete profileManager; @@ -219,6 +217,14 @@ SPDocument::~SPDocument() { inkscape_unref(); keepalive = FALSE; } + + if (this->current_persp3d_impl) + delete this->current_persp3d_impl; + this->current_persp3d_impl = NULL; + + // This is at the end of the destructor, because preceding code adds new orphans to the queue + collectOrphans(); + //delete this->_whiteboard_session_manager; } diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 01f71f76a..f8980e218 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -954,9 +954,20 @@ void SPDynaDrawContext::set_to_accumulated(bool unionize, bool subtract) { } } - SPItem *item=SP_ITEM(desktop->doc()->getObjectByRepr(this->repr)); - item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + // Now we need to write the transform information. + // First, find out whether our repr is still linked to a valid object. In this case, + // we need to write the transform data only for this element. + // Either there was no boolean op or it failed. + SPItem *result = SP_ITEM(desktop->doc()->getObjectByRepr(this->repr)); + + if (result == NULL) { + // The boolean operation succeeded. + // Now we fetch the single item, that has been set as selected by the boolean op. + // This is its result. + result = desktop->getSelection()->singleItem(); + } + result->doWriteTransform(result->getRepr(), result->transform, NULL, true); } else { if (this->repr) { sp_repr_unparent(this->repr); diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index ccc39fbef..221a3e879 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -268,7 +268,7 @@ dbus_call_verb (DocumentInterface *doc_interface, int verbid, GError **error) if ( action ) { sp_action_perform( action, NULL ); if (doc_interface->updates) - Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), g_strdup(verb->get_tip())); + Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), verb->get_tip()); return TRUE; } } @@ -357,7 +357,7 @@ document_interface_call_verb (DocumentInterface *doc_interface, gchar *verbid, G if ( action ) { sp_action_perform( action, NULL ); if (doc_interface->updates) { - Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), g_strdup(verb->get_tip())); + Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), verb->get_tip()); } return TRUE; } diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index dcccf3d7d..1575c2b10 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -89,7 +89,7 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * } // children of "inkscape-extension" } // if we have an XML file - if (INKSCAPE != NULL) { + if (INKSCAPE != NULL && inkscape_use_gui()) { if (_effects_list == NULL) _effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST); if (_filters_list == NULL) diff --git a/src/extension/init.cpp b/src/extension/init.cpp index 2dde9eeb8..0ff4b79c4 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -109,8 +109,6 @@ #include "init.h" -extern gboolean inkscape_app_use_gui( Inkscape::Application const *app ); - namespace Inkscape { namespace Extension { diff --git a/src/extension/internal/metafile-print.h b/src/extension/internal/metafile-print.h index cba4d564d..a21f9de58 100644 --- a/src/extension/internal/metafile-print.h +++ b/src/extension/internal/metafile-print.h @@ -26,8 +26,8 @@ #include "splivarot.h" #include "display/canvas-bpath.h" -struct SPGradient; -struct SPObject; +class SPGradient; +class SPObject; namespace Inkscape { class Pixbuf; diff --git a/src/inkscape.cpp b/src/inkscape.cpp index e1cabd2d5..228841362 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -502,7 +502,7 @@ inkscape_init (SPObject * object) new (&inkscape->document_set) std::map<SPDocument *, int>(); new (&inkscape->selection_models) std::map<SPDocument *, AppSelectionModel *>(); - inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL); + inkscape->menus = NULL; inkscape->desktops = NULL; inkscape->dialogs_toggle = TRUE; inkscape->mapalt = GDK_MOD1_MASK; @@ -1483,7 +1483,9 @@ profile_path(const char *filename) } if (prefdir) { - prefdir = g_build_filename(prefdir, INKSCAPE_PROFILE_DIR, NULL); + const char *prefdir_profile = g_build_filename(prefdir, INKSCAPE_PROFILE_DIR, NULL); + g_free((void *)prefdir); + prefdir = prefdir_profile; } } #endif diff --git a/src/knot.cpp b/src/knot.cpp index 890abd0a1..2b67440dc 100644 --- a/src/knot.cpp +++ b/src/knot.cpp @@ -646,34 +646,14 @@ void sp_knot_update_ctrl(SPKnot *knot) */ static void sp_knot_set_ctrl_state(SPKnot *knot) { + int state = SP_KNOT_STATE_NORMAL; if (knot->flags & SP_KNOT_DRAGGING) { - g_object_set(knot->item, - "fill_color", - knot->fill[SP_KNOT_STATE_DRAGGING], - NULL); - g_object_set(knot->item, - "stroke_color", - knot->stroke[SP_KNOT_STATE_DRAGGING], - NULL); + state = SP_KNOT_STATE_DRAGGING; } else if (knot->flags & SP_KNOT_MOUSEOVER) { - g_object_set(knot->item, - "fill_color", - knot->fill[SP_KNOT_STATE_MOUSEOVER], - NULL); - g_object_set(knot->item, - "stroke_color", - knot->stroke[SP_KNOT_STATE_MOUSEOVER], - NULL); - } else { - g_object_set(knot->item, - "fill_color", - knot->fill[SP_KNOT_STATE_NORMAL], - NULL); - g_object_set(knot->item, - "stroke_color", - knot->stroke[SP_KNOT_STATE_NORMAL], - NULL); + state = SP_KNOT_STATE_MOUSEOVER; } + g_object_set(knot->item, "fill_color", knot->fill[state], NULL); + g_object_set(knot->item, "stroke_color", knot->stroke[state], NULL); } diff --git a/src/libavoid/vertices.h b/src/libavoid/vertices.h index b07c87f95..619692c23 100644 --- a/src/libavoid/vertices.h +++ b/src/libavoid/vertices.h @@ -129,7 +129,7 @@ class VertInfList unsigned int shapesSize(void) const; void stats(FILE *fp = stderr) { - fprintf(fp, "Conns %d, shapes %d\n", _connVertices, + fprintf(fp, "Conns %u, shapes %u\n", _connVertices, _shapeVertices); } private: diff --git a/src/libcola/connected_components.cpp b/src/libcola/connected_components.cpp index 1afec55b4..823f7cf6e 100644 --- a/src/libcola/connected_components.cpp +++ b/src/libcola/connected_components.cpp @@ -77,7 +77,7 @@ namespace cola { } vector<Edge>::const_iterator ei; SimpleConstraints::const_iterator ci; - for(ei=es.begin();ei!=es.end();ei++) { + for(ei=es.begin();ei!=es.end();++ei) { vs[ei->first].neighbours.push_back(&vs[ei->second]); vs[ei->second].neighbours.push_back(&vs[ei->first]); } @@ -88,13 +88,13 @@ namespace cola { dfs(v,remaining,component,cmap); components.push_back(component); } - for(ei=es.begin();ei!=es.end();ei++) { + for(ei=es.begin();ei!=es.end();++ei) { pair<Component*,unsigned> u=cmap[ei->first], v=cmap[ei->second]; assert(u.first==v.first); u.first->edges.push_back(make_pair(u.second,v.second)); } - for(ci=scx.begin();ci!=scx.end();ci++) { + for(ci=scx.begin();ci!=scx.end();++ci) { SimpleConstraint *c=*ci; pair<Component*,unsigned> u=cmap[c->left], v=cmap[c->right]; @@ -102,7 +102,7 @@ namespace cola { u.first->scx.push_back( new SimpleConstraint(u.second,v.second,c->gap)); } - for(ci=scy.begin();ci!=scy.end();ci++) { + for(ci=scy.begin();ci!=scy.end();++ci) { SimpleConstraint *c=*ci; pair<Component*,unsigned> u=cmap[c->left], v=cmap[c->right]; diff --git a/src/libcola/cycle_detector.cpp b/src/libcola/cycle_detector.cpp index 89a2ccaae..11e24a0ba 100644 --- a/src/libcola/cycle_detector.cpp +++ b/src/libcola/cycle_detector.cpp @@ -53,7 +53,7 @@ void CycleDetector::make_matrix() { assert(traverse.empty()); // from the edges passed, fill the adjacency matrix - for (ei = edges->begin(); ei != edges->end(); ei++) { + for (ei = edges->begin(); ei != edges->end(); ++ei) { anEdge = *ei; // the matrix is indexed by the first vertex of the edge // the second vertex of the edge is pushed onto another @@ -241,7 +241,7 @@ bool CycleDetector::find_node(std::vector<Node *> *& list, unsigned k) { } pair< bool, vector<unsigned>::iterator > CycleDetector::find_node(std::vector<unsigned>& list, unsigned k) { - for (vector<unsigned>::iterator ti = traverse.begin(); ti != traverse.end(); ti++) { + for (vector<unsigned>::iterator ti = traverse.begin(); ti != traverse.end(); ++ti) { if (*ti == k) { return pair< bool, vector<unsigned>::iterator >(true, ti); } } diff --git a/src/libcola/gradient_projection.cpp b/src/libcola/gradient_projection.cpp index 47109a4b0..3e41aceac 100644 --- a/src/libcola/gradient_projection.cpp +++ b/src/libcola/gradient_projection.cpp @@ -222,7 +222,7 @@ void GradientProjection::destroyVPSC(IncSolver *vpsc) { delete vpsc; delete [] cs; delete [] vs; - for(vector<Constraint*>::iterator i=lcs.begin();i!=lcs.end();i++) { + for(vector<Constraint*>::iterator i=lcs.begin();i!=lcs.end();++i) { delete *i; } lcs.clear(); diff --git a/src/libcola/straightener.cpp b/src/libcola/straightener.cpp index 650f41aac..fab30d48d 100644 --- a/src/libcola/straightener.cpp +++ b/src/libcola/straightener.cpp @@ -90,7 +90,7 @@ namespace straightener { ds.erase(copyit); } } - for(set<pair<double,unsigned> >::iterator j=pntsOnLineSegment.begin();j!=pntsOnLineSegment.end();j++) { + for(set<pair<double,unsigned> >::iterator j=pntsOnLineSegment.begin();j!=pntsOnLineSegment.end();++j) { path.push_back(j->second); } //printf("\n"); @@ -144,11 +144,11 @@ namespace straightener { e->ypos(conjpos,bs); } //cerr << "edge(intersections="<<bs.size()<<":("<<e->startNode<<","<<e->endNode<<"))"<<endl; - for(vector<double>::iterator it=bs.begin();it!=bs.end();it++) { + for(vector<double>::iterator it=bs.begin();it!=bs.end();++it) { sortedEdges.insert(make_pair(*it,e)); } } - for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) { + for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();++i) { double pos=i->first; if(pos < minpos) continue; if(pos > v->scanpos) break; @@ -169,7 +169,7 @@ namespace straightener { if(r!=NULL) { maxpos=r->scanpos; } - for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) { + for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();++i) { if(i->first < v->scanpos) continue; if(i->first > maxpos) break; double pos=i->first; @@ -262,7 +262,7 @@ namespace straightener { // Case A: create constraints between adjacent edges skipping edges joined // to l,v or r. Node* lastNode=NULL; - for(vector<Node*>::iterator i=L.begin();i!=L.end();i++) { + for(vector<Node*>::iterator i=L.begin();i!=L.end();++i) { if((*i)->dummy) { // node is on an edge Edge *edge=(*i)->edge; @@ -284,7 +284,7 @@ namespace straightener { // their own end, also in the scan line vector<Node*> skipList; lastNode=NULL; - for(vector<Node*>::iterator i=L.begin();i!=L.end();i++) { + for(vector<Node*>::iterator i=L.begin();i!=L.end();++i) { if((*i)->dummy) { // node is on an edge if(lastNode!=NULL) { @@ -292,7 +292,7 @@ namespace straightener { skipList.push_back(*i); } else { for(vector<Node*>::iterator j=skipList.begin(); - j!=skipList.end();j++) { + j!=skipList.end();++j) { //printf(" Rule B: Constraint: v%d +g <= v%d\n",(*j)->id,(*i)->id); cs.push_back(createConstraint(*j,*i,dim)); } @@ -309,7 +309,7 @@ namespace straightener { skipList.clear(); // Case C: reverse of B lastNode=NULL; - for(vector<Node*>::reverse_iterator i=L.rbegin();i!=L.rend();i++) { + for(vector<Node*>::reverse_iterator i=L.rbegin();i!=L.rend();++i) { if((*i)->dummy) { // node is on an edge if(lastNode!=NULL) { @@ -317,7 +317,7 @@ namespace straightener { skipList.push_back(*i); } else { for(vector<Node*>::iterator j=skipList.begin(); - j!=skipList.end();j++) { + j!=skipList.end();++j) { //printf(" Rule C: Constraint: v%d +g <= v%d\n",(*i)->id,(*j)->id); cs.push_back(createConstraint(*i,*j,dim)); } diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index c896cc470..9fc553efd 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -25,7 +25,6 @@ typedef INK_UNORDERED_MAP<PangoFontDescription*, font_instance*, font_descr_hash // need to avoid using the size field size_t font_descr_hash::operator()( PangoFontDescription *const &x) const { int h = 0; - h *= 1128467; char const *theF = sp_font_description_get_family(x); h += (theF)?g_str_hash(theF):0; h *= 1128467; @@ -295,7 +294,7 @@ font_factory *font_factory::Default(void) } font_factory::font_factory(void) : - nbEnt(0), + nbEnt(0), // Note: this "ents" cache only keeps fonts from being unreffed, does not speed up access maxEnt(32), ents(static_cast<font_entry*>(g_malloc(maxEnt*sizeof(font_entry)))), @@ -327,12 +326,6 @@ font_factory::font_factory(void) : font_factory::~font_factory(void) { - if (loadedPtr) { - FaceMapType* tmp = static_cast<FaceMapType*>(loadedPtr); - delete tmp; - loadedPtr = 0; - } - for (int i = 0;i < nbEnt;i++) ents[i].f->Unref(); if ( ents ) g_free(ents); @@ -344,6 +337,12 @@ font_factory::~font_factory(void) #endif //g_object_unref(fontContext); + if (loadedPtr) { + FaceMapType* tmp = static_cast<FaceMapType*>(loadedPtr); + delete tmp; + loadedPtr = 0; + } + // Delete the pango font pointers in the string to instance map PangoStringToDescrMap::iterator it = fontInstanceMap.begin(); while (it != fontInstanceMap.end()) { @@ -1126,7 +1125,7 @@ void font_factory::AddInCache(font_instance *who) return; } who->Ref(); - if ( nbEnt == maxEnt ) { + if ( nbEnt == maxEnt ) { // cache is filled, unref the oldest-accessed font in it int bi = 0; double ba = ents[bi].age; for (int i = 1;i < nbEnt;i++) { diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index fd0cdd3d4..38a105459 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -192,6 +192,7 @@ font_instance::~font_instance(void) //printf("font instance death\n"); if ( pFont ) { + FreeTheFace(); g_object_unref(pFont); pFont = 0; } @@ -232,10 +233,6 @@ void font_instance::Unref(void) //printf("font %x %s unref'd %i\n",this,tc,refCount); //free(tc); if ( refCount <= 0 ) { - if ( daddy ) { - daddy->UnrefFace(this); - } - daddy=NULL; delete this; } } @@ -387,6 +384,7 @@ unsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int void font_instance::InitTheFace() { + if (theFace == NULL && pFont != NULL) { #ifdef USE_PANGO_WIN32 if ( !theFace ) { LOGFONT *lf=pango_win32_font_logfont(pFont); @@ -404,6 +402,7 @@ void font_instance::InitTheFace() FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol); } #endif + } } void font_instance::FreeTheFace() @@ -423,6 +422,7 @@ void font_instance::InstallFace(PangoFont* iFace) return; } pFont=iFace; + iFace = NULL; InitTheFace(); diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 7ea089c93..973db0165 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -980,6 +980,7 @@ void Layout::Calculator::_buildPangoItemizationForPara(ParagraphInfo *para) con attribute_font_description->end_index = para_text.bytes(); pango_attr_list_insert(attributes_list, attribute_font_description); // ownership of attribute is assumed by the list + font->Unref(); } } diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 1989c495a..bdc786749 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -181,6 +181,7 @@ void Layout::show(DrawingGroup *in_arena, Geom::OptRect const &paintbox) const glyph_index++; } nr_text->setStyle(text_source->style); + nr_text->setItemBounds(paintbox); in_arena->prependChild(nr_text); // Set item bounds without filter enlargement in_arena->setItemBounds(paintbox); diff --git a/src/measure-context.cpp b/src/measure-context.cpp index 8db703205..7570e36e7 100644 --- a/src/measure-context.cpp +++ b/src/measure-context.cpp @@ -48,10 +48,6 @@ using Inkscape::ControlManager; using Inkscape::CTLINE_SECONDARY; using Inkscape::Util::unit_table; -Geom::Point start_point; -boost::optional<Geom::Point> explicitBase; -boost::optional<Geom::Point> lastEnd; - std::vector<Inkscape::Display::TemporaryItem*> measure_tmp_items; diff --git a/src/measure-context.h b/src/measure-context.h index e42265045..7d5a88ab7 100644 --- a/src/measure-context.h +++ b/src/measure-context.h @@ -13,6 +13,8 @@ */ #include "event-context.h" +#include <2geom/point.h> +#include <boost/optional.hpp> #define SP_MEASURE_CONTEXT(obj) (dynamic_cast<SPMeasureContext*>((SPEventContext*)obj)) #define SP_IS_MEASURE_CONTEXT(obj) (dynamic_cast<const SPMeasureContext*>((const SPEventContext*)obj) != NULL) @@ -31,6 +33,10 @@ public: private: SPCanvasItem* grabbed; + + Geom::Point start_point; + boost::optional<Geom::Point> explicitBase; + boost::optional<Geom::Point> lastEnd; }; #endif // SEEN_SP_MEASURING_CONTEXT_H diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 2334a08c1..3fcb77207 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -285,6 +285,7 @@ static char const menus_skeleton[] = " <verb verb-id=\"TutorialsShapes\" />\n" " <verb verb-id=\"TutorialsAdvanced\" />\n" " <verb verb-id=\"TutorialsTracing\" />\n" +" <verb verb-id=\"TutorialsTracingPixelArt\" />\n" " <verb verb-id=\"TutorialsCalligraphy\" />\n" " <verb verb-id=\"TutorialsInterpolate\" />\n" " <verb verb-id=\"TutorialsDesign\" />\n" diff --git a/src/number-opt-number.h b/src/number-opt-number.h index 867d0535f..d9ab56102 100644 --- a/src/number-opt-number.h +++ b/src/number-opt-number.h @@ -120,6 +120,8 @@ public: _set = FALSE; optNumber_set = FALSE; } + + g_strfreev(values); } }; diff --git a/src/object-edit.cpp b/src/object-edit.cpp index 25bc62a7f..28786bf66 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -785,24 +785,23 @@ sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p) void ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); + int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12); - SPGenericEllipse *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); - ge->closed = (sp_genericellipse_side(ge, p) == -1) ? TRUE : FALSE; + arc->setClosed(sp_genericellipse_side(arc, p) == -1); - Geom::Point delta = p - Geom::Point(ge->cx.computed, ge->cy.computed); - Geom::Scale sc(ge->rx.computed, ge->ry.computed); - ge->start = atan2(delta * sc.inverse()); - if ( ( state & GDK_CONTROL_MASK ) - && snaps ) - { - ge->start = sp_round(ge->start, M_PI/snaps); + Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed); + Geom::Scale sc(arc->rx.computed, arc->ry.computed); + + arc->start = atan2(delta * sc.inverse()); + + if ((state & GDK_CONTROL_MASK) && snaps) { + arc->start = sp_round(arc->start, M_PI / snaps); } - sp_genericellipse_normalize(ge); - (static_cast<SPObject *>(arc))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + + arc->normalize(); + arc->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } Geom::Point @@ -811,7 +810,7 @@ ArcKnotHolderEntityStart::knot_get() const SPGenericEllipse const *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); - return sp_arc_get_xy(arc, ge->start); + return arc->getPointAtAngle(ge->start); } void @@ -828,24 +827,23 @@ ArcKnotHolderEntityStart::knot_click(guint state) void ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); + int snaps = Inkscape::Preferences::get()->getInt("/options/rotationsnapsperpi/value", 12); - SPGenericEllipse *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); - ge->closed = (sp_genericellipse_side(ge, p) == -1) ? TRUE : FALSE; + arc->setClosed(sp_genericellipse_side(arc, p) == -1); - Geom::Point delta = p - Geom::Point(ge->cx.computed, ge->cy.computed); - Geom::Scale sc(ge->rx.computed, ge->ry.computed); - ge->end = atan2(delta * sc.inverse()); - if ( ( state & GDK_CONTROL_MASK ) - && snaps ) - { - ge->end = sp_round(ge->end, M_PI/snaps); + Geom::Point delta = p - Geom::Point(arc->cx.computed, arc->cy.computed); + Geom::Scale sc(arc->rx.computed, arc->ry.computed); + + arc->end = atan2(delta * sc.inverse()); + + if ((state & GDK_CONTROL_MASK) && snaps) { + arc->end = sp_round(arc->end, M_PI/snaps); } - sp_genericellipse_normalize(ge); - (static_cast<SPObject *>(arc))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + + arc->normalize(); + arc->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } Geom::Point @@ -854,7 +852,7 @@ ArcKnotHolderEntityEnd::knot_get() const SPGenericEllipse const *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); - return sp_arc_get_xy(arc, ge->end); + return arc->getPointAtAngle(ge->end); } diff --git a/src/proj_pt.cpp b/src/proj_pt.cpp index d9d4e06f1..28286948d 100644 --- a/src/proj_pt.cpp +++ b/src/proj_pt.cpp @@ -34,6 +34,7 @@ Pt2::Pt2(const gchar *coord_str) { pt[0] = g_ascii_strtod(coords[0], NULL); pt[1] = g_ascii_strtod(coords[1], NULL); pt[2] = g_ascii_strtod(coords[2], NULL); + g_strfreev (coords); } void diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index c22ed777b..2105ca99a 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2512,7 +2512,9 @@ void sp_selection_clone(SPDesktop *desktop) Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); clone->setAttribute("x", "0", false); clone->setAttribute("y", "0", false); - clone->setAttribute("xlink:href", g_strdup_printf("#%s", sel_repr->attribute("id")), false); + gchar *href_str = g_strdup_printf("#%s", sel_repr->attribute("id")); + clone->setAttribute("xlink:href", href_str, false); + g_free(href_str); clone->setAttribute("inkscape:transform-center-x", sel_repr->attribute("inkscape:transform-center-x"), false); clone->setAttribute("inkscape:transform-center-y", sel_repr->attribute("inkscape:transform-center-y"), false); @@ -2993,7 +2995,9 @@ void sp_selection_symbol(SPDocument *doc, SPObject *group) Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); clone->setAttribute("x", "0", false); clone->setAttribute("y", "0", false); - clone->setAttribute("xlink:href", g_strdup_printf("#%s", id.c_str()), false); + gchar *href_str = g_strdup_printf("#%s", id.c_str()); + clone->setAttribute("xlink:href", href_str, false); + g_free(href_str); clone->setAttribute("inkscape:transform-center-x", group->getAttribute("inkscape:transform-center-x"), false); clone->setAttribute("inkscape:transform-center-y", group->getAttribute("inkscape:transform-center-y"), false); @@ -3153,7 +3157,9 @@ sp_selection_tile(SPDesktop *desktop, bool apply) if (apply) { Inkscape::XML::Node *rect = xml_doc->createElement("svg:rect"); - rect->setAttribute("style", g_strdup_printf("stroke:none;fill:url(#%s)", pat_id)); + gchar *style_str = g_strdup_printf("stroke:none;fill:url(#%s)", pat_id); + rect->setAttribute("style", style_str); + g_free(style_str); Geom::Point min = bbox.min() * parent_transform.inverse(); Geom::Point max = bbox.max() * parent_transform.inverse(); @@ -3719,7 +3725,9 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ Inkscape::GC::release(group); } - apply_mask_to->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id)); + gchar *value_str = g_strdup_printf("url(#%s)", mask_id); + apply_mask_to->setAttribute(attributeName, value_str); + g_free(value_str); } diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index fc78b9777..80e57afc3 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -24,6 +24,8 @@ #include "style.h" #include "display/curve.h" #include <glibmm/i18n.h> +#include <2geom/angle.h> +#include <2geom/ellipse.h> #include <2geom/transforms.h> #include <2geom/pathvector.h> #include <2geom/svg-path.h> @@ -32,29 +34,27 @@ #include "preferences.h" #include "snap-candidate.h" -/* Common parent class */ - -#define noELLIPSE_VERBOSE - - #include "sp-factory.h" namespace { - SPObject* createEllipse() { - return new SPEllipse(); - } +SPObject *create_ellipse() +{ + return new SPEllipse(); +} - SPObject* createCircle() { - return new SPCircle(); - } +SPObject *create_circle() +{ + return new SPCircle(); +} - SPObject* createArc() { - return new SPArc(); - } +SPObject *create_arc() +{ + return new SPArc(); +} - bool ellipseRegistered = SPFactory::instance().registerObject("svg:ellipse", createEllipse); - bool circleRegistered = SPFactory::instance().registerObject("svg:circle", createCircle); - bool arcRegistered = SPFactory::instance().registerObject("arc", createArc); +bool ellipse_registered = SPFactory::instance().registerObject("svg:ellipse", create_ellipse); +bool circle_registered = SPFactory::instance().registerObject("svg:circle", create_circle); +bool arc_registered = SPFactory::instance().registerObject("arc", create_arc); } @@ -64,52 +64,34 @@ namespace { #define SP_2PI (2 * M_PI) -#if 1 -/* Hmmm... shouldn't this also qualify */ -/* Whether it is faster or not, well, nobody knows */ -#define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m))) -#else -/* we do not use C99 round(3) function yet */ -static double sp_round(double x, double y) +SPGenericEllipse::SPGenericEllipse() + : SPShape() + , start(0) + , end(SP_2PI) + , _closed(true) { - double remain; - - g_assert(y > 0.0); - - /* return round(x/y) * y; */ - - remain = fmod(x, y); - - if (remain >= 0.5*y) - return x - remain + y; - else - return x - remain; } -#endif - -static gboolean sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr); -SPGenericEllipse::SPGenericEllipse() : SPShape() { - this->cx.unset(); - this->cy.unset(); - this->rx.unset(); - this->ry.unset(); +SPGenericEllipse::~SPGenericEllipse() +{ +} - this->start = 0.0; - this->end = SP_2PI; - this->closed = TRUE; +bool SPGenericEllipse::closed() { + return _closed; } -SPGenericEllipse::~SPGenericEllipse() { +void SPGenericEllipse::setClosed(bool value) { + _closed = value; } -void SPGenericEllipse::update(SPCtx *ctx, guint flags) { +void SPGenericEllipse::update(SPCtx *ctx, guint flags) +{ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { Geom::Rect const &viewbox = ((SPItemCtx const *) ctx)->viewport; double const dx = viewbox.width(); double const dy = viewbox.height(); - double const dr = sqrt(dx*dx + dy*dy)/sqrt(2); + double const dr = hypot(dx, dy) / sqrt(2); double const em = this->style->font_size.computed; double const ex = em * 0.5; // fixme: get from pango or libnrtype @@ -124,13 +106,14 @@ void SPGenericEllipse::update(SPCtx *ctx, guint flags) { SPShape::update(ctx, flags); } -void SPGenericEllipse::update_patheffect(bool write) { +void SPGenericEllipse::update_patheffect(bool write) +{ this->set_shape(); if (write) { Inkscape::XML::Node *repr = this->getRepr(); - if ( this->_curve != NULL ) { + if (this->_curve != NULL) { gchar *str = sp_svg_write_path(this->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); @@ -142,64 +125,49 @@ void SPGenericEllipse::update_patheffect(bool write) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -#include <2geom/ellipse.h> +bool SPGenericEllipse::_isSlice() const +{ + Geom::AngleInterval a(this->start, this->end, true); -/* fixme: Think (Lauris) */ -/* Can't we use arcto in this method? */ -void SPGenericEllipse::set_shape() { + return !(Geom::are_near(a.extent(), 0) || Geom::are_near(a.extent(), SP_2PI)); +} + +void SPGenericEllipse::set_shape() +{ if (hasBrokenPathEffect()) { - g_warning ("The ellipse shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as ellipse will remove the bad LPE"); + g_warning("The ellipse shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as ellipse will remove the bad LPE"); if (this->getRepr()->attribute("d")) { // unconditionally read the curve from d, if any, to preserve appearance Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d")); SPCurve *cold = new SPCurve(pv); - this->setCurveInsync( cold, TRUE); + this->setCurveInsync(cold, TRUE); cold->unref(); } return; } - if ((this->rx.computed < 1e-18) || (this->ry.computed < 1e-18)) { - return; - } - - if (fabs(this->end - this->start) < 1e-9) { - return; - } - - sp_genericellipse_normalize(this); - - // figure out if we have a slice, guarding against rounding errors - double len = fmod(this->end - this->start, SP_2PI); - - if (len < 0.0) { - len += SP_2PI; + if (Geom::are_near(this->rx.computed, 0) || Geom::are_near(this->ry.computed, 0)) { + return; } - bool slice = false; - - if (fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8) { - slice = false; - this->end = this->start + SP_2PI; - } else { - slice = true; - } + this->normalize(); SPCurve *curve = NULL; // For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations. - if (slice) { - Geom::Point startPoint(cos(start), sin(start)); - Geom::Point endPoint(cos(end), sin(end)); - Geom::Point middlePoint = make_angle_bisector_ray(Geom::Ray(Geom::Point(), start), Geom::Ray(Geom::Point(), end)).versor(); + if (this->_isSlice()) { + Geom::Point center(0, 0); + Geom::Point start_point = Geom::Point::polar(start); + Geom::Point end_point = Geom::Point::polar(end); + Geom::Point middle_point = make_angle_bisector_ray(Geom::Ray(center, start), Geom::Ray(center, end)).versor(); Geom::Ellipse ellipse(0, 0, 1, 1, 0); - Geom::EllipticalArc *arc = ellipse.arc(startPoint, middlePoint, endPoint); + Geom::EllipticalArc *arc = ellipse.arc(start_point, middle_point, end_point); - Geom::Path path(startPoint); + Geom::Path path(start_point); path.append(*arc); delete arc; @@ -207,9 +175,9 @@ void SPGenericEllipse::set_shape() { Geom::PathBuilder pb; pb.append(path); - if (this->closed) { + if (this->_closed) { // "pizza slice" - pb.lineTo(Geom::Point(0, 0)); + pb.lineTo(center); pb.closePath(); } else { // arc only @@ -234,7 +202,7 @@ void SPGenericEllipse::set_shape() { /* Reset the shape's curve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ - this->setCurveInsync( curve, TRUE); + this->setCurveInsync(curve, TRUE); this->setCurveBeforeLPE(curve); if (hasPathEffect() && sp_lpe_item_path_effects_enabled(this)) { @@ -242,7 +210,7 @@ void SPGenericEllipse::set_shape() { bool success = sp_lpe_item_perform_path_effect(this, c_lpe); if (success) { - this->setCurveInsync( c_lpe, TRUE); + this->setCurveInsync(c_lpe, TRUE); } c_lpe->unref(); @@ -251,70 +219,49 @@ void SPGenericEllipse::set_shape() { curve->unref(); } -void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) { - sp_genericellipse_normalize(this); +void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) +{ + this->normalize(); Geom::Affine const i2dt = this->i2dt_affine(); - // figure out if we have a slice, while guarding against rounding errors - bool slice = false; - double len = fmod(this->end - this->start, SP_2PI); - - if (len < 0.0) { - len += SP_2PI; - } - - if (fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8) { - slice = false; - this->end = this->start + SP_2PI; - } else { - slice = true; - } - - double rx = this->rx.computed; - double ry = this->ry.computed; - double cx = this->cx.computed; - double cy = this->cy.computed; - - // Snap to the 4 quadrant points of the this, but only if the arc + // Snap to the 4 quadrant points of the ellipse, but only if the arc // spans far enough to include them if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_ELLIPSE_QUADRANT_POINT)) { - double angle = 0; - - for (angle = 0; angle < SP_2PI; angle += M_PI_2) { - if (angle >= this->start && angle <= this->end) { - Geom::Point pt = Geom::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2dt; + for (double angle = 0; angle < SP_2PI; angle += M_PI_2) { + if (Geom::AngleInterval(this->start, this->end, true).contains(angle)) { + Geom::Point pt = this->getPointAtAngle(angle) * i2dt; p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ELLIPSE_QUADRANT_POINT, Inkscape::SNAPTARGET_ELLIPSE_QUADRANT_POINT)); } } } - // Add the centre, if we have a closed slice or when explicitly asked for - bool c1 = snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_NODE_CUSP) && slice && this->closed; - bool c2 = snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_OBJECT_MIDPOINT); + double cx = this->cx.computed; + double cy = this->cy.computed; - if (c1 || c2) { - Geom::Point pt = Geom::Point(cx, cy) * i2dt; + bool slice = this->_isSlice(); - if (c1) { - p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); - } + // Add the centre, if we have a closed slice or when explicitly asked for + if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_NODE_CUSP) && slice && this->_closed) { + Geom::Point pt = Geom::Point(cx, cy) * i2dt; + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + } - if (c2) { - p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); - } + if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_OBJECT_MIDPOINT)) { + Geom::Point pt = Geom::Point(cx, cy) * i2dt; + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); } // And if we have a slice, also snap to the endpoints if (snapprefs->isTargetSnappable(Inkscape::SNAPTARGET_NODE_CUSP) && slice) { // Add the start point, if it's not coincident with a quadrant point - if (fmod(this->start, M_PI_2) != 0.0 ) { - Geom::Point pt = Geom::Point(cx + cos(this->start)*rx, cy + sin(this->start)*ry) * i2dt; + if (!Geom::are_near(std::fmod(this->start, M_PI_2), 0)) { + Geom::Point pt = this->getPointAtAngle(this->start) * i2dt; p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } // Add the end point, if it's not coincident with a quadrant point - if (fmod(this->end, M_PI_2) != 0.0 ) { - Geom::Point pt = Geom::Point(cx + cos(this->end)*rx, cy + sin(this->end)*ry) * i2dt; + if (!Geom::are_near(std::fmod(this->end, M_PI_2), 0)) { + Geom::Point pt = this->getPointAtAngle(this->end) * i2dt; p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } } @@ -323,13 +270,14 @@ void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) { /* Calculate ellipse start in parent coords. */ - Geom::Point pos( Geom::Point(this->cx.computed, this->cy.computed) * xform ); + Geom::Point pos(Geom::Point(this->cx.computed, this->cy.computed) * xform); /* This function takes care of translation and scaling, we return whatever parts we can't handle. */ Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); gdouble const sw = hypot(ret[0], ret[1]); gdouble const sh = hypot(ret[2], ret[3]); + if (sw > 1e-9) { ret[0] /= sw; ret[1] /= sw; @@ -337,6 +285,7 @@ Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) ret[0] = 1.0; ret[1] = 0.0; } + if (sh > 1e-9) { ret[2] /= sh; ret[3] /= sh; @@ -348,6 +297,7 @@ Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) if (this->rx._set) { this->rx = this->rx.computed * sw; } + if (this->ry._set) { this->ry = this->ry.computed * sh; } @@ -373,26 +323,16 @@ Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) return ret; } -void -sp_genericellipse_normalize(SPGenericEllipse *ellipse) +void SPGenericEllipse::normalize() { - ellipse->start = fmod(ellipse->start, SP_2PI); - ellipse->end = fmod(ellipse->end, SP_2PI); + Geom::AngleInterval a(this->start, this->end, true); - if (ellipse->start < 0.0) { - ellipse->start += SP_2PI; - } - - double diff = ellipse->start - ellipse->end; - - if (diff >= 0.0) { - ellipse->end += diff - fmod(diff, SP_2PI) + SP_2PI; - } - - /* Now we keep: 0 <= start < end <= 2*PI */ + this->start = a.initialAngle().radians0(); + this->end = a.finalAngle().radians0(); } -Inkscape::XML::Node* SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { +Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ if (flags & SP_OBJECT_WRITE_EXT) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:path"); @@ -404,7 +344,7 @@ Inkscape::XML::Node* SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I sp_repr_set_svg_double(repr, "sodipodi:ry", this->ry.computed); if (SP_IS_ARC(this)) { - sp_arc_set_elliptical_path_attribute(SP_ARC(this), this->getRepr()); + SP_ARC(this)->sp_arc_set_elliptical_path_attribute(this->getRepr()); } } @@ -416,23 +356,27 @@ Inkscape::XML::Node* SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, I } /* SVG <ellipse> element */ -SPEllipse::SPEllipse() : SPGenericEllipse() { +SPEllipse::SPEllipse() : SPGenericEllipse() +{ } -SPEllipse::~SPEllipse() { +SPEllipse::~SPEllipse() +{ } -void SPEllipse::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPGenericEllipse::build(document, repr); +void SPEllipse::build(SPDocument *document, Inkscape::XML::Node *repr) +{ + SPGenericEllipse::build(document, repr); - this->readAttr( "cx" ); - this->readAttr( "cy" ); - this->readAttr( "rx" ); - this->readAttr( "ry" ); + this->readAttr("cx"); + this->readAttr("cy"); + this->readAttr("rx"); + this->readAttr("ry"); } -Inkscape::XML::Node* SPEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { +Inkscape::XML::Node *SPEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:ellipse"); } @@ -448,80 +392,68 @@ Inkscape::XML::Node* SPEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape } -void SPEllipse::set(unsigned int key, gchar const* value) { +void SPEllipse::set(unsigned int key, gchar const *value) +{ switch (key) { - case SP_ATTR_CX: - this->cx.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_CY: - this->cy.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_RX: - if (!this->rx.read(value) || (this->rx.value <= 0.0)) { - this->rx.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_RY: - if (!this->ry.read(value) || (this->ry.value <= 0.0)) { - this->ry.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - default: - SPGenericEllipse::set(key, value); - break; - } -} - -const char* SPEllipse::displayName() { - return _("Ellipse"); -} + case SP_ATTR_CX: + this->cx.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_CY: + this->cy.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_RX: + if (!this->rx.read(value) || (this->rx.value <= 0.0)) { + this->rx.unset(); + } + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; -void -sp_ellipse_position_set(SPEllipse *ellipse, gdouble x, gdouble y, gdouble rx, gdouble ry) -{ - SPGenericEllipse *ge; - - g_return_if_fail(ellipse != NULL); - g_return_if_fail(SP_IS_ELLIPSE(ellipse)); + case SP_ATTR_RY: + if (!this->ry.read(value) || (this->ry.value <= 0.0)) { + this->ry.unset(); + } - ge = SP_GENERICELLIPSE(ellipse); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - ge->cx.computed = x; - ge->cy.computed = y; - ge->rx.computed = rx; - ge->ry.computed = ry; + default: + SPGenericEllipse::set(key, value); + break; + } +} - ((SPObject *)ge)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); +const char *SPEllipse::displayName() +{ + return _("Ellipse"); } + /* SVG <circle> element */ -SPCircle::SPCircle() : SPGenericEllipse() { +SPCircle::SPCircle() : SPGenericEllipse() +{ } -SPCircle::~SPCircle() { +SPCircle::~SPCircle() +{ } -void SPCircle::build(SPDocument *document, Inkscape::XML::Node *repr) { +void SPCircle::build(SPDocument *document, Inkscape::XML::Node *repr) +{ SPGenericEllipse::build(document, repr); - this->readAttr( "cx" ); - this->readAttr( "cy" ); - this->readAttr( "r" ); + this->readAttr("cx"); + this->readAttr("cy"); + this->readAttr("r"); } -Inkscape::XML::Node* SPCircle::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { +Inkscape::XML::Node *SPCircle::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:circle"); } @@ -535,55 +467,60 @@ Inkscape::XML::Node* SPCircle::write(Inkscape::XML::Document *xml_doc, Inkscape: return repr; } -void SPCircle::set(unsigned int key, gchar const* value) { +void SPCircle::set(unsigned int key, gchar const *value) +{ switch (key) { - case SP_ATTR_CX: - this->cx.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_CY: - this->cy.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_R: - if (!this->rx.read(value) || this->rx.value <= 0.0) { - this->rx.unset(); - } - - this->ry = this->rx; - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - default: - SPGenericEllipse::set(key, value); - break; + case SP_ATTR_CX: + this->cx.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_CY: + this->cy.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_R: + if (!this->rx.read(value) || this->rx.value <= 0.0) { + this->rx.unset(); + } + + this->ry = this->rx; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + default: + SPGenericEllipse::set(key, value); + break; } } -const char* SPCircle::displayName() { - return _("Circle"); +const char *SPCircle::displayName() +{ + return _("Circle"); } /* <path sodipodi:type="arc"> element */ -SPArc::SPArc() : SPGenericEllipse() { +SPArc::SPArc() : SPGenericEllipse() +{ } -SPArc::~SPArc() { +SPArc::~SPArc() +{ } -void SPArc::build(SPDocument *document, Inkscape::XML::Node *repr) { - SPGenericEllipse::build(document, repr); +void SPArc::build(SPDocument *document, Inkscape::XML::Node *repr) +{ + SPGenericEllipse::build(document, repr); - this->readAttr( "sodipodi:cx" ); - this->readAttr( "sodipodi:cy" ); - this->readAttr( "sodipodi:rx" ); - this->readAttr( "sodipodi:ry" ); + this->readAttr("sodipodi:cx"); + this->readAttr("sodipodi:cy"); + this->readAttr("sodipodi:rx"); + this->readAttr("sodipodi:ry"); - this->readAttr( "sodipodi:start" ); - this->readAttr( "sodipodi:end" ); - this->readAttr( "sodipodi:open" ); + this->readAttr("sodipodi:start"); + this->readAttr("sodipodi:end"); + this->readAttr("sodipodi:open"); } /* @@ -594,32 +531,33 @@ void SPArc::build(SPDocument *document, Inkscape::XML::Node *repr) { * See SVG 1.0 Specification W3C Recommendation * ``F.6 Ellptical arc implementation notes'' for more detail. */ -static gboolean -sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr) +bool SPArc::sp_arc_set_elliptical_path_attribute(Inkscape::XML::Node *repr) { - SPGenericEllipse *ge = SP_GENERICELLIPSE(arc); - Inkscape::SVG::PathString str; - Geom::Point p1 = sp_arc_get_xy(arc, ge->start); - Geom::Point p2 = sp_arc_get_xy(arc, ge->end); - double rx = ge->rx.computed; - double ry = ge->ry.computed; + Geom::Point p1 = this->getPointAtAngle(this->start); + Geom::Point p2 = this->getPointAtAngle(this->end); + double rx = this->rx.computed; + double ry = this->ry.computed; str.moveTo(p1); - double dt = fmod(ge->end - ge->start, SP_2PI); + double dt = fmod(this->end - this->start, SP_2PI); + if (fabs(dt) < 1e-6) { - Geom::Point ph = sp_arc_get_xy(arc, (ge->start + ge->end) / 2.0); + Geom::Point ph = getPointAtAngle((this->start + this->end) / 2.0); + str.arcTo(rx, ry, 0, true, true, ph) - .arcTo(rx, ry, 0, true, true, p2) - .closePath(); + .arcTo(rx, ry, 0, true, true, p2) + .closePath(); } else { bool fa = (fabs(dt) > M_PI); bool fs = (dt > 0); + str.arcTo(rx, ry, 0, fa, fs, p2); - if (ge->closed) { - Geom::Point center = Geom::Point(ge->cx.computed, ge->cy.computed); + + if (this->_closed) { + Geom::Point center = Geom::Point(this->cx.computed, this->cy.computed); str.lineTo(center).closePath(); } } @@ -628,7 +566,8 @@ sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr) return true; } -Inkscape::XML::Node* SPArc::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { +Inkscape::XML::Node *SPArc::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) +{ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:path"); } @@ -642,17 +581,11 @@ Inkscape::XML::Node* SPArc::write(Inkscape::XML::Document *xml_doc, Inkscape::XM sp_repr_set_svg_double(repr, "sodipodi:ry", this->ry.computed); // write start and end only if they are non-trivial; otherwise remove - gdouble len = fmod(this->end - this->start, SP_2PI); - - if (len < 0.0) { - len += SP_2PI; - } - - if (!(fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8)) { + if (this->_isSlice()) { sp_repr_set_svg_double(repr, "sodipodi:start", this->start); sp_repr_set_svg_double(repr, "sodipodi:end", this->end); - repr->setAttribute("sodipodi:open", (!this->closed) ? "true" : NULL); + repr->setAttribute("sodipodi:open", (!this->_closed) ? "true" : NULL); } else { repr->setAttribute("sodipodi:end", NULL); repr->setAttribute("sodipodi:start", NULL); @@ -661,73 +594,75 @@ Inkscape::XML::Node* SPArc::write(Inkscape::XML::Document *xml_doc, Inkscape::XM } // write d= - sp_arc_set_elliptical_path_attribute(this, repr); + this->sp_arc_set_elliptical_path_attribute(repr); SPGenericEllipse::write(xml_doc, repr, flags); return repr; } -void SPArc::set(unsigned int key, gchar const* value) { +void SPArc::set(unsigned int key, gchar const *value) +{ switch (key) { - case SP_ATTR_SODIPODI_CX: - this->cx.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_SODIPODI_CY: - this->cy.readOrUnset(value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_SODIPODI_RX: - if (!this->rx.read(value) || this->rx.computed <= 0.0) { - this->rx.unset(); - } + case SP_ATTR_SODIPODI_CX: + this->cx.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_SODIPODI_CY: + this->cy.readOrUnset(value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + + case SP_ATTR_SODIPODI_RX: + if (!this->rx.read(value) || this->rx.computed <= 0.0) { + this->rx.unset(); + } - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - case SP_ATTR_SODIPODI_RY: - if (!this->ry.read(value) || this->ry.computed <= 0.0) { - this->ry.unset(); - } + case SP_ATTR_SODIPODI_RY: + if (!this->ry.read(value) || this->ry.computed <= 0.0) { + this->ry.unset(); + } - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - case SP_ATTR_SODIPODI_START: - if (value) { - sp_svg_number_read_d(value, &this->start); - } else { - this->start = 0; - } + case SP_ATTR_SODIPODI_START: + if (value) { + sp_svg_number_read_d(value, &this->start); + } else { + this->start = 0; + } - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - case SP_ATTR_SODIPODI_END: - if (value) { - sp_svg_number_read_d(value, &this->end); - } else { - this->end = 2 * M_PI; - } + case SP_ATTR_SODIPODI_END: + if (value) { + sp_svg_number_read_d(value, &this->end); + } else { + this->end = 2 * M_PI; + } - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - case SP_ATTR_SODIPODI_OPEN: - this->closed = (!value); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; + case SP_ATTR_SODIPODI_OPEN: + this->_closed = (!value); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; - default: - SPGenericEllipse::set(key, value); - break; + default: + SPGenericEllipse::set(key, value); + break; } } -void SPArc::modified(guint flags) { +void SPArc::modified(guint flags) +{ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { this->set_shape(); } @@ -735,16 +670,10 @@ void SPArc::modified(guint flags) { SPGenericEllipse::modified(flags); } - -const char* SPArc::displayName() { - gdouble len = fmod(this->end - this->start, SP_2PI); - - if (len < 0.0) { - len += SP_2PI; - } - - if (!(fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8)) { - if (this->closed) { +const char *SPArc::displayName() +{ + if (this->_isSlice()) { + if (this->_closed) { return _("Segment"); } else { return _("Arc"); @@ -754,40 +683,33 @@ const char* SPArc::displayName() { } } -void -sp_arc_position_set(SPArc *arc, gdouble x, gdouble y, gdouble rx, gdouble ry) +void SPArc::sp_arc_position_set(gdouble x, gdouble y, gdouble rx, gdouble ry) { - g_return_if_fail(arc != NULL); - g_return_if_fail(SP_IS_ARC(arc)); - - SPGenericEllipse *ge = SP_GENERICELLIPSE(arc); + this->cx.computed = x; + this->cy.computed = y; + this->rx.computed = rx; + this->ry.computed = ry; - ge->cx.computed = x; - ge->cy.computed = y; - ge->rx.computed = rx; - ge->ry.computed = ry; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + // those pref values are in degrees, while we want radians - if (prefs->getDouble("/tools/shapes/arc/start", 0.0) != 0) - ge->start = prefs->getDouble("/tools/shapes/arc/start", 0.0) * M_PI / 180; - if (prefs->getDouble("/tools/shapes/arc/end", 0.0) != 0) - ge->end = prefs->getDouble("/tools/shapes/arc/end", 0.0) * M_PI / 180; - if (!prefs->getBool("/tools/shapes/arc/open")) - ge->closed = 1; - else - ge->closed = 0; + if (prefs->getDouble("/tools/shapes/arc/start", 0.0) != 0) { + this->start = Geom::Angle::from_degrees(prefs->getDouble("/tools/shapes/arc/start", 0.0)).radians0(); + } - ((SPObject *)arc)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); -} + if (prefs->getDouble("/tools/shapes/arc/end", 0.0) != 0) { + this->end = Geom::Angle::from_degrees(prefs->getDouble("/tools/shapes/arc/end", 0.0)).radians0(); + } -Geom::Point sp_arc_get_xy(SPArc *arc, gdouble arg) -{ - SPGenericEllipse *ge = SP_GENERICELLIPSE(arc); + this->_closed = !prefs->getBool("/tools/shapes/arc/open"); - return Geom::Point(ge->rx.computed * cos(arg) + ge->cx.computed, - ge->ry.computed * sin(arg) + ge->cy.computed); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +Geom::Point SPGenericEllipse::getPointAtAngle(double arg) const +{ + return Geom::Point::polar(arg) * Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed); +} /* Local Variables: diff --git a/src/sp-ellipse.h b/src/sp-ellipse.h index 083f5847d..eab0b4907 100644 --- a/src/sp-ellipse.h +++ b/src/sp-ellipse.h @@ -23,29 +23,47 @@ class SPGenericEllipse : public SPShape { public: - SPGenericEllipse(); - virtual ~SPGenericEllipse(); + SPGenericEllipse(); + virtual ~SPGenericEllipse(); - SVGLength cx; - SVGLength cy; - SVGLength rx; - SVGLength ry; + SVGLength cx; + SVGLength cy; + SVGLength rx; + SVGLength ry; - unsigned int closed : 1; - double start, end; + /** + * If we have a slice, returns whether the shape is closed ("pizza slice") or not (arc only). + */ + bool closed(); + void setClosed(bool value); - virtual void update(SPCtx* ctx, unsigned int flags); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + double start, end; - virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); - virtual void set_shape(); - virtual Geom::Affine set_transform(Geom::Affine const& xform); + virtual void update(SPCtx *ctx, unsigned int flags); + virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void update_patheffect(bool write); + virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs); + virtual void set_shape(); + virtual Geom::Affine set_transform(Geom::Affine const &xform); + + virtual void update_patheffect(bool write); + + /** + * @brief Makes sure that start and end lie between 0 and 2 * PI. + */ + void normalize(); + + Geom::Point getPointAtAngle(double arg) const; + +protected: + /** + * @brief Determines whether the shape is a part of an ellipse. + */ + bool _isSlice() const; + + bool _closed; }; -/* This is technically priate by we need this in object edit (Lauris) */ -void sp_genericellipse_normalize (SPGenericEllipse *ellipse); /* SVG <ellipse> element */ #define SP_ELLIPSE(obj) (dynamic_cast<SPEllipse*>((SPObject*)obj)) @@ -53,16 +71,15 @@ void sp_genericellipse_normalize (SPGenericEllipse *ellipse); class SPEllipse : public SPGenericEllipse { public: - SPEllipse(); - virtual ~SPEllipse(); + SPEllipse(); + virtual ~SPEllipse(); - virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void set(unsigned int key, gchar const* value); - virtual const char* displayName(); + virtual void build(SPDocument *document, Inkscape::XML::Node *repr); + virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, gchar const *value); + virtual const char *displayName(); }; -void sp_ellipse_position_set (SPEllipse * ellipse, gdouble x, gdouble y, gdouble rx, gdouble ry); /* SVG <circle> element */ #define SP_CIRCLE(obj) (dynamic_cast<SPCircle*>((SPObject*)obj)) @@ -70,32 +87,48 @@ void sp_ellipse_position_set (SPEllipse * ellipse, gdouble x, gdouble y, gdouble class SPCircle : public SPGenericEllipse { public: - SPCircle(); - virtual ~SPCircle(); + SPCircle(); + virtual ~SPCircle(); - virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void set(unsigned int key, gchar const* value); - virtual const char* displayName(); + virtual void build(SPDocument *document, Inkscape::XML::Node *repr); + virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, gchar const *value); + virtual const char *displayName(); }; + /* <path sodipodi:type="arc"> element */ #define SP_ARC(obj) (dynamic_cast<SPArc*>((SPObject*)obj)) #define SP_IS_ARC(obj) (dynamic_cast<const SPArc*>((SPObject*)obj) != NULL) class SPArc : public SPGenericEllipse { public: - SPArc(); - virtual ~SPArc(); - - virtual void build(SPDocument *document, Inkscape::XML::Node *repr); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); - virtual void set(unsigned int key, gchar const* value); - virtual const char* displayName(); - virtual void modified(unsigned int flags); -}; + SPArc(); + virtual ~SPArc(); -void sp_arc_position_set (SPArc * arc, gdouble x, gdouble y, gdouble rx, gdouble ry); -Geom::Point sp_arc_get_xy (SPArc *ge, gdouble arg); + virtual void build(SPDocument *document, Inkscape::XML::Node *repr); + virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags); + virtual void set(unsigned int key, gchar const *value); + virtual const char *displayName(); + virtual void modified(unsigned int flags); + + void sp_arc_position_set(gdouble x, gdouble y, gdouble rx, gdouble ry); + +private: + bool sp_arc_set_elliptical_path_attribute(Inkscape::XML::Node *repr); + + friend class SPGenericEllipse; +}; #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:fileencoding=utf-8:textwidth=99 : diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index 91389bf7d..1a5c65be9 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -114,6 +114,10 @@ void SPFilter::release() { this->href = NULL; } + for (map<gchar *, int, ltstr>::const_iterator i = this->_image_name->begin() ; i != this->_image_name->end() ; i++) { + g_free(i->first); + } + delete this->_image_name; SPObject::release(); diff --git a/src/sp-flowdiv.cpp b/src/sp-flowdiv.cpp index 867e68441..00ba48b06 100644 --- a/src/sp-flowdiv.cpp +++ b/src/sp-flowdiv.cpp @@ -54,13 +54,11 @@ void SPFlowdiv::update(SPCtx *ctx, unsigned int flags) { SPItemCtx *ictx = reinterpret_cast<SPItemCtx *>(ctx); SPItemCtx cctx = *ictx; - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - - flags &= SP_OBJECT_MODIFIED_CASCADE; + childflags &= SP_OBJECT_MODIFIED_CASCADE; GSList* l = NULL; for (SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { @@ -74,19 +72,21 @@ void SPFlowdiv::update(SPCtx *ctx, unsigned int flags) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); + child->updateDisplay((SPCtx *)&cctx, childflags); } else { - child->updateDisplay(ctx, flags); + child->updateDisplay(ctx, childflags); } } sp_object_unref(child); } + + SPItem::update(ctx, flags); } void SPFlowdiv::modified(unsigned int flags) { @@ -195,13 +195,11 @@ void SPFlowtspan::update(SPCtx *ctx, unsigned int flags) { SPItemCtx *ictx = reinterpret_cast<SPItemCtx *>(ctx); SPItemCtx cctx = *ictx; - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - - flags &= SP_OBJECT_MODIFIED_CASCADE; + childflags &= SP_OBJECT_MODIFIED_CASCADE; GSList* l = NULL; for ( SPObject *child = this->firstChild() ; child ; child = child->getNext() ) { @@ -215,19 +213,21 @@ void SPFlowtspan::update(SPCtx *ctx, unsigned int flags) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); + child->updateDisplay((SPCtx *)&cctx, childflags); } else { - child->updateDisplay(ctx, flags); + child->updateDisplay(ctx, childflags); } } sp_object_unref(child); } + + SPItem::update(ctx, flags); } void SPFlowtspan::modified(unsigned int flags) { diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index ed17f1948..13ab7bc64 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -72,13 +72,11 @@ void SPFlowregion::update(SPCtx *ctx, unsigned int flags) { SPItemCtx *ictx = reinterpret_cast<SPItemCtx *>(ctx); SPItemCtx cctx = *ictx; - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - - flags &= SP_OBJECT_MODIFIED_CASCADE; + childflags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = NULL; @@ -93,20 +91,22 @@ void SPFlowregion::update(SPCtx *ctx, unsigned int flags) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM (child)) { SPItem const &chi = *SP_ITEM(child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); + child->updateDisplay((SPCtx *)&cctx, childflags); } else { - child->updateDisplay(ctx, flags); + child->updateDisplay(ctx, childflags); } } sp_object_unref(child); } + SPItem::update(ctx, flags); + this->UpdateComputed(); } diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 88564c0ac..49360f9d9 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -72,10 +72,11 @@ void SPFlowtext::update(SPCtx* ctx, unsigned int flags) { SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; - SPItem::update(ctx, flags); - - if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - flags &= SP_OBJECT_MODIFIED_CASCADE; + unsigned childflags = flags; + if (flags & SP_OBJECT_MODIFIED_FLAG) { + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + } + childflags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = NULL; @@ -90,20 +91,22 @@ void SPFlowtext::update(SPCtx* ctx, unsigned int flags) { SPObject *child = SP_OBJECT(l->data); l = g_slist_remove(l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); + child->updateDisplay((SPCtx *)&cctx, childflags); } else { - child->updateDisplay(ctx, flags); + child->updateDisplay(ctx, childflags); } } sp_object_unref(child); } + SPItem::update(ctx, flags); + this->rebuildLayout(); Geom::OptRect pbox = this->geometricBounds(); @@ -326,7 +329,12 @@ Inkscape::DrawingItem* SPFlowtext::show(Inkscape::Drawing &drawing, unsigned int } void SPFlowtext::hide(unsigned int key) { - SPItem::hide(key); + for (SPItemView* v = this->display; v != NULL; v = v->next) { + if (v->key == key) { + Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); + this->_clearFlow(g); + } + } } diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 05dfb5f48..f2fc6a37a 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -682,11 +682,12 @@ Inkscape::Pixbuf *sp_image_repr_read_image(gchar const *href, gchar const *absre // and if it fails, we also try to use bare href regardless of its g_path_is_absolute if (g_file_test (fullname, G_FILE_TEST_EXISTS) && !g_file_test (fullname, G_FILE_TEST_IS_DIR)) { inkpb = Inkscape::Pixbuf::create_from_file(fullname); - g_free (fullname); if (inkpb != NULL) { + g_free (fullname); return inkpb; } } + g_free (fullname); } /* try filename as absolute */ diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index a99a3e988..41e049b86 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -161,44 +161,49 @@ void SPGroup::order_changed (Inkscape::XML::Node *child, Inkscape::XML::Node *ol } void SPGroup::update(SPCtx *ctx, unsigned int flags) { - SPLPEItem::update(ctx, flags); - SPItemCtx *ictx, cctx; ictx = (SPItemCtx *) ctx; cctx = *ictx; - if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - } + unsigned childflags = flags; - flags &= SP_OBJECT_MODIFIED_CASCADE; - - if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = this->display; v != NULL; v = v->next) { - Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - group->setStyle(this->style); - } + if (flags & SP_OBJECT_MODIFIED_FLAG) { + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } + childflags &= SP_OBJECT_MODIFIED_CASCADE; GSList *l = g_slist_reverse(this->childList(true, SPObject::ActionUpdate)); while (l) { SPObject *child = SP_OBJECT (l->data); l = g_slist_remove (l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM (child)) { SPItem const &chi = *SP_ITEM(child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); + child->updateDisplay((SPCtx *)&cctx, childflags); } else { - child->updateDisplay(ctx, flags); + child->updateDisplay(ctx, childflags); } } sp_object_unref(child); } + + // For a group, we need to update ourselves *after* updating children. + // this is because the group might contain shapes such as rect or ellipse, + // which recompute their equivalent path (a.k.a curve) in the update callback, + // and this is in turn used when computing bbox. + SPLPEItem::update(ctx, flags); + + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { + Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); + group->setStyle(this->style); + } + } } void SPGroup::modified(guint flags) { @@ -212,13 +217,6 @@ void SPGroup::modified(guint flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = this->display; v != NULL; v = v->next) { - Inkscape::DrawingGroup *group = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - group->setStyle(this->style); - } - } - GSList *l = g_slist_reverse(this->childList(true)); while (l) { diff --git a/src/sp-item.cpp b/src/sp-item.cpp index a99bf85cc..5bf0afdeb 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -603,13 +603,13 @@ void SPItem::update(SPCtx *ctx, guint flags) { } } } - /* Update bounding box data used by filters */ + /* Update bounding box in user space, used for filter and objectBoundingBox units */ if (item->style->filter.set && item->display) { - Geom::OptRect item_bbox = item->visualBounds(); + Geom::OptRect item_bbox = item->geometricBounds(); SPItemView *itemview = item->display; do { - if (itemview->arenaitem) // Already enlarged by visualBounds - itemview->arenaitem->setFilterBounds(item_bbox); + if (itemview->arenaitem) + itemview->arenaitem->setItemBounds(item_bbox); } while ( (itemview = itemview->next) ); } @@ -665,16 +665,20 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X if (item->clip_ref){ if (item->clip_ref->getObject()) { - const gchar *value = g_strdup_printf ("url(%s)", item->clip_ref->getURI()->toString()); + gchar *uri = item->clip_ref->getURI()->toString(); + const gchar *value = g_strdup_printf ("url(%s)", uri); repr->setAttribute ("clip-path", value); g_free ((void *) value); + g_free ((void *) uri); } } if (item->mask_ref){ if (item->mask_ref->getObject()) { - const gchar *value = g_strdup_printf ("url(%s)", item->mask_ref->getURI()->toString()); + gchar *uri = item->mask_ref->getURI()->toString(); + const gchar *value = g_strdup_printf ("url(%s)", uri); repr->setAttribute ("mask", value); g_free ((void *) value); + g_free ((void *) uri); } } @@ -721,7 +725,7 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const // call the subclass method // CPPIFY //bbox = this->bbox(Geom::identity(), SPItem::VISUAL_BBOX); - bbox = const_cast<SPItem*>(this)->bbox(Geom::identity(), SPItem::VISUAL_BBOX); + bbox = const_cast<SPItem*>(this)->bbox(Geom::identity(), SPItem::GEOMETRIC_BBOX); // see LP Bug 1229971 SPFilter *filter = SP_FILTER(style->getFilter()); // default filer area per the SVG spec: @@ -1061,12 +1065,8 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned SP_MASK(mask)->sp_mask_set_bbox(mask_key, item_bbox); mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } - if (style->filter.set && display) { - item_bbox = visualBounds(); - } ai->setData(this); - // Already enlarged by visualBounds for filters - ai->setFilterBounds(item_bbox); + ai->setItemBounds(geometricBounds()); } return ai; diff --git a/src/sp-object.h b/src/sp-object.h index 4e9a6c938..bcaa1dac7 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -106,7 +106,9 @@ enum { class SPDocument; /// Internal class consisting of two bits. -struct SPIXmlSpace { +class SPIXmlSpace { +public: + SPIXmlSpace(): set(0), value(SP_XML_SPACE_DEFAULT) {}; guint set : 1; guint value : 1; }; diff --git a/src/sp-radial-gradient.cpp b/src/sp-radial-gradient.cpp index c8bf5db81..7c481fead 100644 --- a/src/sp-radial-gradient.cpp +++ b/src/sp-radial-gradient.cpp @@ -156,28 +156,36 @@ cairo_pattern_t* SPRadialGradient::pattern_new(cairo_t *ct, Geom::OptRect const // https://bugs.launchpad.net/inkscape/+bug/970355 Geom::Affine gs2user = this->gradientTransform; - Geom::Scale gs2user_scale; if (this->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX && bbox) { Geom::Affine bbox2user(bbox->width(), 0, 0, bbox->height(), bbox->left(), bbox->top()); gs2user *= bbox2user; - gs2user_scale = Geom::Scale( gs2user[0], gs2user[3] ); } - Geom::Point d = focus - center; - Geom::Point d_user = d * gs2user_scale; - Geom::Point r_user( radius, 0 ); - r_user *= gs2user_scale; - - if (d_user.length() + tolerance > r_user.length()) { + // we need to use vectors with the same direction to represent the transformed + // radius and the focus-center delta, because gs2user might contain non-uniform scaling + Geom::Point d(focus - center); + Geom::Point d_user(d.length(), 0); + Geom::Point r_user(radius, 0); + d_user *= gs2user.withoutTranslation(); + r_user *= gs2user.withoutTranslation(); + + double dx = d_user.x(), dy = d_user.y(); + cairo_user_to_device_distance(ct, &dx, &dy); + + // compute the tolerance distance in user space + // create a vector with the same direction as the transformed d, + // with the length equal to tolerance + double dl = hypot(dx, dy); + double tx = tolerance * dx / dl, ty = tolerance * dy / dl; + cairo_device_to_user_distance(ct, &tx, &ty); + double tolerance_user = hypot(tx, ty); + + if (d_user.length() + tolerance_user > r_user.length()) { scale = r_user.length() / d_user.length(); - double dx = d_user.x(), dy = d_user.y(); - cairo_user_to_device_distance(ct, &dx, &dy); - if (!Geom::are_near(dx, 0, tolerance) || !Geom::are_near(dy, 0, tolerance)) - { - scale *= 1.0 - 2.0 * tolerance / hypot(dx, dy); - } + // nudge the focus slightly inside + scale *= 1.0 - 2.0 * tolerance / dl; } cairo_pattern_t *cp = cairo_pattern_create_radial( diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 72a5996d1..c431f52da 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -135,12 +135,9 @@ void SPText::remove_child(Inkscape::XML::Node *rch) { void SPText::update(SPCtx *ctx, guint flags) { - SPItem::update(ctx, flags); - - guint cflags = (flags & SP_OBJECT_MODIFIED_CASCADE); - + unsigned childflags = (flags & SP_OBJECT_MODIFIED_CASCADE); if (flags & SP_OBJECT_MODIFIED_FLAG) { - cflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } // Create temporary list of children @@ -157,14 +154,17 @@ void SPText::update(SPCtx *ctx, guint flags) { SPObject *child = reinterpret_cast<SPObject*>(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); - if (cflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { /* fixme: Do we need transform? */ - child->updateDisplay(ctx, cflags); + child->updateDisplay(ctx, childflags); } sp_object_unref(child, this); } + // update ourselves after updating children + SPItem::update(ctx, flags); + if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG ) ) @@ -318,7 +318,12 @@ Inkscape::DrawingItem* SPText::show(Inkscape::Drawing &drawing, unsigned key, un void SPText::hide(unsigned int key) { -// SPItem::onHide(key); + for (SPItemView* v = this->display; v != NULL; v = v->next) { + if (v->key == key) { + Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); + this->_clearFlow(g); + } + } } const char* SPText::displayName() { diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index 4f9947a04..1c0481547 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -148,21 +148,21 @@ void SPTRef::set(unsigned int key, const gchar* value) { void SPTRef::update(SPCtx *ctx, guint flags) { debug("0x%p",this); - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - - flags &= SP_OBJECT_MODIFIED_CASCADE; + childflags &= SP_OBJECT_MODIFIED_CASCADE; SPObject *child = this->stringChild; if (child) { - if ( flags || ( child->uflags & SP_OBJECT_MODIFIED_FLAG )) { - child->updateDisplay(ctx, flags); + if ( childflags || ( child->uflags & SP_OBJECT_MODIFIED_FLAG )) { + child->updateDisplay(ctx, childflags); } } + + SPItem::update(ctx, flags); } void SPTRef::modified(unsigned int flags) { diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp index 21c5ee11f..20d404130 100644 --- a/src/sp-tspan.cpp +++ b/src/sp-tspan.cpp @@ -107,19 +107,19 @@ void SPTSpan::set(unsigned int key, const gchar* value) { } void SPTSpan::update(SPCtx *ctx, guint flags) { - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - - flags &= SP_OBJECT_MODIFIED_CASCADE; + childflags &= SP_OBJECT_MODIFIED_CASCADE; for ( SPObject *ochild = this->firstChild() ; ochild ; ochild = ochild->getNext() ) { if ( flags || ( ochild->uflags & SP_OBJECT_MODIFIED_FLAG )) { - ochild->updateDisplay(ctx, flags); + ochild->updateDisplay(ctx, childflags); } } + + SPItem::update(ctx, flags); } void SPTSpan::modified(unsigned int flags) { diff --git a/src/sp-use.cpp b/src/sp-use.cpp index a558c6bf4..ec367d786 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -476,20 +476,12 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; - SPItem::update(ctx, flags); - + unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { - flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } - flags &= SP_OBJECT_MODIFIED_CASCADE; - - if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - for (SPItemView *v = this->display; v != NULL; v = v->next) { - Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); - g->setStyle(this->style); - } - } + childflags &= SP_OBJECT_MODIFIED_CASCADE; /* Set up child viewport */ if (this->x.unit == SVGLength::PERCENT) { @@ -510,21 +502,30 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { cctx.viewport = Geom::Rect::from_xywh(0, 0, this->width.computed, this->height.computed); cctx.i2vp = Geom::identity(); - flags&=~SP_OBJECT_USER_MODIFIED_FLAG_B; + childflags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; if (this->child) { sp_object_ref(this->child); - if (flags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem const &chi = *SP_ITEM(this->child); cctx.i2doc = chi.transform * ictx->i2doc; cctx.i2vp = chi.transform * ictx->i2vp; - this->child->updateDisplay((SPCtx *)&cctx, flags); + this->child->updateDisplay((SPCtx *)&cctx, childflags); } sp_object_unref(this->child); } + SPItem::update(ctx, flags); + + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + for (SPItemView *v = this->display; v != NULL; v = v->next) { + Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); + g->setStyle(this->style); + } + } + /* As last step set additional transform of arena group */ for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 8a57fa98a..319928d99 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -2183,6 +2183,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop, gchar *message = g_strdup_printf(_("%s <b>%d</b> of <b>%d</b> paths simplified..."), simplificationType, pathsSimplified, totalPathCount); desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, message); + g_free(message); } didSomething |= sp_selected_path_simplify_item(desktop, selection, item, @@ -2192,7 +2193,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop, desktop->clearWaitingCursor(); if (pathsSimplified > 20) { - desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, g_strdup_printf(_("<b>%d</b> paths simplified."), pathsSimplified)); + desktop->messageStack()->flashF(Inkscape::NORMAL_MESSAGE, _("<b>%d</b> paths simplified."), pathsSimplified); } return didSomething; diff --git a/src/spray-context.cpp b/src/spray-context.cpp index fd9aff196..6b97dcc17 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -499,7 +499,9 @@ static bool sp_spray_recursive(SPDesktop *desktop, // Ad the clone to the list of the father's sons parent->appendChild(clone); // Generates the link between father and son attributes - clone->setAttribute("xlink:href", g_strdup_printf("#%s", old_repr->attribute("id")), false); + gchar *href_str = g_strdup_printf("#%s", old_repr->attribute("id")); + clone->setAttribute("xlink:href", href_str, false); + g_free(href_str); SPObject *clone_object = doc->getObjectByRepr(clone); // conversion object->item diff --git a/src/style.cpp b/src/style.cpp index 2807a7d9a..bea56e7b1 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -593,10 +593,18 @@ sp_style_unref(SPStyle *style) sp_style_filter_clear(style); g_free(style->stroke_dash.dash); + + for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) { + if (style->marker[i].value) { + g_free(style->marker[i].value); + style->marker[i].value = NULL; + } + } + g_free(style); + return NULL; } - - return NULL; + return style; } /** @@ -4447,6 +4455,7 @@ sp_style_write_ipaint(gchar *b, gint const len, gchar const *const key, if ( paint->value.href && paint->value.href->getURI() ) { const gchar* uri = paint->value.href->getURI()->toString(); css << "url(" << uri << ")"; + g_free((void *)uri); } if ( paint->noneSet ) { @@ -4631,7 +4640,10 @@ sp_style_write_ifilter(gchar *p, gint const len, gchar const *key, if (val->inherit) { return g_snprintf(p, len, "%s:inherit;", key); } else if (val->href && val->href->getURI()) { - return g_snprintf(p, len, "%s:url(%s);", key, val->href->getURI()->toString()); + gchar *uri = val->href->getURI()->toString(); + gint ret = g_snprintf(p, len, "%s:url(%s);", key, uri); + g_free(uri); + return ret; } } diff --git a/src/svg/svg-length.cpp b/src/svg/svg-length.cpp index bb6cc5428..8d26a95d2 100644 --- a/src/svg/svg-length.cpp +++ b/src/svg/svg-length.cpp @@ -171,6 +171,14 @@ unsigned int sp_svg_number_write_de(gchar *buf, int bufLen, double val, unsigned } } +SVGLength::SVGLength() + : _set(false) + , unit(NONE) + , value(0) + , computed(0) +{ +} + /* Length */ bool SVGLength::read(gchar const *str) diff --git a/src/svg/svg-length.h b/src/svg/svg-length.h index 3832a4eb5..477b3ef81 100644 --- a/src/svg/svg-length.h +++ b/src/svg/svg-length.h @@ -21,6 +21,7 @@ class SVGLength { public: + SVGLength(); enum Unit { NONE, diff --git a/src/text-chemistry.cpp b/src/text-chemistry.cpp index 8a3fede0f..532d19e02 100644 --- a/src/text-chemistry.cpp +++ b/src/text-chemistry.cpp @@ -152,7 +152,9 @@ text_put_on_path() // create textPath and put it into the text Inkscape::XML::Node *textpath = xml_doc->createElement("svg:textPath"); // reference the shape - textpath->setAttribute("xlink:href", g_strdup_printf("#%s", shape->getRepr()->attribute("id"))); + gchar *href_str = g_strdup_printf("#%s", shape->getRepr()->attribute("id")); + textpath->setAttribute("xlink:href", href_str); + g_free(href_str); if (text_alignment == Inkscape::Text::Layout::RIGHT) { textpath->setAttribute("startOffset", "100%"); } else if (text_alignment == Inkscape::Text::Layout::CENTER) { @@ -234,9 +236,9 @@ text_remove_all_kerns_recursively(SPObject *o) gchar **xa_space = g_strsplit(x, " ", 0); gchar **xa_comma = g_strsplit(x, ",", 0); if (xa_space && *xa_space && *(xa_space + 1)) { - o->getRepr()->setAttribute("x", g_strdup(*xa_space)); + o->getRepr()->setAttribute("x", *xa_space); } else if (xa_comma && *xa_comma && *(xa_comma + 1)) { - o->getRepr()->setAttribute("x", g_strdup(*xa_comma)); + o->getRepr()->setAttribute("x", *xa_comma); } g_strfreev(xa_space); g_strfreev(xa_comma); @@ -331,7 +333,9 @@ text_flow_into_shape() Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); clone->setAttribute("x", "0"); clone->setAttribute("y", "0"); - clone->setAttribute("xlink:href", g_strdup_printf("#%s", item->getRepr()->attribute("id"))); + gchar *href_str = g_strdup_printf("#%s", item->getRepr()->attribute("id")); + clone->setAttribute("xlink:href", href_str); + g_free(href_str); // add the new clone to the region region_repr->appendChild(clone); diff --git a/src/tools-switch.cpp b/src/tools-switch.cpp index fd160e518..a3c0f2daa 100644 --- a/src/tools-switch.cpp +++ b/src/tools-switch.cpp @@ -86,6 +86,31 @@ static char const *const tool_names[] = { "/tools/lpetool", NULL }; +static char const *const tool_msg[] = { + NULL, + N_("<b>Click</b> to Select and Tranform objects, <b>Drag</b> to select many objects."), + N_("Modify selected path points (nodes) directly."), + N_("To tweak a path by pushing, select it and drag over it."), + N_("<b>Drag</b>, <b>click</b> or <b>click and scroll</b> to spray the selected objects."), + N_("<b>Drag</b> to create a rectangle. <b>Drag controls</b> to round corners and resize. <b>Click</b> to select."), + N_("<b>Drag</b> to create a 3D box. <b>Drag controls</b> to resize in perspective. <b>Click</b> to select (with <b>Ctrl+Alt</b> for single faces)."), + N_("<b>Drag</b> to create an ellipse. <b>Drag controls</b> to make an arc or segment. <b>Click</b> to select."), + N_("<b>Drag</b> to create a star. <b>Drag controls</b> to edit the star shape. <b>Click</b> to select."), + N_("<b>Drag</b> to create a spiral. <b>Drag controls</b> to edit the spiral shape. <b>Click</b> to select."), + N_("<b>Drag</b> to create a freehand line. <b>Shift</b> appends to selected path, <b>Alt</b> activates sketch mode."), + N_("<b>Click</b> or <b>click and drag</b> to start a path; with <b>Shift</b> to append to selected path. <b>Ctrl+click</b> to create single dots (straight line modes only)."), + N_("<b>Drag</b> to draw a calligraphic stroke; with <b>Ctrl</b> to track a guide path. <b>Arrow keys</b> adjust width (left/right) and angle (up/down)."), + N_("<b>Click</b> to select or create text, <b>drag</b> to create flowed text; then type."), + N_("<b>Drag</b> or <b>double click</b> to create a gradient on selected objects, <b>drag handles</b> to adjust gradients."), + N_("<b>Drag</b> or <b>double click</b> to create a mesh on selected objects, <b>drag handles</b> to adjust meshes."), + N_("<b>Click</b> or <b>drag around an area</b> to zoom in, <b>Shift+click</b> to zoom out."), + N_("<b>Drag</b> to measure the dimensions of objects."), + N_("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard"), + N_("<b>Click and drag</b> between shapes to create a connector."), + N_("<b>Click</b> to paint a bounded area, <b>Shift+click</b> to union the new fill with the current selection, <b>Ctrl+click</b> to change the clicked object's fill and stroke to the current setting."), + N_("<b>Drag</b> to erase."), + N_("Choose a subtool from the toolbar"), +}; static int tools_prefpath2num(char const *id) @@ -123,140 +148,11 @@ tools_switch(SPDesktop *dt, int num) } dt->set_event_context2(tool_names[num]); - - switch (num) { - case TOOLS_SELECT: - //dt->set_event_context(SP_TYPE_SELECT_CONTEXT, tool_names[num]); - /* fixme: This is really ugly hack. We should bind and unbind class methods */ - dt->activate_guides(true); - inkscape_eventcontext_set(dt->getEventContext()); - break; - case TOOLS_NODES: - //dt->set_event_context(INK_TYPE_NODE_TOOL, tool_names[num]); - dt->activate_guides(true); - inkscape_eventcontext_set(dt->getEventContext()); - break; - case TOOLS_TWEAK: - //dt->set_event_context(SP_TYPE_TWEAK_CONTEXT, tool_names[num]); - dt->activate_guides(true); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("To tweak a path by pushing, select it and drag over it.")); - break; - case TOOLS_SPRAY: - //dt->set_event_context(SP_TYPE_SPRAY_CONTEXT, tool_names[num]); - dt->activate_guides(true); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b>, <b>click</b> or <b>click and scroll</b> to spray the selected objects.")); - break; - case TOOLS_SHAPES_RECT: - //dt->set_event_context(SP_TYPE_RECT_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create a rectangle. <b>Drag controls</b> to round corners and resize. <b>Click</b> to select.")); - break; - case TOOLS_SHAPES_3DBOX: - //dt->set_event_context(SP_TYPE_BOX3D_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create a 3D box. <b>Drag controls</b> to resize in perspective. <b>Click</b> to select (with <b>Ctrl+Alt</b> for single faces).")); - break; - case TOOLS_SHAPES_ARC: - //dt->set_event_context(SP_TYPE_ARC_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create an ellipse. <b>Drag controls</b> to make an arc or segment. <b>Click</b> to select.")); - break; - case TOOLS_SHAPES_STAR: - //dt->set_event_context(SP_TYPE_STAR_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create a star. <b>Drag controls</b> to edit the star shape. <b>Click</b> to select.")); - break; - case TOOLS_SHAPES_SPIRAL: - //dt->set_event_context(SP_TYPE_SPIRAL_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create a spiral. <b>Drag controls</b> to edit the spiral shape. <b>Click</b> to select.")); - break; - case TOOLS_FREEHAND_PENCIL: - //dt->set_event_context(SP_TYPE_PENCIL_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to create a freehand line. <b>Shift</b> appends to selected path, <b>Alt</b> activates sketch mode.")); - break; - case TOOLS_FREEHAND_PEN: - //dt->set_event_context(SP_TYPE_PEN_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>click and drag</b> to start a path; with <b>Shift</b> to append to selected path. <b>Ctrl+click</b> to create single dots (straight line modes only).")); - break; - case TOOLS_CALLIGRAPHIC: - //dt->set_event_context(SP_TYPE_DYNA_DRAW_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to draw a calligraphic stroke; with <b>Ctrl</b> to track a guide path. <b>Arrow keys</b> adjust width (left/right) and angle (up/down).")); - break; - case TOOLS_TEXT: - //dt->set_event_context(SP_TYPE_TEXT_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> to select or create text, <b>drag</b> to create flowed text; then type.")); - break; - case TOOLS_GRADIENT: - //dt->set_event_context(SP_TYPE_GRADIENT_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> or <b>double click</b> to create a gradient on selected objects, <b>drag handles</b> to adjust gradients.")); - break; - case TOOLS_MESH: - //dt->set_event_context(SP_TYPE_MESH_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> or <b>double click</b> to create a mesh on selected objects, <b>drag handles</b> to adjust meshes.")); - break; - case TOOLS_ZOOM: - //dt->set_event_context(SP_TYPE_ZOOM_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> or <b>drag around an area</b> to zoom in, <b>Shift+click</b> to zoom out.")); - break; - case TOOLS_MEASURE: - //dt->set_event_context(SP_TYPE_MEASURE_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to measure the dimensions of objects.")); - break; - case TOOLS_DROPPER: - //dt->set_event_context(SP_TYPE_DROPPER_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard")); - break; - case TOOLS_CONNECTOR: - //dt->set_event_context(SP_TYPE_CONNECTOR_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click and drag</b> between shapes to create a connector.")); - break; - case TOOLS_PAINTBUCKET: - //dt->set_event_context(SP_TYPE_FLOOD_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Click</b> to paint a bounded area, <b>Shift+click</b> to union the new fill with the current selection, <b>Ctrl+click</b> to change the clicked object's fill and stroke to the current setting.")); - break; - case TOOLS_ERASER: - //dt->set_event_context(SP_TYPE_ERASER_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Drag</b> to erase.")); - break; - case TOOLS_LPETOOL: - //dt->set_event_context(SP_TYPE_LPETOOL_CONTEXT, tool_names[num]); - dt->activate_guides(false); - inkscape_eventcontext_set(dt->getEventContext()); - dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("Choose a subtool from the toolbar")); - break; - } + /* fixme: This is really ugly hack. We should bind and unbind class methods */ + /* First 4 tools use guides, first is undefined but we don't care */ + dt->activate_guides(num < 5); + inkscape_eventcontext_set(dt->getEventContext()); + dt->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, gettext( tool_msg[num] ) ); } void tools_switch_by_item(SPDesktop *dt, SPItem *item, Geom::Point const p) diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index f87288494..ca0edfadd 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -1017,7 +1017,7 @@ void SearchResultList::populate_from_xml(xmlNode * a_node) } else if (!strcmp(reinterpret_cast<const char*>(cur_node->name), "enclosure")) { - xmlChar *xml_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar*>(g_strdup("url"))); + xmlChar *xml_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar const*>("url")); char* url = reinterpret_cast<char*>(xml_url); char* filename = g_path_get_basename(url); @@ -1027,7 +1027,7 @@ void SearchResultList::populate_from_xml(xmlNode * a_node) } else if (!strcmp(reinterpret_cast<const char*>(cur_node->name), "thumbnail")) { - xmlChar *xml_thumbnail_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar*>(g_strdup("url"))); + xmlChar *xml_thumbnail_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar const*>("url")); char* thumbnail_url = reinterpret_cast<char*>(xml_thumbnail_url); char* thumbnail_filename = g_path_get_basename(thumbnail_url); diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index ab5f4c0e9..56ecfdecc 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -541,7 +541,9 @@ void SvgFontsDialog::set_glyph_description_from_selected_path(){ Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d")); //XML Tree being directly used here while it shouldn't be. - glyph->getRepr()->setAttribute("d", (char*) sp_svg_write_path (flip_coordinate_system(pathv))); + gchar *str = sp_svg_write_path (flip_coordinate_system(pathv)); + glyph->getRepr()->setAttribute("d", str); + g_free(str); DocumentUndo::done(doc, SP_VERB_DIALOG_SVG_FONTS, _("Set glyph curves")); update_glyphs(); @@ -578,7 +580,9 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){ if (SP_IS_MISSING_GLYPH(obj)){ //XML Tree being directly used here while it shouldn't be. - obj->getRepr()->setAttribute("d", (char*) sp_svg_write_path (flip_coordinate_system(pathv))); + gchar *str = sp_svg_write_path (flip_coordinate_system(pathv)); + obj->getRepr()->setAttribute("d", str); + g_free(str); DocumentUndo::done(doc, SP_VERB_DIALOG_SVG_FONTS, _("Set glyph curves")); } } diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 6e14e8e97..b775c0637 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -459,7 +459,10 @@ void PathManipulator::weldSegments() if (j->selected()) ++num_selected; else ++num_unselected; } - if (num_selected < 3) continue; + + // if 2 or fewer nodes are selected, there can't be any middle points to remove. + if (num_selected <= 2) continue; + if (num_unselected == 0 && sp->closed()) { // if all nodes in a closed subpath are selected, the operation doesn't make much sense continue; @@ -489,14 +492,16 @@ void PathManipulator::weldSegments() } if (num_points > 2) { // remove nodes in the middle + // TODO: fit bezier to the former shape sel_beg = sel_beg.next(); while (sel_beg != sel_end.prev()) { NodeList::iterator next = sel_beg.next(); sp->erase(sel_beg); sel_beg = next; } - sel_beg = sel_end; } + sel_beg = sel_end; + // decrease num_selected by the number of points processed num_selected -= num_points; } } diff --git a/src/verbs.cpp b/src/verbs.cpp index 23a560423..bdef0526a 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2119,6 +2119,9 @@ void TutorialVerb::perform(SPAction *action, void *data) // TRANSLATORS: See "tutorial-basic.svg" comment. sp_help_open_tutorial(NULL, (gpointer)_("tutorial-tracing.svg")); break; + case SP_VERB_TUTORIAL_TRACING_PIXELART: + sp_help_open_tutorial(NULL, (gpointer)_("tutorial-tracing-pixelart.svg")); + break; case SP_VERB_TUTORIAL_CALLIGRAPHY: // TRANSLATORS: See "tutorial-basic.svg" comment. sp_help_open_tutorial(NULL, (gpointer)_("tutorial-calligraphy.svg")); @@ -2883,6 +2886,8 @@ Verb *Verb::_base_verbs[] = { // TRANSLATORS: "to trace" means "to convert a bitmap to vector graphics" (to vectorize) new TutorialVerb(SP_VERB_TUTORIAL_TRACING, "TutorialsTracing", N_("Inkscape: T_racing"), N_("Using bitmap tracing"), NULL/*"tutorial_tracing"*/), + new TutorialVerb(SP_VERB_TUTORIAL_TRACING_PIXELART, "TutorialsTracingPixelArt", N_("Inkscape: Tracing Pixel Art"), + N_("Using Trace Pixel Art dialog"), NULL), new TutorialVerb(SP_VERB_TUTORIAL_CALLIGRAPHY, "TutorialsCalligraphy", N_("Inkscape: _Calligraphy"), N_("Using the Calligraphy pen tool"), NULL), new TutorialVerb(SP_VERB_TUTORIAL_INTERPOLATE, "TutorialsInterpolate", N_("Inkscape: _Interpolate"), diff --git a/src/verbs.h b/src/verbs.h index 40292745a..0f764eb29 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -304,6 +304,7 @@ enum { SP_VERB_TUTORIAL_SHAPES, SP_VERB_TUTORIAL_ADVANCED, SP_VERB_TUTORIAL_TRACING, + SP_VERB_TUTORIAL_TRACING_PIXELART, SP_VERB_TUTORIAL_CALLIGRAPHY, SP_VERB_TUTORIAL_INTERPOLATE, SP_VERB_TUTORIAL_DESIGN, diff --git a/src/widgets/arc-toolbar.cpp b/src/widgets/arc-toolbar.cpp index 42f696bec..c31c61e32 100644 --- a/src/widgets/arc-toolbar.cpp +++ b/src/widgets/arc-toolbar.cpp @@ -123,7 +123,7 @@ sp_arctb_startend_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *v ge->end = (gtk_adjustment_get_value(adj) * M_PI)/ 180; } - sp_genericellipse_normalize(ge); + ge->normalize(); (SP_OBJECT(arc))->updateRepr(); (SP_OBJECT(arc))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 31f4bb2e5..a0b638031 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -85,6 +85,8 @@ SPObject* getMarkerObj(gchar const *n, SPDocument *doc) // FIXME: get the document from the object and let the caller pass it in SPObject *marker = doc->getObjectById(b); + + g_free(b); return marker; } |
