From 35a96bde514a8897f6f0fcc41c5833bf63df2e2a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:29:01 +0200 Subject: Adding upstream version 1.0.2. Signed-off-by: Daniel Baumann --- src/rubberband.cpp | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/rubberband.cpp (limited to 'src/rubberband.cpp') diff --git a/src/rubberband.cpp b/src/rubberband.cpp new file mode 100644 index 0000000..3519ee8 --- /dev/null +++ b/src/rubberband.cpp @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Rubberbanding selector. + * + * Author: + * Lauris Kaplinski + * Jon A. Cruz + * + * Copyright (C) 1999-2002 Lauris Kaplinski + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "display/sodipodi-ctrlrect.h" +#include "desktop.h" + +#include "rubberband.h" +#include "display/sp-canvas.h" +#include "display/canvas-bpath.h" +#include "display/curve.h" + +Inkscape::Rubberband *Inkscape::Rubberband::_instance = nullptr; + +Inkscape::Rubberband::Rubberband(SPDesktop *dt) + : _desktop(dt), _rect(nullptr), _touchpath(nullptr), _started(false) +{ + _points.clear(); + _mode = RUBBERBAND_MODE_RECT; + _touchpath_curve = new SPCurve(); +} + +void Inkscape::Rubberband::delete_canvas_items() +{ + if (_rect) { + SPCanvasItem *temp = _rect; + _rect = nullptr; + sp_canvas_item_destroy(temp); + } + if (_touchpath) { + SPCanvasItem *temp = _touchpath; + _touchpath = nullptr; + sp_canvas_item_destroy(temp); + } +} + + +void Inkscape::Rubberband::start(SPDesktop *d, Geom::Point const &p) +{ + _points.clear(); + _touchpath_curve->reset(); + delete_canvas_items(); + _desktop = d; + _start = p; + _started = true; + _points.push_back(_desktop->d2w(p)); + _touchpath_curve->moveto(p); + + _desktop->canvas->forceFullRedrawAfterInterruptions(5); +} + +void Inkscape::Rubberband::stop() +{ + _started = false; + _mode = RUBBERBAND_MODE_RECT; // restore the default + + _points.clear(); + _touchpath_curve->reset(); + + delete_canvas_items(); + + if (_desktop) { + _desktop->canvas->endForcedFullRedraws(); + } +} + +void Inkscape::Rubberband::move(Geom::Point const &p) +{ + if (!_started) + return; + + _end = p; + _desktop->scroll_to_point(p); + _touchpath_curve->lineto(p); + + Geom::Point next = _desktop->d2w(p); + // we want the points to be at most 0.5 screen pixels apart, + // so that we don't lose anything small; + // if they are farther apart, we interpolate more points + if (!_points.empty() && Geom::L2(next-_points.back()) > 0.5) { + Geom::Point prev = _points.back(); + int subdiv = 2 * (int) round(Geom::L2(next-prev) + 0.5); + for (int i = 1; i <= subdiv; i ++) { + _points.push_back(prev + ((double)i/subdiv) * (next - prev)); + } + } else { + _points.push_back(next); + } + + if (_mode == RUBBERBAND_MODE_RECT) { + if (_rect == nullptr) { + _rect = static_cast(sp_canvas_item_new(_desktop->getControls(), SP_TYPE_CTRLRECT, nullptr)); + _rect->setColor(0x808080ff, false, 0x0); + _rect->setInvert(true); + } + _rect->setRectangle(Geom::Rect(_start, _end)); + + sp_canvas_item_show(_rect); + if (_touchpath) + sp_canvas_item_hide(_touchpath); + + } else if (_mode == RUBBERBAND_MODE_TOUCHPATH) { + if (_touchpath == nullptr) { + _touchpath = sp_canvas_bpath_new(_desktop->getSketch(), nullptr); + sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(_touchpath), 0xff0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); + sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(_touchpath), 0, SP_WIND_RULE_NONZERO); + } + sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(_touchpath), _touchpath_curve); + + sp_canvas_item_show(_touchpath); + if (_rect) + sp_canvas_item_hide(_rect); + } +} + +void Inkscape::Rubberband::setMode(int mode) +{ + _mode = mode; +} + +/** + * @return Rectangle in desktop coordinates + */ +Geom::OptRect Inkscape::Rubberband::getRectangle() const +{ + if (!_started) { + return Geom::OptRect(); + } + + return Geom::Rect(_start, _end); +} + +Inkscape::Rubberband *Inkscape::Rubberband::get(SPDesktop *desktop) +{ + if (_instance == nullptr) { + _instance = new Inkscape::Rubberband(desktop); + } + + return _instance; +} + +bool Inkscape::Rubberband::is_started() +{ + return _started; +} + +/* + 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 : -- cgit v1.2.3