Warning, file /graphics/washipad/src/stroke.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // This file is part of Washi Pad 0002 // SPDX-FileCopyrightText: 2018 Kevin Ottens <ervin@kde.org> 0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include "stroke.h" 0006 0007 #include <QVector2D> 0008 0009 bool StrokeSample::operator==(const StrokeSample &other) const 0010 { 0011 return position == other.position 0012 && qFuzzyCompare(width, other.width); 0013 } 0014 0015 Stroke::Type Stroke::type() const 0016 { 0017 return m_type; 0018 } 0019 0020 void Stroke::setType(Stroke::Type type) 0021 { 0022 m_type = type; 0023 } 0024 0025 QColor Stroke::color() const 0026 { 0027 return m_color; 0028 } 0029 0030 void Stroke::setColor(const QColor &color) 0031 { 0032 m_color = color; 0033 } 0034 0035 QVector<StrokeSample> Stroke::samples() const 0036 { 0037 return m_samples; 0038 } 0039 0040 void Stroke::addSample(const StrokeSample &sample) 0041 { 0042 m_samples << sample; 0043 m_boundingRectCache = QRectF{}; 0044 } 0045 0046 void Stroke::addSamples(const QVector<StrokeSample> &samples) 0047 { 0048 m_samples += samples; 0049 m_boundingRectCache = QRectF{}; 0050 } 0051 0052 QVector<Stroke> Stroke::eraseArea(const QVector2D ¢er, float radius) 0053 { 0054 const auto areaBoundingRect = QRectF{(center - QVector2D{radius, radius}).toPointF(), 0055 (center + QVector2D{radius, radius}).toPointF()}; 0056 auto result = QVector<Stroke>{}; 0057 0058 // For sure won't get any hits 0059 if (!boundingRect().intersects(areaBoundingRect)) { 0060 result.append(*this); 0061 return result; 0062 } 0063 0064 const auto isHit = [=](const StrokeSample &sample) { 0065 return QVector2D{sample.position - center}.length() <= radius; 0066 }; 0067 0068 auto it = std::cbegin(m_samples); 0069 const auto end = std::cend(m_samples); 0070 0071 while (it != end) { 0072 auto previous = it; 0073 // Find first hit 0074 it = std::find_if(it, end, isHit); 0075 0076 // Copy [previous, it) in a new stroke if there's more than one sample 0077 const auto distance = static_cast<int>(std::distance(previous, it)); 0078 if (distance >= 2) { 0079 auto stroke = *this; 0080 stroke.m_samples.clear(); 0081 stroke.m_samples.reserve(distance); 0082 std::copy(previous, it, std::back_inserter(stroke.m_samples)); 0083 0084 result.append(stroke); 0085 } 0086 0087 // Jump to next non-hit 0088 it = std::find_if_not(it, end, isHit); 0089 } 0090 0091 return result; 0092 } 0093 0094 QRectF Stroke::boundingRect() const 0095 { 0096 if (!m_boundingRectCache.isValid()) { 0097 auto minX = 0.0f; 0098 auto minY = 0.0f; 0099 auto maxX = 0.0f; 0100 auto maxY = 0.0f; 0101 0102 for (const auto &sample : qAsConst(m_samples)) { 0103 const auto position = sample.position; 0104 if (position.x() < minX) 0105 minX = position.x(); 0106 else if (position.x() > maxX) 0107 maxX = position.x(); 0108 0109 if (position.y() < minY) 0110 minY = position.y(); 0111 else if (position.y() > maxY) 0112 maxY = position.y(); 0113 } 0114 0115 m_boundingRectCache = {QPointF{static_cast<qreal>(minX), static_cast<qreal>(minY)}, 0116 QPointF{static_cast<qreal>(maxX), static_cast<qreal>(maxY)}}; 0117 } 0118 0119 return m_boundingRectCache; 0120 }