diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2015-07-24 19:53:33 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2015-07-24 19:53:33 +0000 |
| commit | 5a37f06c70e0e4e2519812564f4dcdced7c0246a (patch) | |
| tree | f959f73813cb6f968072aee1100323b24e294136 /src/display | |
| parent | update to trunk (diff) | |
| parent | Fix a bug continuing a bezier path whith a LPE one like spiro or bspline on a... (diff) | |
| download | inkscape-5a37f06c70e0e4e2519812564f4dcdced7c0246a.tar.gz inkscape-5a37f06c70e0e4e2519812564f4dcdced7c0246a.zip | |
update to trunk
(bzr r13879.1.17)
Diffstat (limited to 'src/display')
| -rw-r--r-- | src/display/cairo-utils.cpp | 8 | ||||
| -rw-r--r-- | src/display/canvas-arena.cpp | 2 | ||||
| -rw-r--r-- | src/display/canvas-axonomgrid.cpp | 4 | ||||
| -rw-r--r-- | src/display/canvas-grid.cpp | 28 | ||||
| -rw-r--r-- | src/display/curve-test.h | 75 | ||||
| -rw-r--r-- | src/display/curve.cpp | 39 | ||||
| -rw-r--r-- | src/display/curve.h | 2 | ||||
| -rw-r--r-- | src/display/drawing-image.cpp | 2 | ||||
| -rw-r--r-- | src/display/drawing-text.cpp | 28 | ||||
| -rw-r--r-- | src/display/snap-indicator.cpp | 15 | ||||
| -rw-r--r-- | src/display/sp-canvas-item.h | 7 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 30 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 1 |
13 files changed, 128 insertions, 113 deletions
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp index e1f12b04b..59e190676 100644 --- a/src/display/cairo-utils.cpp +++ b/src/display/cairo-utils.cpp @@ -18,9 +18,7 @@ #include <glib/gstdio.h> #include <glibmm/fileutils.h> #include <2geom/pathvector.h> -#include <2geom/bezier-curve.h> -#include <2geom/elliptical-arc.h> -#include <2geom/hvlinesegment.h> +#include <2geom/curves.h> #include <2geom/affine.h> #include <2geom/point.h> #include <2geom/path.h> @@ -531,7 +529,7 @@ feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & tran case 2: { Geom::QuadraticBezier const *quadratic_bezier = static_cast<Geom::QuadraticBezier const*>(&c); - std::vector<Geom::Point> points = quadratic_bezier->points(); + std::vector<Geom::Point> points = quadratic_bezier->controlPoints(); points[0] *= trans; points[1] *= trans; points[2] *= trans; @@ -554,7 +552,7 @@ feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & tran case 3: { Geom::CubicBezier const *cubic_bezier = static_cast<Geom::CubicBezier const*>(&c); - std::vector<Geom::Point> points = cubic_bezier->points(); + std::vector<Geom::Point> points = cubic_bezier->controlPoints(); //points[0] *= trans; // don't do this one here for fun: it is only needed for optimized strokes points[1] *= trans; points[2] *= trans; diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index 8738b93e4..ec99eca9a 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -290,7 +290,7 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event) ret = sp_canvas_arena_send_event (arena, (GdkEvent *) &ec); } } - ret = sp_canvas_arena_send_event (arena, event); + ret = ret || sp_canvas_arena_send_event (arena, event); break; case GDK_SCROLL: { diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index a2df86823..1794ccbab 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -17,10 +17,6 @@ # include "config.h" #endif -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include <glibmm/threads.h> -#endif - #include <gtkmm/box.h> #include <gtkmm/label.h> diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 9b9f64529..decf93626 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -17,10 +17,6 @@ # include "config.h" #endif -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include <glibmm/threads.h> -#endif - #include <gtkmm/box.h> #include <gtkmm/label.h> @@ -910,7 +906,7 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) gdouble const syg = floor ((buf->rect.top() - ow[Geom::Y]) / sw[Geom::Y]) * sw[Geom::Y] + ow[Geom::Y]; gint const ylinestart = round((syg - ow[Geom::Y]) / sw[Geom::Y]); - //set correct coloring, depending preference (when zoomed out, always major coloring or minor coloring) + // no_emphasize_when_zoomedout determines color (minor or major) when only major grid lines/dots shown. Inkscape::Preferences *prefs = Inkscape::Preferences::get(); guint32 _empcolor; bool no_emp_when_zoomed_out = prefs->getBool("/options/grids/no_emphasize_when_zoomedout", false); @@ -926,6 +922,7 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE); if (!render_dotted) { + // Line grid gint ylinenum; gdouble y; for (y = syg, ylinenum = ylinestart; y < buf->rect.bottom(); y += sw[Geom::Y], ylinenum++) { @@ -948,8 +945,23 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) } } } else { + // Dotted grid gint ylinenum; gdouble y; + + // alpha needs to be larger than in the line case to maintain a similar visual impact but + // setting it to the maximal value makes the dots dominant in some cases. Solution, + // increase the alpha by a factor of 4. This then allows some user adjustment. + guint32 _empdot = (_empcolor & 0xff) << 2; + if (_empdot > 0xff) + _empdot = 0xff; + _empdot += (_empcolor & 0xffffff00); + + guint32 _colordot = (color & 0xff) << 2; + if (_colordot > 0xff) + _colordot = 0xff; + _colordot += (color & 0xffffff00); + for (y = syg, ylinenum = ylinestart; y < buf->rect.bottom(); y += sw[Geom::Y], ylinenum++) { gint const iy = round(y); @@ -961,13 +973,15 @@ CanvasXYGrid::Render (SPCanvasBuf *buf) || (!scaled[Geom::Y] && (ylinenum % empspacing) != 0) || ((scaled[Geom::X] || scaled[Geom::Y]) && no_emp_when_zoomed_out) ) { - grid_dot (buf, ix, iy, color | (guint32)0x000000FF); // put alpha to max value + // Minor point: dot only + grid_dot (buf, ix, iy, _colordot); // | (guint32)0x000000FF); // put alpha to max value } else { + // Major point: small cross gint const pitch = 1; grid_dot (buf, ix-pitch, iy, _empcolor); grid_dot (buf, ix+pitch, iy, _empcolor); - grid_dot (buf, ix, iy, _empcolor | (guint32)0x000000FF); // put alpha to max value + grid_dot (buf, ix, iy, _empdot ); // | (guint32)0x000000FF); // put alpha to max value grid_dot (buf, ix, iy-pitch, _empcolor); grid_dot (buf, ix, iy+pitch, _empcolor); diff --git a/src/display/curve-test.h b/src/display/curve-test.h index 3d698ca07..f921a5361 100644 --- a/src/display/curve-test.h +++ b/src/display/curve-test.h @@ -16,17 +16,18 @@ public: CurveTest() : path4(Geom::Point(3,5)) // Just a moveto { // Closed path - path1.append(Geom::HLineSegment(Geom::Point(0,0),1)); - path1.append(Geom::VLineSegment(Geom::Point(1,0),1)); + path1.append(Geom::LineSegment(Geom::Point(0,0),Geom::Point(1,0))); + path1.append(Geom::LineSegment(Geom::Point(1,0),Geom::Point(1,1))); path1.close(); // Closed path (ClosingSegment is zero length) path2.append(Geom::LineSegment(Geom::Point(2,0),Geom::Point(3,0))); - // TODO fix path2.append(Geom::BezierCurve<3>(Geom::Point(3,0),Geom::Point(2,1),Geom::Point(1,1),Geom::Point(2,0))); + path2.append(Geom::CubicBezier(Geom::Point(3,0),Geom::Point(2,1),Geom::Point(1,1),Geom::Point(2,0))); path2.close(); // Open path - path3.append(Geom::SVGEllipticalArc(Geom::Point(4,0),1,2,M_PI,false,false,Geom::Point(5,1))); - path3.append(Geom::VLineSegment(Geom::Point(5,1),2), Geom::Path::STITCH_DISCONTINUOUS); - path3.append(Geom::HLineSegment(Geom::Point(6,4),2), Geom::Path::STITCH_DISCONTINUOUS); + path3.setStitching(true); + path3.append(Geom::EllipticalArc(Geom::Point(4,0),1,2,M_PI,false,false,Geom::Point(5,1))); + path3.append(Geom::LineSegment(Geom::Point(5,1),Geom::Point(5,2))); + path3.append(Geom::LineSegment(Geom::Point(6,4),Geom::Point(2,4))); } virtual ~CurveTest() {} @@ -49,17 +50,17 @@ public: TS_ASSERT_EQUALS(curve.get_segment_count() , 0u); } { // Individual paths - Geom::PathVector pv(1, Geom::Path()); + Geom::PathVector pv((Geom::Path())); pv[0] = path1; TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 3u); pv[0] = path2; - TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 3u); + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 2u); pv[0] = path3; TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 4u); pv[0] = path4; TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 0u); pv[0].close(); - TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 1u); + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 0u); } { // Combination Geom::PathVector pv; @@ -68,7 +69,7 @@ public: pv.push_back(path3); pv.push_back(path4); SPCurve curve(pv); - TS_ASSERT_EQUALS(curve.get_segment_count() , 10u); + TS_ASSERT_EQUALS(curve.get_segment_count() , 9u); } } @@ -86,7 +87,7 @@ public: TS_ASSERT_EQUALS(curve.nodes_in_path() , 1u); } { // Individual paths - Geom::PathVector pv(1, Geom::Path()); + Geom::PathVector pv((Geom::Path())); pv[0] = path1; TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 3u); pv[0] = path2; @@ -112,28 +113,28 @@ public: void testIsEmpty() { TS_ASSERT(SPCurve(Geom::PathVector()).is_empty()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path1)).is_empty()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path2)).is_empty()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path3)).is_empty()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path4)).is_empty()); + TS_ASSERT(!SPCurve(path1).is_empty()); + TS_ASSERT(!SPCurve(path2).is_empty()); + TS_ASSERT(!SPCurve(path3).is_empty()); + TS_ASSERT(!SPCurve(path4).is_empty()); } void testIsClosed() { TS_ASSERT(!SPCurve(Geom::PathVector()).is_closed()); - Geom::PathVector pv(1, Geom::Path()); + Geom::PathVector pv((Geom::Path())); TS_ASSERT(!SPCurve(pv).is_closed()); pv[0].close(); TS_ASSERT(SPCurve(pv).is_closed()); - TS_ASSERT(SPCurve(Geom::PathVector(1, path1)).is_closed()); - TS_ASSERT(SPCurve(Geom::PathVector(1, path2)).is_closed()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path3)).is_closed()); - TS_ASSERT(!SPCurve(Geom::PathVector(1, path4)).is_closed()); + TS_ASSERT(SPCurve(path1).is_closed()); + TS_ASSERT(SPCurve(path2).is_closed()); + TS_ASSERT(!SPCurve(path3).is_closed()); + TS_ASSERT(!SPCurve(path4).is_closed()); } void testLastFirstSegment() { - Geom::PathVector pv(1, path4); + Geom::PathVector pv(path4); TS_ASSERT_EQUALS(SPCurve(pv).first_segment() , (void*)0); TS_ASSERT_EQUALS(SPCurve(pv).last_segment() , (void*)0); pv[0].close(); @@ -185,10 +186,10 @@ public: void testFirstPoint() { - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path1)).first_point()) , Geom::Point(0,0)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path2)).first_point()) , Geom::Point(2,0)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path3)).first_point()) , Geom::Point(4,0)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path4)).first_point()) , Geom::Point(3,5)); + TS_ASSERT_EQUALS(*(SPCurve(path1).first_point()) , Geom::Point(0,0)); + TS_ASSERT_EQUALS(*(SPCurve(path2).first_point()) , Geom::Point(2,0)); + TS_ASSERT_EQUALS(*(SPCurve(path3).first_point()) , Geom::Point(4,0)); + TS_ASSERT_EQUALS(*(SPCurve(path4).first_point()) , Geom::Point(3,5)); Geom::PathVector pv; TS_ASSERT(!SPCurve(pv).first_point()); pv.push_back(path1); @@ -201,10 +202,10 @@ public: void testLastPoint() { - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path1)).last_point()) , Geom::Point(0,0)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path2)).last_point()) , Geom::Point(2,0)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path3)).last_point()) , Geom::Point(8,4)); - TS_ASSERT_EQUALS(*(SPCurve(Geom::PathVector(1, path4)).last_point()) , Geom::Point(3,5)); + TS_ASSERT_EQUALS(*(SPCurve(path1).last_point()) , Geom::Point(0,0)); + TS_ASSERT_EQUALS(*(SPCurve(path2).last_point()) , Geom::Point(2,0)); + TS_ASSERT_EQUALS(*(SPCurve(path3).last_point()) , Geom::Point(8,4)); + TS_ASSERT_EQUALS(*(SPCurve(path4).last_point()) , Geom::Point(3,5)); Geom::PathVector pv; TS_ASSERT(!SPCurve(pv).last_point()); pv.push_back(path1); @@ -217,10 +218,10 @@ public: void testSecondPoint() { - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path1)).second_point()) , Geom::Point(1,0)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path2)).second_point()) , Geom::Point(3,0)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path3)).second_point()) , Geom::Point(5,1)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path4)).second_point()) , Geom::Point(3,5)); + TS_ASSERT_EQUALS( *(SPCurve(path1).second_point()) , Geom::Point(1,0)); + TS_ASSERT_EQUALS( *(SPCurve(path2).second_point()) , Geom::Point(3,0)); + TS_ASSERT_EQUALS( *(SPCurve(path3).second_point()) , Geom::Point(5,1)); + TS_ASSERT_EQUALS( *(SPCurve(path4).second_point()) , Geom::Point(3,5)); Geom::PathVector pv; pv.push_back(path1); pv.push_back(path2); @@ -232,10 +233,10 @@ public: void testPenultimatePoint() { - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path1)).penultimate_point()) , Geom::Point(1,1)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path2)).penultimate_point()) , Geom::Point(3,0)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path3)).penultimate_point()) , Geom::Point(6,4)); - TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(1, path4)).penultimate_point()) , Geom::Point(3,5)); + TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(path1)).penultimate_point()) , Geom::Point(1,1)); + TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(path2)).penultimate_point()) , Geom::Point(3,0)); + TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(path3)).penultimate_point()) , Geom::Point(6,4)); + TS_ASSERT_EQUALS( *(SPCurve(Geom::PathVector(path4)).penultimate_point()) , Geom::Point(3,5)); Geom::PathVector pv; pv.push_back(path1); pv.push_back(path2); diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 54a62939d..3024d1276 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -31,14 +31,12 @@ SPCurve::SPCurve() : _refcount(1), _pathv() -{ -} +{} SPCurve::SPCurve(Geom::PathVector const& pathv) : _refcount(1), _pathv(pathv) -{ -} +{} SPCurve * SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides) @@ -90,13 +88,7 @@ SPCurve::get_pathvector() const size_t SPCurve::get_segment_count() const { - size_t nr = 0; - for(Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); ++it) { - nr += (*it).size(); - - if (it->closed()) nr += 1; - } - return nr; + return _pathv.curveCount(); } /** @@ -211,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); } /** @@ -476,7 +469,7 @@ SPCurve::last_point() const SPCurve * SPCurve::create_reverse() const { - SPCurve *new_curve = new SPCurve(Geom::reverse_paths_and_order(_pathv)); + SPCurve *new_curve = new SPCurve(_pathv.reversed()); return new_curve; } @@ -635,20 +628,10 @@ SPCurve::nodes_in_path() const { size_t nr = 0; for(Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); ++it) { - nr += (*it).size(); - - nr++; // count last node (this works also for closed paths because although they don't have a 'last node', they do have an extra segment - - // do not count closing knot double for zero-length closing line segments - // however, if the path is only a moveto, and is closed, do not subtract 1 (otherwise the result will be zero nodes) - if ( it->closed() - && ((*it).size() != 0) ) - { - Geom::Curve const &c = it->back_closed(); - if (are_near(c.initialPoint(), c.finalPoint())) { - nr--; - } - } + // if the path does not have any segments, it is a naked moveto, + // and therefore any path has at least one valid node + size_t psize = std::max<size_t>(1, it->size_closed()); + nr += psize; } return nr; diff --git a/src/display/curve.h b/src/display/curve.h index 5fad75b18..42b899210 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -13,7 +13,7 @@ #ifndef SEEN_DISPLAY_CURVE_H #define SEEN_DISPLAY_CURVE_H -#include <2geom/forward.h> +#include <2geom/pathvector.h> #include <cstddef> #include <boost/optional.hpp> diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp index 8fe337959..1594614ac 100644 --- a/src/display/drawing-image.cpp +++ b/src/display/drawing-image.cpp @@ -172,7 +172,7 @@ static double distance_to_segment (Geom::Point const &p, Geom::Point const &a1, Geom::Point const &a2) { Geom::LineSegment l(a1, a2); - Geom::Point np = l.pointAt(l.nearestPoint(p)); + Geom::Point np = l.pointAt(l.nearestTime(p)); return Geom::distance(np, p); } diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index e20a7ff2a..a3ca7173a 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -91,9 +91,24 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext if (_transform) { scale_bigbox /= _transform->descrim(); } + - Geom::Rect bigbox(Geom::Point(-_width*scale_bigbox*0.1, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1)); - Geom::Rect b = bigbox * ctx.ctm; + /* Because there can be text decorations the bounding box must correspond in Y to a little above the glyph's ascend + and a little below its descend. This leaves room for overline and underline. The left and right sides + come from the glyph's bounding box. Note that the initial direction of ascender is positive down in Y, and + this flips after the transform is applied. So change the sign on descender. 1.1 provides a little extra space + above and below the max/min y positions of the letters to place the text decorations.*/ + + Geom::Rect b; + if(_drawable){ + Geom::OptRect tiltb = bounds_exact(*_font->PathVector(_glyph)); + Geom::Rect bigbox(Geom::Point(tiltb->left(),-_dsc*scale_bigbox*1.1),Geom::Point(tiltb->right(),_asc*scale_bigbox*1.1)); + b = bigbox * ctx.ctm; + } + else { // Fallback, spaces mostly + Geom::Rect bigbox(Geom::Point(0.0, -_dsc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, _asc*scale_bigbox*1.1)); + b = bigbox * ctx.ctm; + } /* The pick box matches the characters as best as it can, leaving no extra space above or below @@ -108,11 +123,11 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext if(_drawable){ pb = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm); } - if(!pb){ // Fallback + if(!pb){ // Fallback, spaces mostly Geom::Rect pbigbox(Geom::Point(0.0, _asc*scale_bigbox*0.66),Geom::Point(_width*scale_bigbox, 0.0)); pb = pbigbox * ctx.ctm; } - + #if 0 /* FIXME if this is commented out then not even an approximation of pick on decorations */ /* adjust the pick box up or down to include the decorations. @@ -214,7 +229,7 @@ DrawingText::addComponent(font_instance *font, int glyph, Geom::Affine const &tr ng->setGlyph(font, glyph, trans); if(font->PathVector(glyph)){ ng->_drawable = true; } else { ng->_drawable = false; } - ng->_width = width; // only used when _drawable = false + ng->_width = width; // used especially when _drawable = false, otherwise, it is the advance of the font ng->_asc = ascent; // of font, not of this one character ng->_dsc = descent; // of font, not of this one character ng->_pl = phase_length; // used for phase of dots, dashes, and wavy @@ -367,7 +382,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas /* returns scaled line thickness */ void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool under) { - if (_nrstyle.font_size < 1.0e-32)return; // would cause a divide by zero and nothing would be visible anyway + if ( _nrstyle.font_size <= 1.0e-32 )return; // might cause a divide by zero or overflow and nothing would be visible anyway double tsp_width_adj = _nrstyle.tspan_width / _nrstyle.font_size; double tsp_asc_adj = _nrstyle.ascender / _nrstyle.font_size; double tsp_size_adj = (_nrstyle.ascender + _nrstyle.descender) / _nrstyle.font_size; @@ -381,6 +396,7 @@ void DrawingText::decorateItem(DrawingContext &dc, double phase_length, bool und Geom::Point p2; // All lines must be the same thickness, in combinations, line_through trumps underline double thickness = final_underline_thickness; + if ( thickness <= 1.0e-32 )return; // might cause a divide by zero or overflow and nothing would be visible anyway dc.setTolerance(0.5); // Is this really necessary... could effect dots. if( under ) { diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 8c0c8163f..926b35599 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -258,6 +258,19 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap const int timeout_val = 4000; + // 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 + // the current item, after which any events will go to the root handler instead of any + // item handler. Dragging an object which has just snapped might therefore not be possible + // without selecting / repicking it again. To avoid this, we make sure here that the + // snap indicator will never be picked, and will therefore never be the current item. + // Reported bugs: + // - scrolling when hovering above a pre-snap indicator won't work (for example) + // (https://bugs.launchpad.net/inkscape/+bug/522335/comments/8) + // - dragging doesn't work without repicking + // (https://bugs.launchpad.net/inkscape/+bug/1420301/comments/15) + SP_CTRL(canvasitem)->pickable = false; + SP_CTRL(canvasitem)->moveto(p.getPoint()); _snaptarget = _desktop->add_temporary_canvasitem(canvasitem, timeout_val); _snaptarget_is_presnap = pre_snap; @@ -282,6 +295,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap SPCanvasItem *canvas_tooltip = sp_canvastext_new(_desktop->getTempGroup(), _desktop, tooltip_pos, tooltip_str); sp_canvastext_set_fontsize(SP_CANVASTEXT(canvas_tooltip), fontsize); + SP_CANVASTEXT(canvas_tooltip)->pickable = false; // See the extensive comment above SP_CANVASTEXT(canvas_tooltip)->rgba = 0xffffffff; SP_CANVASTEXT(canvas_tooltip)->outline = false; SP_CANVASTEXT(canvas_tooltip)->background = true; @@ -306,6 +320,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap SP_CTRLRECT(box)->setRectangle(*bbox); SP_CTRLRECT(box)->setColor(pre_snap ? 0x7f7f7fff : 0xff0000ff, 0, 0); SP_CTRLRECT(box)->setDashed(true); + SP_CTRLRECT(box)->pickable = false; // See the extensive comment above sp_canvas_item_move_to_z(box, 0); _snaptarget_bbox = _desktop->add_temporary_canvasitem(box, timeout_val); } diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h index 3b7b7bd4f..3e9e085a0 100644 --- a/src/display/sp-canvas-item.h +++ b/src/display/sp-canvas-item.h @@ -69,7 +69,12 @@ struct SPCanvasItem { gboolean visible; gboolean need_update; gboolean need_affine; - + + // If true, then SPCanvasGroup::point() and sp_canvas_item_invoke_point() will calculate + // the distance to the pointer, such that this item can be picked in pickCurrentItem() + // Only if an item can be picked, then it can be set as current_item and receive events! + bool pickable; + bool in_destruction; }; diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 305b0950a..5efc4ce86 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -375,6 +375,7 @@ sp_canvas_item_init(SPCanvasItem *item) // used for rubberbanding, path outline, etc. item->visible = TRUE; item->in_destruction = false; + item->pickable = true; } SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, gchar const *first_arg_name, ...) @@ -728,7 +729,6 @@ bool sp_canvas_item_is_visible(SPCanvasItem *item) return item->visible; } - /** * Sets visible flag on item and requests a redraw. */ @@ -1009,21 +1009,21 @@ double SPCanvasGroup::point(SPCanvasItem *item, Geom::Point p, SPCanvasItem **ac if ((child->x1 <= x2) && (child->y1 <= y2) && (child->x2 >= x1) && (child->y2 >= y1)) { SPCanvasItem *point_item = NULL; // cater for incomplete item implementations - int has_point; - if (child->visible && SP_CANVAS_ITEM_GET_CLASS(child)->point) { + int pickable; + if (child->visible && child->pickable && SP_CANVAS_ITEM_GET_CLASS(child)->point) { dist = sp_canvas_item_invoke_point(child, p, &point_item); - has_point = TRUE; + pickable = TRUE; } else { - has_point = FALSE; + pickable = FALSE; } - // This metric should be improved, because in case of (partly) overlapping items we will now + // TODO: This metric should be improved, because in case of (partly) overlapping items we will now // always select the last one that has been added to the group. We could instead select the one // of which the center is the closest, for example. One can then move to the center // of the item to be focused, and have that one selected. Of course this will only work if the // centers are not coincident, but at least it's better than what we have now. // See the extensive comment in Inkscape::SelTrans::_updateHandles() - if (has_point && point_item && ((int) (dist + 0.5) <= item->canvas->close_enough)) { + if (pickable && point_item && ((int) (dist + 0.5) <= item->canvas->close_enough)) { best = dist; *actual_item = point_item; } @@ -1480,20 +1480,6 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event) if (canvas->grabbed_item && !is_descendant (canvas->current_item, canvas->grabbed_item)) { item = canvas->grabbed_item; } else { - // Make sure that current_item is up-to-date. If a snap indicator was just deleted, then - // sp_canvas_item_dispose has been called and there is no current_item specified. We need - // that though because otherwise we don't know where to send this event to, leading to a - // lost event. We can't wait for idle events to have current_item updated, we need it now! - // Otherwise, scrolling when hovering above a pre-snap indicator won't work (for example) - // See this bug report: https://bugs.launchpad.net/inkscape/+bug/522335/comments/8 - if (canvas->need_repick && !canvas->in_repick && event->type == GDK_SCROLL) { - // To avoid side effects, we'll only do this for scroll events, because this is the - // only thing we want to fix here. An example of a reported side effect is that - // otherwise selection of nodes in the node editor by dragging a rectangle using a - // tablet will break - canvas->need_repick = FALSE; - pickCurrentItem(canvas, reinterpret_cast<GdkEvent *>(event)); - } item = canvas->current_item; } @@ -1527,7 +1513,7 @@ int SPCanvasImpl::pickCurrentItem(SPCanvas *canvas, GdkEvent *event) { int button_down = 0; - if (!canvas->root) // canvas may have already be destroyed by closing desktop durring interrupted display! + if (!canvas->root) // canvas may have already be destroyed by closing desktop during interrupted display! return FALSE; int retval = FALSE; diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 48c3de2fc..65b06ade8 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -23,6 +23,7 @@ #endif #include <gtk/gtk.h> +#include <stdint.h> #include <glibmm/ustring.h> #include <2geom/affine.h> #include <2geom/rect.h> |
