From 02aedb930177c008f1074fa7b17dd6085825ee1b Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Tue, 7 Jul 2015 01:29:26 +0200 Subject: Update 2Geom to r2417: make scan-build happy (bzr r14235) --- src/2geom/ellipse.cpp | 4 ++-- src/2geom/nearest-time.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/2geom/ellipse.cpp b/src/2geom/ellipse.cpp index 0264ab4ae..fed3bf86f 100644 --- a/src/2geom/ellipse.cpp +++ b/src/2geom/ellipse.cpp @@ -499,7 +499,7 @@ std::vector Ellipse::intersect(Ellipse const &other) const Line lines[2]; if (aa != 0) { - bb /= aa; cc /= aa; dd /= aa; ee /= aa; ff /= aa; + bb /= aa; cc /= aa; dd /= aa; ee /= aa; /*ff /= aa;*/ Coord s = (ee + std::sqrt(ee*ee - 4*bb)) / 2; Coord q = ee - s; Coord alpha = (dd - cc*q) / (s - q); @@ -508,7 +508,7 @@ std::vector Ellipse::intersect(Ellipse const &other) const lines[0] = Line(1, q, alpha); lines[1] = Line(1, s, beta); } else if (bb != 0) { - cc /= bb; dd /= bb; ee /= bb; ff /= bb; + cc /= bb; /*dd /= bb;*/ ee /= bb; ff /= bb; Coord s = ee; Coord q = 0; Coord alpha = cc / ee; diff --git a/src/2geom/nearest-time.cpp b/src/2geom/nearest-time.cpp index 0b21e51a2..103921021 100644 --- a/src/2geom/nearest-time.cpp +++ b/src/2geom/nearest-time.cpp @@ -80,7 +80,7 @@ Coord nearest_time(Point const &p, D2 const &input, Coord from, Coord to t = 0; } if (dfinal < mind) { - mind = dfinal; + //mind = dfinal; t = 1; } -- cgit v1.2.3 From 06a9bb45855e6fc4d66de0b58ab66ca5a0822887 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 7 Jul 2015 17:29:26 +0200 Subject: Patch from Simon Keller to correct alignment of rotated text in PDF+TEX output. (bzr r14236) --- src/extension/internal/latex-text-renderer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 1026f51ad..5933dd526 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -409,7 +409,8 @@ Flowing in rectangle is possible, not in arb shape. return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think } - Geom::Rect framebox = frame->getRect() * transform(); + // We will transform the coordinates + Geom::Rect framebox = frame->getRect(); // get position and alignment // Align on topleft corner. @@ -429,7 +430,10 @@ Flowing in rectangle is possible, not in arb shape. // no need to add LaTeX code for standard justified output :) break; } - Geom::Point pos(framebox.corner(3)); //topleft corner + + // The topleft Corner was calculated after rotating the text which results in a wrong Coordinate. + // Now, the topleft Corner is rotated after calculating it + Geom::Point pos(framebox.corner(0) * transform()); //topleft corner // determine color and transparency (for now, use rgb color model as it is most native to Inkscape) bool has_color = false; // if the item has no color set, don't force black color @@ -472,7 +476,9 @@ Flowing in rectangle is possible, not in arb shape. os << "\\rotatebox{" << degrees << "}{"; } os << "\\makebox(0,0)" << alignment << "{"; - os << "\\begin{minipage}{" << framebox.width() << "\\unitlength}"; + + // Scale the x width correctly + os << "\\begin{minipage}{" << framebox.width() * transform().expansionX() << "\\unitlength}"; os << justification; // Walk through all spans in the text object. -- cgit v1.2.3 From 96085240c58b87b7df948b7fa1e928a4432a7cf1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 8 Jul 2015 23:08:19 +0200 Subject: Fix build failures on some platforms. Correct CMakeLists.txt after 2Geom sync - patch by su_v. (bzr r14237) --- src/2geom/CMakeLists.txt | 7 ------- src/2geom/conicsec.cpp | 1 + src/2geom/point.h | 4 +++- src/live_effects/CMakeLists.txt | 2 -- 4 files changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/2geom/CMakeLists.txt b/src/2geom/CMakeLists.txt index 8a2884a2a..eb7abb614 100644 --- a/src/2geom/CMakeLists.txt +++ b/src/2geom/CMakeLists.txt @@ -68,8 +68,6 @@ set(2geom_SRC conic_section_clipper_cr.h conic_section_clipper_impl.h conicsec.h - conjugate_gradient.h - convex-cover.h coord.h crossing.h curve.h @@ -83,7 +81,6 @@ set(2geom_SRC generic-interval.h generic-rect.h geom.h - hvlinesegment.h int-interval.h int-point.h int-rect.h @@ -91,19 +88,16 @@ set(2geom_SRC line.h linear.h math-utils.h - nearest-point.h ord.h path-intersection.h path-sink.h path.h pathvector.h piecewise.h - point-ops.h point.h polynomial.h ray.h rect.h - region.h sbasis-2d.h sbasis-curve.h sbasis-geometric.h @@ -111,7 +105,6 @@ set(2geom_SRC sbasis-poly.h sbasis-to-bezier.h sbasis.h - shape.h solver.h svg-path-parser.h svg-path-writer.h diff --git a/src/2geom/conicsec.cpp b/src/2geom/conicsec.cpp index 3b36137be..089db71a4 100644 --- a/src/2geom/conicsec.cpp +++ b/src/2geom/conicsec.cpp @@ -1337,6 +1337,7 @@ bool xAx::decompose (Line& l1, Line& l2) const */ Rect xAx::arc_bound (const Point & P1, const Point & Q, const Point & P2) const { + using std::swap; //std::cout << "BOUND: P1 = " << P1 << std::endl; //std::cout << "BOUND: Q = " << Q << std::endl; //std::cout << "BOUND: P2 = " << P2 << std::endl; diff --git a/src/2geom/point.h b/src/2geom/point.h index f2659d351..a66e64647 100644 --- a/src/2geom/point.h +++ b/src/2geom/point.h @@ -386,7 +386,9 @@ inline Coord distanceSq (Point const &a, Point const &b) { /// Test whether two points are no further apart than some threshold. /// @relates Point inline bool are_near(Point const &a, Point const &b, double eps = EPSILON) { - return are_near(distance(a, b), 0, eps); + // do not use an unqualified calls to distance before the empty + // specialization of iterator_traits is defined - see end of file + return are_near((a - b).length(), 0, eps); } /// Test whether three points lie approximately on the same line. diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index c4b92e579..8a097590a 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -3,7 +3,6 @@ set(live_effects_SRC lpe-angle_bisector.cpp lpe-attach-path.cpp lpe-bendpath.cpp - lpe-boolops.cpp lpe-bounding-box.cpp lpe-bspline.cpp lpe-circle_3pts.cpp @@ -81,7 +80,6 @@ set(live_effects_SRC lpe-angle_bisector.h lpe-attach-path.h lpe-bendpath.h - lpe-boolops.h lpe-bounding-box.h lpe-bspline.h lpe-circle_3pts.h -- cgit v1.2.3 From 99dad514a04e1da213fa0877c15cae5d4ca00ea0 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Fri, 10 Jul 2015 16:50:38 +0200 Subject: Force PNG bitmap export to always write with PNG extension (bzr r14238) --- src/ui/dialog/export.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 384aec415..1edfdfe80 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -945,17 +945,19 @@ Gtk::Dialog * Export::create_progress_dialog (Glib::ustring progress_text) { Glib::ustring Export::filename_add_extension (Glib::ustring filename, Glib::ustring extension) { Glib::ustring::size_type dot; + Glib::ustring::size_type dot_ext; dot = filename.find_last_of("."); - if ( !dot ) + dot_ext = filename.lowercase().rfind("." + extension.lowercase()); + if ( dot == std::string::npos ) { return filename = filename + "." + extension; } else { - if (dot==filename.find_last_of(Glib::ustring::compose(".", extension))) + if (dot == dot_ext) { - return filename; + return filename = filename; } else { -- cgit v1.2.3 From e45d61d03281d9103b3b8daf40b84e6f415eadc4 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sat, 11 Jul 2015 00:58:49 +0200 Subject: Fix a bug continuing a bezier path whith a LPE one like spiro or bspline (bzr r14239) --- src/ui/tools/freehand-base.cpp | 7 ++++--- src/ui/tools/pen-tool.cpp | 21 ++++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index e8cbfcdbf..4fad06c98 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -598,9 +598,10 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 || prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){ s = dc->overwrite_curve; - } - if (dc->sa->start) { - s = reverse_then_unref(s); + } else { + if (dc->sa->start) { + s = reverse_then_unref(s); + } } s->append_continuous(c, 0.0625); c->unref(); diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp index 38892517d..827dbf5c3 100644 --- a/src/ui/tools/pen-tool.cpp +++ b/src/ui/tools/pen-tool.cpp @@ -1351,8 +1351,9 @@ void PenTool::_bsplineSpiroColor() void PenTool::_bsplineSpiro(bool shift) { - if(!this->spiro && !this->bspline) + if(!this->spiro && !this->bspline){ return; + } shift?this->_bsplineSpiroOff():this->_bsplineSpiroOn(); this->_bsplineSpiroBuild(); @@ -1413,13 +1414,19 @@ void PenTool::_bsplineSpiroStartAnchor(bool shift) }else{ this->spiro = false; } - if(!this->spiro && !this->bspline) + if(!this->spiro && !this->bspline){ + SPCurve *tmp_curve = this->sa->curve->copy(); + if (this->sa->start) { + tmp_curve = tmp_curve ->create_reverse(); + } + this->overwrite_curve = tmp_curve ; return; - - if(shift) + } + if(shift){ this->_bsplineSpiroStartAnchorOff(); - else + } else { this->_bsplineSpiroStartAnchorOn(); + } } void PenTool::_bsplineSpiroStartAnchorOn() @@ -1482,9 +1489,9 @@ void PenTool::_bsplineSpiroStartAnchorOff() } void PenTool::_bsplineSpiroMotion(bool shift){ - if(!this->spiro && !this->bspline) + if(!this->spiro && !this->bspline){ return; - + } using Geom::X; using Geom::Y; if(this->red_curve->is_empty()) return; -- cgit v1.2.3 From 0ea72b9451e2544b4966080e70c9e9689edd3109 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 11 Jul 2015 14:20:59 -0400 Subject: Shit son, MROE FUCKING DOCS FUCKING EVERYWHERE IT'S A WONDER WE HAVE SPACE FOR A VECTOR GRAPHICS PROGRAM BETWEEN ALL THESE DOCS (bzr r14242) --- src/helper/geom-pathstroke.cpp | 103 +++++++++++++++++++++-------------------- src/helper/geom-pathstroke.h | 50 ++++++++++++++++---- 2 files changed, 94 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp index e1038b03a..e5f207c66 100644 --- a/src/helper/geom-pathstroke.cpp +++ b/src/helper/geom-pathstroke.cpp @@ -1,7 +1,8 @@ -/* Author: +/* Authors: * Liam P. White + * Tavmjong Bah * - * Copyright (C) 2014-2015 Author + * Copyright (C) 2014-2015 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -60,14 +61,14 @@ namespace { // Internal data structure -struct join_data -{ +struct join_data { join_data(Geom::Path &_res, Geom::Path const&_outgoing, Geom::Point _in_tang, Geom::Point _out_tang, double _miter, double _width) - : res(_res), outgoing(_outgoing), in_tang(_in_tang) - , out_tang(_out_tang), miter(_miter), width(_width) {} + : res(_res), outgoing(_outgoing), in_tang(_in_tang), out_tang(_out_tang), miter(_miter), width(_width) {}; - // I/O + // contains the current path that is being built on Geom::Path &res; + + // contains the next curve to append Geom::Path const& outgoing; // input tangents @@ -382,47 +383,6 @@ void tangents(Geom::Point tang[2], Geom::Curve const& incoming, Geom::Curve cons tang[0] = tang1, tang[1] = tang2; } -void outline_helper(Geom::Path &res, Geom::Path const& temp, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, Inkscape::LineJoinType join) -{ - if (res.size() == 0 || temp.size() == 0) - return; - - Geom::Curve const& outgoing = temp.front(); - if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) { - // if the points are /that/ close, just ignore this one - res.setFinal(temp.initialPoint()); - res.append(temp); - return; - } - - join_data jd(res, temp, in_tang, out_tang, miter, width); - - bool on_outside = (Geom::cross(in_tang, out_tang) > 0); - - if (on_outside) { - join_func *jf; - switch (join) { - case Inkscape::JOIN_BEVEL: - jf = &bevel_join; - break; - case Inkscape::JOIN_ROUND: - jf = &round_join; - break; - case Inkscape::JOIN_EXTRAPOLATE: - jf = &extrapolate_join; - break; - case Inkscape::JOIN_MITER_CLIP: - jf = &miter_clip_join; - break; - default: - jf = &miter_join; - } - jf(jd); - } else { - join_inside(jd); - } -} - // Offsetting a line segment is mathematically stable and quick to do Geom::LineSegment offset_line(Geom::LineSegment const& l, double width) { @@ -696,7 +656,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin res.append(temp); } else { tangents(tang, input[u-1], input[u]); - outline_helper(res, temp, tang[0], tang[1], width, miter, join); + outline_join(res, temp, tang[0], tang[1], width, miter, join); } // odd number of paths @@ -704,7 +664,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin temp = Geom::Path(); offset_curve(temp, &input[u+1], width); tangents(tang, input[u], input[u+1]); - outline_helper(res, temp, tang[0], tang[1], width, miter, join); + outline_join(res, temp, tang[0], tang[1], width, miter, join); } } @@ -716,7 +676,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin Geom::Path temp2; temp2.append(c2); tangents(tang, input.back(), input.front()); - outline_helper(temp, temp2, tang[0], tang[1], width, miter, join); + outline_join(temp, temp2, tang[0], tang[1], width, miter, join); res.erase(res.begin()); res.erase_last(); // @@ -727,6 +687,47 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin return res; } +void outline_join(Geom::Path &res, Geom::Path const& temp, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, Inkscape::LineJoinType join) +{ + if (res.size() == 0 || temp.size() == 0) + return; + + Geom::Curve const& outgoing = temp.front(); + if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) { + // if the points are /that/ close, just ignore this one + res.setFinal(temp.initialPoint()); + res.append(temp); + return; + } + + join_data jd(res, temp, in_tang, out_tang, miter, width); + + bool on_outside = (Geom::cross(in_tang, out_tang) > 0); + + if (on_outside) { + join_func *jf; + switch (join) { + case Inkscape::JOIN_BEVEL: + jf = &bevel_join; + break; + case Inkscape::JOIN_ROUND: + jf = &round_join; + break; + case Inkscape::JOIN_EXTRAPOLATE: + jf = &extrapolate_join; + break; + case Inkscape::JOIN_MITER_CLIP: + jf = &miter_clip_join; + break; + default: + jf = &miter_join; + } + jf(jd); + } else { + join_inside(jd); + } +} + } // namespace Inkscape /* diff --git a/src/helper/geom-pathstroke.h b/src/helper/geom-pathstroke.h index 0cfb9f817..6697273cf 100644 --- a/src/helper/geom-pathstroke.h +++ b/src/helper/geom-pathstroke.h @@ -1,10 +1,11 @@ #ifndef INKSCAPE_HELPER_PATH_STROKE_H #define INKSCAPE_HELPER_PATH_STROKE_H -/* Author: +/* Authors: * Liam P. White + * Tavmjong Bah * - * Copyright (C) 2014-2015 Author + * Copyright (C) 2014-2015 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -26,21 +27,54 @@ enum LineCapType { BUTT_FLAT, BUTT_ROUND, BUTT_SQUARE, - BUTT_PEAK, // ? + BUTT_PEAK, // This is not a line ending supported by the SVG standard. }; +/** + * Strokes the path given by @a input. + * Joins may behave oddly if the width is negative. + * + * @param[in] input Input path. + * @param[in] width Stroke width. + * @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE. + * @param[in] join Line join type used during offset. Member of LineJoinType enum. + * @param[in] cap Line cap type used during stroking. Member of LineCapType enum. + * + * @return Stroked path. + * If the input path is closed, the resultant vector will contain two paths. + * Otherwise, there should be only one in the output. + */ +Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT); + /** * Offset the input path by @a width. * Joins may behave oddly if the width is negative. * - * @param input - * @param width Amount to offset. - * @param miter Miter limit. Only used with JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE. - * @param join + * @param[in] input Input path. + * @param[in] width Amount to offset. + * @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE. + * @param[in] join Line join type used during offset. Member of LineJoinType enum. + * + * @return Offsetted output. */ Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL); -Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT); +/** + * Builds a join on the provided path. + * Joins may behave oddly if the width is negative. + * + * @param[inout] res The path to build the join on. + * The outgoing path (or a portion thereof) will be appended after the join is created. + * Previous segments may be modified as an optimization, beware! + * + * @param[in] outgoing The segment to append on the outgoing portion of the join. + * @param[in] in_tang The end tangent to consider on the input path. + * @param[in] out_tang The begin tangent to consider on the output path. + * @param[in] width + * @param[in] miter + * @param[in] join + */ +void outline_join(Geom::Path &res, Geom::Path const& outgoing, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, LineJoinType join); } // namespace Inkscape -- cgit v1.2.3 From e0767cb0f376a7befe269e5eef9fb71d99e02c37 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 13 Jul 2015 15:50:02 +0200 Subject: Don't allow zero values for width/height and corresponding viewBox numbers. (bzr r14243) --- src/ui/widget/page-sizer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index 0a5697661..19ab1a280 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -266,12 +266,14 @@ PageSizer::PageSizer(Registry & _wr) _viewboxW.setDigits(2); _viewboxH.setDigits(2); + _dimensionWidth.setRange( 0.00001, 10000000 ); + _dimensionHeight.setRange( 0.00001, 10000000 ); _scaleX.setRange( 0.00001, 100000 ); _scaleY.setRange( 0.00001, 100000 ); _viewboxX.setRange( -100000, 100000 ); _viewboxY.setRange( -100000, 100000 ); - _viewboxW.setRange( 0, 200000 ); - _viewboxH.setRange( 0, 200000 ); + _viewboxW.setRange( 0.01, 200000 ); + _viewboxH.setRange( 0.01, 200000 ); _scaleY.set_sensitive (false); // We only want to display Y scale. -- cgit v1.2.3 From a3d09e2486cf76da1633c15fd40c2c39a0c06a4a Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 14 Jul 2015 00:23:14 +0200 Subject: fix "arrange" tool (typo) Fixed bugs: - https://launchpad.net/bugs/1473711 (bzr r14244) --- src/ui/dialog/grid-arrange-tab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp index c44f66a4d..ccd23a572 100644 --- a/src/ui/dialog/grid-arrange-tab.cpp +++ b/src/ui/dialog/grid-arrange-tab.cpp @@ -311,7 +311,7 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h GSList *current_row = NULL; col_cnt = 0; - for(;it!=sorted.end()&&col Date: Tue, 14 Jul 2015 13:04:32 +0200 Subject: Fix for circular references detection in almost all cases, fixing https://bugs.launchpad.net/inkscape/+bug/167247 and a few of its duplicates. This fix is aimed at preventing any sort of circular references with the URIReference::_acceptObject method, checking the absence of loops in the reference+child tree. There can be some performance improvements done if we add a pointer from cloned sub-objects to their origin sub-object. The remaining cases that are not fixed can involve non-trivial loops using one or more "url()" stylesheet references. Being able to take them into account would require a non-obvious style.cpp refactoring making use of URIReference for this kind of reference (and not handling manually the signals in the styling code, which would probably be a good thing to do anyway) (bzr r14245) --- src/live_effects/lpeobject-reference.cpp | 9 +---- src/live_effects/parameter/path-reference.cpp | 2 +- src/persp3d-reference.cpp | 3 +- src/sp-clippath.h | 2 +- src/sp-filter-reference.cpp | 2 +- src/sp-gradient-reference.cpp | 2 +- src/sp-hatch.h | 2 +- src/sp-marker.h | 2 +- src/sp-mask.h | 2 +- src/sp-object.cpp | 5 +-- src/sp-paint-server.cpp | 2 +- src/sp-pattern.h | 5 ++- src/sp-tag-use-reference.cpp | 9 +---- src/sp-tref-reference.cpp | 2 +- src/sp-use-reference.cpp | 13 +------ src/uri-references.cpp | 50 +++++++++++++++++++++++++++ src/uri-references.h | 10 +++--- 17 files changed, 74 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpeobject-reference.cpp b/src/live_effects/lpeobject-reference.cpp index 573c8a2fd..d9de6e77f 100644 --- a/src/live_effects/lpeobject-reference.cpp +++ b/src/live_effects/lpeobject-reference.cpp @@ -43,14 +43,7 @@ LPEObjectReference::~LPEObjectReference(void) bool LPEObjectReference::_acceptObject(SPObject * const obj) const { if (IS_LIVEPATHEFFECT(obj)) { - SPObject * const owner = getOwner(); - /* Refuse references to us or to an ancestor. */ - for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { - if ( iter == obj ) { - return false; - } - } - return true; + return URIReference::_acceptObject(obj); } else { return false; } diff --git a/src/live_effects/parameter/path-reference.cpp b/src/live_effects/parameter/path-reference.cpp index a76fb1b32..42589b050 100644 --- a/src/live_effects/parameter/path-reference.cpp +++ b/src/live_effects/parameter/path-reference.cpp @@ -22,7 +22,7 @@ bool PathReference::_acceptObject(SPObject * const obj) const return false; } // TODO: check whether the referred path has this LPE applied, if so: deny deny deny! - return true; + return URIReference::_acceptObject(obj); } else { return false; } diff --git a/src/persp3d-reference.cpp b/src/persp3d-reference.cpp index 895eac6f2..4526a8d8f 100644 --- a/src/persp3d-reference.cpp +++ b/src/persp3d-reference.cpp @@ -35,7 +35,8 @@ Persp3DReference::~Persp3DReference(void) bool Persp3DReference::_acceptObject(SPObject *obj) const { - return SP_IS_PERSP3D(obj); + return SP_IS_PERSP3D(obj) && URIReference::_acceptObject(obj); +; /* effic: Don't bother making this an inline function: _acceptObject is a virtual function, typically called from a context where the runtime type is not known at compile time. */ } diff --git a/src/sp-clippath.h b/src/sp-clippath.h index 91dcfd625..c9a8c68df 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -88,7 +88,7 @@ protected: return false; } SPObject * const owner = this->getOwner(); - if (obj->isAncestorOf(owner)) { + if (!URIReference::_acceptObject(obj)) { //XML Tree being used directly here while it shouldn't be... Inkscape::XML::Node * const owner_repr = owner->getRepr(); //XML Tree being used directly here while it shouldn't be... diff --git a/src/sp-filter-reference.cpp b/src/sp-filter-reference.cpp index 57600ad39..afb014820 100644 --- a/src/sp-filter-reference.cpp +++ b/src/sp-filter-reference.cpp @@ -4,7 +4,7 @@ bool SPFilterReference::_acceptObject(SPObject *obj) const { - return SP_IS_FILTER(obj); + return SP_IS_FILTER(obj) && URIReference::_acceptObject(obj); /* effic: Don't bother making this an inline function: _acceptObject is a virtual function, typically called from a context where the runtime type is not known at compile time. */ } diff --git a/src/sp-gradient-reference.cpp b/src/sp-gradient-reference.cpp index d2b8128fb..216ac73de 100644 --- a/src/sp-gradient-reference.cpp +++ b/src/sp-gradient-reference.cpp @@ -4,7 +4,7 @@ bool SPGradientReference::_acceptObject(SPObject *obj) const { - return SP_IS_GRADIENT(obj); + return SP_IS_GRADIENT(obj) && URIReference::_acceptObject(obj); /* effic: Don't bother making this an inline function: _acceptObject is a virtual function, typically called from a context where the runtime type is not known at compile time. */ } diff --git a/src/sp-hatch.h b/src/sp-hatch.h index 5004a611f..546f06a1e 100644 --- a/src/sp-hatch.h +++ b/src/sp-hatch.h @@ -168,7 +168,7 @@ public: protected: virtual bool _acceptObject(SPObject *obj) const { - return dynamic_cast(obj) != NULL; + return dynamic_cast(obj) != NULL && URIReference::_acceptObject(obj); } }; diff --git a/src/sp-marker.h b/src/sp-marker.h index 56cbaf94f..bae13243b 100644 --- a/src/sp-marker.h +++ b/src/sp-marker.h @@ -92,7 +92,7 @@ class SPMarkerReference : public Inkscape::URIReference { } protected: virtual bool _acceptObject(SPObject *obj) const { - return SP_IS_MARKER(obj); + return SP_IS_MARKER(obj) && URIReference::_acceptObject(obj); } }; diff --git a/src/sp-mask.h b/src/sp-mask.h index 3559483bb..74bd4d66e 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -81,7 +81,7 @@ protected: return false; } SPObject * const owner = this->getOwner(); - if (obj->isAncestorOf(owner)) { + if (!URIReference::_acceptObject(obj)) { //XML Tree being used directly here while it shouldn't be... Inkscape::XML::Node * const owner_repr = owner->getRepr(); //XML Tree being used directly here while it shouldn't be... diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 0bb8c240f..db66eb3e6 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -721,6 +721,9 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns } this->cloned = cloned; + /* Invoke derived methods, if any */ + this->build(document, repr); + if ( !cloned ) { this->document->bindObjectToRepr(this->repr, this); @@ -754,8 +757,6 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns g_assert(this->getId() == NULL); } - /* Invoke derived methods, if any */ - this->build(document, repr); /* Signalling (should be connected AFTER processing derived methods */ sp_repr_add_listener(repr, &object_event_vector, this); diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp index ae40ad1aa..c3416c6c8 100644 --- a/src/sp-paint-server.cpp +++ b/src/sp-paint-server.cpp @@ -27,7 +27,7 @@ SPPaintServer *SPPaintServerReference::getObject() const bool SPPaintServerReference::_acceptObject(SPObject *obj) const { - return SP_IS_PAINT_SERVER(obj); + return SP_IS_PAINT_SERVER(obj) && URIReference::_acceptObject(obj); } SPPaintServer::SPPaintServer() : SPObject() { diff --git a/src/sp-pattern.h b/src/sp-pattern.h index 145bb934e..a5e7be1d4 100644 --- a/src/sp-pattern.h +++ b/src/sp-pattern.h @@ -129,9 +129,8 @@ public: } protected: - virtual bool _acceptObject(SPObject *obj) const - { - return SP_IS_PATTERN(obj); + virtual bool _acceptObject(SPObject *obj) const { + return SP_IS_PATTERN (obj)&& URIReference::_acceptObject(obj); } }; diff --git a/src/sp-tag-use-reference.cpp b/src/sp-tag-use-reference.cpp index 220cd16d1..9fcb31fd1 100644 --- a/src/sp-tag-use-reference.cpp +++ b/src/sp-tag-use-reference.cpp @@ -24,14 +24,7 @@ bool SPTagUseReference::_acceptObject(SPObject * const obj) const { if (SP_IS_ITEM(obj)) { - SPObject * const owner = getOwner(); - // Refuse references to us or to an ancestor. - for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { - if ( iter == obj ) { - return false; - } - } - return true; + return URIReference::_acceptObject(obj); } else { return false; } diff --git a/src/sp-tref-reference.cpp b/src/sp-tref-reference.cpp index e82f575e0..7c6ff00e7 100644 --- a/src/sp-tref-reference.cpp +++ b/src/sp-tref-reference.cpp @@ -21,7 +21,7 @@ bool SPTRefReference::_acceptObject(SPObject * const obj) const { SPObject *owner = getOwner(); if (SP_IS_TREF(owner)) - return sp_tref_reference_allowed(SP_TREF(getOwner()), obj); + return URIReference::_acceptObject(obj); else return false; } diff --git a/src/sp-use-reference.cpp b/src/sp-use-reference.cpp index 642cfede8..f0b2985d2 100644 --- a/src/sp-use-reference.cpp +++ b/src/sp-use-reference.cpp @@ -25,18 +25,7 @@ bool SPUseReference::_acceptObject(SPObject * const obj) const { - if (SP_IS_ITEM(obj)) { - SPObject * const owner = getOwner(); - // Refuse references to us or to an ancestor. - for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { - if ( iter == obj ) { - return false; - } - } - return true; - } else { - return false; - } + return URIReference::_acceptObject(obj); } diff --git a/src/uri-references.cpp b/src/uri-references.cpp index 2518c173e..04f904d39 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -43,6 +43,56 @@ URIReference::~URIReference() detach(); } +/* + * The main ideas here are: + * (1) "If we are inside a clone, then we can accept if and only if our "original thing" can accept the reference" + * (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id, but also its cloned reprs + * (descendants of referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i could not find a better way. + * FIXME: find a better and safer way to find the "original object" of anyone with the flag ->cloned + * + * (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed edges are + * either parent->child relations , *** or href'ing to href'ed *** relations, stays acyclic. + * We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case linear in the number of objects. + * There are no easy objects allowing to do the second proposition, while "hrefList" is a "list of objects href'ing us", so we'll take this. + * Then we keep a set of already visited elements, and do a DFS on this graph. if we find obj, then BOOM. + */ + +bool URIReference::_acceptObject(SPObject *obj) const { + //we go back following hrefList and parent to find if the object already references ourselves indirectly + std::set done; + SPObject * owner = getOwner(); + if(!owner)return true; + while(owner->cloned){ + std::vector positions; + while(owner->cloned){ + int position=0; + SPObject* c = owner->parent->firstChild(); + while(c != owner && dynamic_cast(c) ){position++;c=c->next;} + positions.push_back(position); + owner=owner->parent; + } + owner = ((SPUse*)owner)->get_original(); + for(int i=positions.size()-2;i>=0;i--)owner=owner->childList(false)[positions[i]]; + } + //once we have the "original" object (hopefully) we look at who is referencing it + std::list todo(owner->hrefList); + todo.push_front(owner->parent); + while(!todo.empty()){ + SPObject* e = todo.front(); + todo.pop_front(); + if(!dynamic_cast(e))continue; + if(done.insert(e).second){ + if(e==obj){return false;} + todo.push_front(e->parent); + todo.insert(todo.begin(),e->hrefList.begin(),e->hrefList.end()); + } + } + return true; +} + + + + void URIReference::attach(const URI &uri) throw(BadURIException) { SPDocument *document = NULL; diff --git a/src/uri-references.h b/src/uri-references.h index 0c51481cc..e56ea0612 100644 --- a/src/uri-references.h +++ b/src/uri-references.h @@ -15,11 +15,15 @@ */ #include +#include +#include #include #include #include "bad-uri-exception.h" #include "sp-object.h" +#include "sp-item.h" +#include "sp-use.h" namespace Inkscape { @@ -122,11 +126,7 @@ public: SPObject *getOwnerObject() { return _owner; } protected: - virtual bool _acceptObject(SPObject *obj) const { - (void)obj; - return true; - } - + virtual bool _acceptObject(SPObject *obj) const; private: SPObject *_owner; SPDocument *_owner_document; -- cgit v1.2.3 From e297259e8fb1fafb05019649a87ba030fbc7ad9c Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 15 Jul 2015 20:10:34 +0200 Subject: Add a script that simplifies syncing 2Geom changes (bzr r14246) --- src/2geom/sync.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 src/2geom/sync.sh (limited to 'src') diff --git a/src/2geom/sync.sh b/src/2geom/sync.sh new file mode 100755 index 000000000..a2c162903 --- /dev/null +++ b/src/2geom/sync.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +function usage { + echo "2Geom sync to upstream script" + echo "Usage: $0 path/to/2geom/checkout/dir" +} + +if [ "x$(which rsync)" = "x" ]; then + echo "rsync not found on your system, please install it" + exit 1 +fi + +if [ "x$1" = "x" ]; then + usage $0 + exit 64 +fi +if [ ! -d "$1" ]; then + usage $0 + exit 64 +fi +if [ ! -f "$1/src/2geom/path.h" ]; then + usage $0 + exit 64 +fi + +INK_2GEOM="$(dirname $0)/" +UPSTREAM_2GEOM="$1/src/2geom/" +rsync -r --existing \ + --exclude CMakeLists.txt --exclude sync.sh \ + "$UPSTREAM_2GEOM" "$INK_2GEOM" -- cgit v1.2.3 From 8d9336326e52ee6a181c658d57c7c3a3b776fcf8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 15 Jul 2015 20:18:11 +0200 Subject: Sync 2Geom to revision 2420. Should fix build failure on llvm-gcc 4.2 and an issue with powerstroke. (bzr r14247) --- src/2geom/ellipse.cpp | 52 +++++++++++++++++++++++++++++++++++++++------------ src/2geom/path.cpp | 3 --- 2 files changed, 40 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/2geom/ellipse.cpp b/src/2geom/ellipse.cpp index fed3bf86f..4b5ad9762 100644 --- a/src/2geom/ellipse.cpp +++ b/src/2geom/ellipse.cpp @@ -205,22 +205,50 @@ Ellipse::arc(Point const &ip, Point const &inner, Point const &fp) bool sweep_flag = false; // Determination of large arc flag: - // The arc is larger than half of the ellipse if the inner point - // is on the same side of the line going from the initial - // to the final point as the center of the ellipse - Point versor = fp - ip; - double sdist_c = cross(versor, _center - ip); - double sdist_inner = cross(versor, inner - ip); - - // if we have exactly half of an arc, do not set the large flag. - if (sdist_c != 0 && sgn(sdist_c) == sgn(sdist_inner)) { + // large_arc is false when the inner point is on the same side + // of the center---initial point line as the final point, AND + // is on the same side of the center---final point line as the + // initial point. + // Additionally, large_arc is always false when we have exactly + // 1/2 of an arc, i.e. the cross product of the center -> initial point + // and center -> final point vectors is zero. + // Negating the above leads to the condition for large_arc being true. + Point fv = fp - _center; + Point iv = ip - _center; + Point innerv = inner - _center; + double ifcp = cross(fv, iv); + + if (ifcp != 0 && (sgn(cross(fv, innerv)) != sgn(ifcp) || + sgn(cross(iv, innerv)) != sgn(-ifcp))) + { large_arc_flag = true; } + //cross(-iv, fv) && large_arc_flag + + // Determination of sweep flag: - // If the inner point is on the left side of the ip-fp line, - // we go in clockwise direction. - if (sdist_inner < 0) { + // For clarity, let's assume that Y grows up. Then the cross product + // is positive for points on the left side of a vector and negative + // on the right side of a vector. + // + // cross(?, v) > 0 + // o-------------------> + // cross(?, v) < 0 + // + // If the arc is small (large_arc_flag is false) and the final point + // is on the right side of the vector initial point -> center, + // we have to go in the direction of increasing angles + // (counter-clockwise) and the sweep flag is true. + // If the arc is large, the opposite is true, since we have to reach + // the final point going the long way - in the other direction. + // We can express this observation as: + // cross(_center - ip, fp - _center) < 0 xor large_arc flag + // This is equal to: + // cross(-iv, fv) < 0 xor large_arc flag + // But cross(-iv, fv) is equal to cross(fv, iv) due to antisymmetry + // of the cross product, so we end up with the condition below. + if ((ifcp < 0) ^ large_arc_flag) { sweep_flag = true; } diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp index 836e65013..871441751 100644 --- a/src/2geom/path.cpp +++ b/src/2geom/path.cpp @@ -441,7 +441,6 @@ std::vector Path::roots(Coord v, Dim2 d) const // The class below implements sweepline optimization for curve intersection in paths. // Instead of O(N^2), this takes O(N + X), where X is the number of overlaps // between the bounding boxes of curves. -namespace { struct CurveSweepTraits { struct Bound { @@ -512,8 +511,6 @@ private: Coord _precision; }; -} // end anonymous namespace - std::vector Path::intersect(Path const &other, Coord precision) const { std::vector result; -- cgit v1.2.3 From 3767f1ca97ac6dcacce110089fd7247669ab8e5b Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Wed, 15 Jul 2015 20:47:16 +0200 Subject: Update 2Geom to r2421, fix SBasis derivatives. Fixes LP bug #1473317. Fixed bugs: - https://launchpad.net/bugs/1473317 (bzr r14248) --- src/2geom/sbasis.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/2geom/sbasis.cpp b/src/2geom/sbasis.cpp index 4f1df621e..42d92d7b8 100644 --- a/src/2geom/sbasis.cpp +++ b/src/2geom/sbasis.cpp @@ -328,9 +328,9 @@ SBasis derivative(SBasis const &a) { } int k = a.size()-1; double d = (2*k+1)*(a[k][1] - a[k][0]); - if(d == 0) + if (d == 0 && k > 0) { c.pop_back(); - else { + } else { c[k][0] = d; c[k][1] = d; } @@ -351,9 +351,9 @@ void SBasis::derive() { // in place version } int k = size()-1; double d = (2*k+1)*((*this)[k][1] - (*this)[k][0]); - if(d == 0) + if (d == 0 && k > 0) { pop_back(); - else { + } else { (*this)[k][0] = d; (*this)[k][1] = d; } -- cgit v1.2.3 From b8027c4442f0e93903ff96c49fbd0c0e4d1444e3 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 16 Jul 2015 07:56:04 -0400 Subject: setStitching(), gajiosdfksdsfd (bzr r14249) --- src/helper/geom-pathstroke.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp index e5f207c66..c73a9e9e7 100644 --- a/src/helper/geom-pathstroke.cpp +++ b/src/helper/geom-pathstroke.cpp @@ -647,7 +647,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin const size_t k = (input.back_closed().isDegenerate() && input.closed()) ?input.size_default()-1:input.size_default(); for (size_t u = 0; u < k; u += 2) { - temp = Geom::Path(); + temp.clear(); offset_curve(temp, &input[u], width); @@ -661,7 +661,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin // odd number of paths if (u < k - 1) { - temp = Geom::Path(); + temp.clear(); offset_curve(temp, &input[u+1], width); tangents(tang, input[u], input[u+1]); outline_join(res, temp, tang[0], tang[1], width, miter, join); @@ -671,7 +671,7 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin if (input.closed()) { Geom::Curve const &c1 = res.back(); Geom::Curve const &c2 = res.front(); - temp = Geom::Path(); + temp.clear(); temp.append(c1); Geom::Path temp2; temp2.append(c2); -- cgit v1.2.3 From 1997b7aeecff6a01b3e319cd2a42a6029bc56ae7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 19 Jul 2015 15:22:31 +0200 Subject: Enable stitching in Spiro and SPCurve to prevent some crashes (bzr r14250) --- src/display/curve.cpp | 5 +++-- src/live_effects/spiro-converters.cpp | 6 +++++- src/live_effects/spiro-converters.h | 6 ++---- src/live_effects/spiro.h | 6 ++---- 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 386c63166..3024d1276 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -203,8 +203,9 @@ SPCurve::moveto(double x, double y) void SPCurve::moveto(Geom::Point const &p) { - _pathv.push_back( Geom::Path() ); // for some reason Geom::Path(p) does not work... - _pathv.back().start(p); + Geom::Path path(p); + path.setStitching(true); + _pathv.push_back(path); } /** diff --git a/src/live_effects/spiro-converters.cpp b/src/live_effects/spiro-converters.cpp index 3c7bdf99e..f116d5256 100644 --- a/src/live_effects/spiro-converters.cpp +++ b/src/live_effects/spiro-converters.cpp @@ -64,7 +64,11 @@ ConverterSPCurve::curveto(double x1, double y1, double x2, double y2, double x3, } - +ConverterPath::ConverterPath(Geom::Path &path) + : _path(path) +{ + _path.setStitching(true); +} void ConverterPath::moveto(double x, double y, bool is_open) diff --git a/src/live_effects/spiro-converters.h b/src/live_effects/spiro-converters.h index 83f6ebbc3..90855d2d6 100644 --- a/src/live_effects/spiro-converters.h +++ b/src/live_effects/spiro-converters.h @@ -25,7 +25,7 @@ class ConverterSPCurve : public ConverterBase { public: ConverterSPCurve(SPCurve &curve) : _curve(curve) - {} ; + {} virtual void moveto(double x, double y, bool is_open); virtual void lineto(double x, double y); @@ -45,9 +45,7 @@ private: */ class ConverterPath : public ConverterBase { public: - ConverterPath(Geom::Path &path) - : _path(path) - {} ; + ConverterPath(Geom::Path &path); virtual void moveto(double x, double y, bool is_open); virtual void lineto(double x, double y); diff --git a/src/live_effects/spiro.h b/src/live_effects/spiro.h index 0d85da74b..066b44ca8 100644 --- a/src/live_effects/spiro.h +++ b/src/live_effects/spiro.h @@ -25,11 +25,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA #define INKSCAPE_SPIRO_H #include "live_effects/spiro-converters.h" +#include <2geom/forward.h> class SPCurve; -namespace Geom { - class Path; -} namespace Spiro { @@ -53,4 +51,4 @@ double get_knot_th(const spiro_seg *s, int i); } // namespace Spiro -#endif // INKSCAPE_SPIRO_H \ No newline at end of file +#endif // INKSCAPE_SPIRO_H -- cgit v1.2.3 From 8417b110e22e3e56862c0deff4ae72e76a9958b1 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Sun, 19 Jul 2015 19:27:14 -0400 Subject: fix typo in intersection_point() (Bug 1475097) Fixed bugs: - https://launchpad.net/bugs/1475097 (bzr r14251) --- src/live_effects/lpe-powerstroke.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 6ce912bcb..f90d67d4e 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -49,7 +49,7 @@ static boost::optional intersection_point( Point const & origin_a, Point { Coord denom = cross(vector_a, vector_b); if (!are_near(denom,0.)){ - Coord t = (cross(origin_b, vector_a) + cross(origin_b, vector_b)) / denom; + Coord t = (cross(vector_b, origin_a) + cross(origin_b, vector_b)) / denom; return origin_a + t * vector_a; } return boost::none; -- cgit v1.2.3 From 535ed65a232ae48ed3b107304dc416ec5eba249e Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Wed, 22 Jul 2015 22:25:18 +0200 Subject: Fix a bug continuing a bezier path whith a LPE one like spiro or bspline on a start node (bzr r14252) --- src/ui/tools/freehand-base.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 4fad06c98..e8cbfcdbf 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -598,10 +598,9 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 || prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){ s = dc->overwrite_curve; - } else { - if (dc->sa->start) { - s = reverse_then_unref(s); - } + } + if (dc->sa->start) { + s = reverse_then_unref(s); } s->append_continuous(c, 0.0625); c->unref(); -- cgit v1.2.3 From f873250f0c426d7b281acd37d65c4e549eb204a3 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 24 Jul 2015 21:38:06 +0200 Subject: Make persistence of snap indicator configurable, and clean up the snapping tab in the preferences dialog Fixed bugs: - https://launchpad.net/bugs/1420301 (bzr r14253) --- src/display/snap-indicator.cpp | 11 ++++++++--- src/ui/dialog/inkscape-preferences.cpp | 26 +++++++++++++++++++------- src/ui/dialog/inkscape-preferences.h | 1 + src/ui/tools/tool-base.h | 7 ++++++- src/ui/widget/preferences-widget.cpp | 1 + src/ui/widget/preferences-widget.h | 1 + 6 files changed, 36 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 926b35599..17deea16d 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -256,7 +256,12 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap "shape", SP_KNOT_SHAPE_CROSS, NULL ); - const int timeout_val = 4000; + double timeout_val = prefs->getDouble("/options/snapindicatorpersistence/value", 2.0); + if (timeout_val < 0.1) { + timeout_val = 0.1; // a zero value would mean infinite persistence (i.e. until new snap occurs) + // Besides, negatives values would ....? + } + // The snap indicator will be deleted after some time-out, and sp_canvas_item_dispose // will be called. This will set canvas->current_item to NULL if the snap indicator was @@ -272,7 +277,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap SP_CTRL(canvasitem)->pickable = false; SP_CTRL(canvasitem)->moveto(p.getPoint()); - _snaptarget = _desktop->add_temporary_canvasitem(canvasitem, timeout_val); + _snaptarget = _desktop->add_temporary_canvasitem(canvasitem, timeout_val*1000.0); _snaptarget_is_presnap = pre_snap; // Display the tooltip, which reveals the type of snap source and the type of snap target @@ -307,7 +312,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap SP_CANVASTEXT(canvas_tooltip)->anchor_position = TEXT_ANCHOR_CENTER; g_free(tooltip_str); - _snaptarget_tooltip = _desktop->add_temporary_canvasitem(canvas_tooltip, timeout_val); + _snaptarget_tooltip = _desktop->add_temporary_canvasitem(canvas_tooltip, timeout_val*1000.0); } // Display the bounding box, if we snapped to one diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 3b0731953..98695e080 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1229,26 +1229,38 @@ void InkscapePreferences::initPageBehavior() this->AddPage(_page_scrolling, _("Scrolling"), iter_behavior, PREFS_PAGE_BEHAVIOR_SCROLLING); // Snapping options + _page_snapping.add_group_header( _("Snap indicator")); + _snap_indicator.init( _("Enable snap indicator"), "/options/snapindicator/value", true); - _page_snapping.add_line( false, "", _snap_indicator, "", + _page_snapping.add_line( true, "", _snap_indicator, "", _("After snapping, a symbol is drawn at the point that has snapped")); - _snap_delay.init("/options/snapdelay/value", 0, 1000, 50, 100, 300, 0); - _page_snapping.add_line( false, _("_Delay (in ms):"), _snap_delay, "", - _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true); + _snap_indicator.changed_signal.connect( sigc::mem_fun(_snap_persistence, &Gtk::Widget::set_sensitive) ); + + _snap_persistence.init("/options/snapindicatorpersistence/value", 0.1, 10, 0.1, 1, 2, 1); + _page_snapping.add_line( true, _("Snap indicator persistence (in seconds):"), _snap_persistence, "", + _("Controls how long the snap indicator message will be shown, before it disappears"), true); + + _page_snapping.add_group_header( _("What should snap")); _snap_closest_only.init( _("Only snap the node closest to the pointer"), "/options/snapclosestonly/value", false); - _page_snapping.add_line( false, "", _snap_closest_only, "", + _page_snapping.add_line( true, "", _snap_closest_only, "", _("Only try to snap the node that is initially closest to the mouse pointer")); _snap_weight.init("/options/snapweight/value", 0, 1, 0.1, 0.2, 0.5, 1); - _page_snapping.add_line( false, _("_Weight factor:"), _snap_weight, "", + _page_snapping.add_line( true, _("_Weight factor:"), _snap_weight, "", _("When multiple snap solutions are found, then Inkscape can either prefer the closest transformation (when set to 0), or prefer the node that was initially the closest to the pointer (when set to 1)"), true); _snap_mouse_pointer.init( _("Snap the mouse pointer when dragging a constrained knot"), "/options/snapmousepointer/value", false); - _page_snapping.add_line( false, "", _snap_mouse_pointer, "", + _page_snapping.add_line( true, "", _snap_mouse_pointer, "", _("When dragging a knot along a constraint line, then snap the position of the mouse pointer instead of snapping the projection of the knot onto the constraint line")); + _page_snapping.add_group_header( _("Delayed snap")); + + _snap_delay.init("/options/snapdelay/value", 0, 1, 0.1, 0.2, 0.3, 1); + _page_snapping.add_line( true, _("Delay (in seconds):"), _snap_delay, "", + _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true); + this->AddPage(_page_snapping, _("Snapping"), iter_behavior, PREFS_PAGE_BEHAVIOR_SNAPPING); // Steps options diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index dcea91741..7e0184c55 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -322,6 +322,7 @@ protected: UI::Widget::PrefCheckButton _importexport_import_res_override; UI::Widget::PrefSlider _snap_delay; UI::Widget::PrefSlider _snap_weight; + UI::Widget::PrefSlider _snap_persistence; UI::Widget::PrefCheckButton _font_dialog; UI::Widget::PrefCombo _font_unit_type; UI::Widget::PrefCheckButton _font_output_px; diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h index 7a6ab83e7..58eb6f88e 100644 --- a/src/ui/tools/tool-base.h +++ b/src/ui/tools/tool-base.h @@ -75,7 +75,12 @@ public: Inkscape::Preferences *prefs = Inkscape::Preferences::get(); double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000); - _timer_id = g_timeout_add(value, &sp_event_context_snap_watchdog_callback, this); + // We used to have this specified in milliseconds; this has changed to seconds now for consistency's sake + if (value > 1) { // Apparently we have an old preference file, this value must have been in milliseconds; + value = value / 1000.0; // now convert this value to seconds + } + + _timer_id = g_timeout_add(value*1000.0, &sp_event_context_snap_watchdog_callback, this); _event = gdk_event_copy((GdkEvent*) event); ((GdkEventMotion *)_event)->time = GDK_CURRENT_TIME; diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp index 72597e4d9..e906762e3 100644 --- a/src/ui/widget/preferences-widget.cpp +++ b/src/ui/widget/preferences-widget.cpp @@ -205,6 +205,7 @@ void PrefCheckButton::init(Glib::ustring const &label, Glib::ustring const &pref void PrefCheckButton::on_toggled() { + this->changed_signal.emit(this->get_active()); if (this->get_visible()) //only take action if the user toggled it { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h index 8b75b8368..1d2d77699 100644 --- a/src/ui/widget/preferences-widget.h +++ b/src/ui/widget/preferences-widget.h @@ -59,6 +59,7 @@ class PrefCheckButton : public Gtk::CheckButton public: void init(Glib::ustring const &label, Glib::ustring const &prefs_path, bool default_value); + sigc::signal changed_signal; protected: Glib::ustring _prefs_path; void on_toggled(); -- cgit v1.2.3 From 1867f123d5c52008738a2873abda555d3bd882f3 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 24 Jul 2015 22:16:07 +0200 Subject: 3D box tool: the shift key must not prevent snapping of the vanishing point. It must only serve to separate the vanishing points, in case of multiple boxes sharing the same vanishing points Fixed bugs: - https://launchpad.net/bugs/1460415 (bzr r14254) --- src/vanishing-point.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp index 46f895c06..553e3a31d 100644 --- a/src/vanishing-point.cpp +++ b/src/vanishing-point.cpp @@ -130,7 +130,7 @@ vp_knot_moved_handler (SPKnot *knot, Geom::Point const &ppointer, guint state, g // FIXME: Do we need to create a new dragger as well? dragger->updateZOrders (); DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_CONTEXT_3DBOX, - _("Split vanishing points")); + _("Split vanishing points")); return; } } @@ -175,22 +175,24 @@ vp_knot_moved_handler (SPKnot *knot, Geom::Point const &ppointer, guint state, g // as is currently the case. DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_CONTEXT_3DBOX, - _("Merge vanishing points")); + _("Merge vanishing points")); return; } } + } - // We didn't snap to another dragger, so we'll try a regular snap - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE)); - m.unSetup(); - if (s.getSnapped()) { - p = s.getPoint(); - knot->moveto(p); - } + // We didn't hit the return statement above, so we didn't snap to another dragger. Therefore we'll now try a regular snap + // Regardless of the status of the SHIFT key, we will try to snap; Here SHIFT does not disable snapping, as the shift key + // has a different purpose in this context (see above) + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE)); + m.unSetup(); + if (s.getSnapped()) { + p = s.getPoint(); + knot->moveto(p); } dragger->point = p; // FIXME: Is dragger->point being used at all? @@ -241,7 +243,7 @@ vp_knot_ungrabbed_handler (SPKnot *knot, guint /*state*/, gpointer data) g_return_if_fail (dragger->parent); g_return_if_fail (dragger->parent->document); DocumentUndo::done(dragger->parent->document, SP_VERB_CONTEXT_3DBOX, - _("3D box: Move vanishing point")); + _("3D box: Move vanishing point")); } unsigned int VanishingPoint::global_counter = 0; @@ -630,7 +632,7 @@ VPDrag::updateBoxHandles () // FIXME: Is there a way to update the knots without accessing the // (previously) statically linked function KnotHolder::update_knots? - std::vector sel = selection->itemList(); + std::vector sel = selection->itemList(); if (sel.empty()) return; // no selection -- cgit v1.2.3