File indexing completed on 2024-04-21 15:24:03

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 "strokepainter.h"
0006 
0007 #include <QPainter>
0008 #include <QPainterPath>
0009 #include <QVector2D>
0010 
0011 #include "stroke.h"
0012 
0013 void StrokePainter::render(const Stroke &stroke, QPainter *painter)
0014 {
0015     const auto samples = stroke.samples();
0016     if (samples.size() < 2)
0017         return;
0018 
0019     auto it = std::cbegin(samples);
0020     auto lastSample = *it;
0021     ++it;
0022 
0023     auto forwardPoints = QVector<QVector2D>{};
0024     auto backwardPoints = QVector<QVector2D>{};
0025 
0026     while (it != std::cend(samples)) {
0027         const auto currentSample = *it;
0028 
0029         const auto penWidth = currentSample.width;
0030 
0031         const auto currentPos = currentSample.position;
0032         const auto lastPos = lastSample.position;
0033 
0034         const auto direction = currentPos - lastPos;
0035         const auto ortho = QVector2D(direction.y(), -direction.x()).normalized();
0036 
0037         const auto p1 = (lastPos - penWidth * ortho / 2.0f);
0038         const auto p2 = (lastPos + penWidth * ortho / 2.0f);
0039         const auto p3 = (currentPos - penWidth * ortho / 2.0f);
0040         const auto p4 = (currentPos + penWidth * ortho / 2.0f);
0041 
0042         forwardPoints << p1 << p3;
0043         backwardPoints << p2 << p4;
0044 
0045         lastSample = currentSample;
0046         ++it;
0047     }
0048 
0049     auto path = QPainterPath();
0050     path.moveTo(static_cast<qreal>(forwardPoints[0].x()),
0051                 static_cast<qreal>(forwardPoints[0].y()));
0052     for (auto it = forwardPoints.cbegin() + 1; it != forwardPoints.cend(); ++it) {
0053         path.lineTo(static_cast<qreal>(it->x()),
0054                     static_cast<qreal>(it->y()));
0055     }
0056     for (auto it = backwardPoints.crbegin(); it != backwardPoints.crend(); ++it) {
0057         path.lineTo(static_cast<qreal>(it->x()),
0058                     static_cast<qreal>(it->y()));
0059     }
0060     path.closeSubpath();
0061     path.setFillRule(Qt::WindingFill);
0062 
0063     painter->setPen(Qt::NoPen);
0064     painter->setBrush(stroke.color());
0065     painter->drawPath(path);
0066 }