File indexing completed on 2024-05-12 15:56:41
0001 /* This file is part of the KDE project 0002 * 0003 * SPDX-FileCopyrightText: 2012 Thorsten Zachmann <zachmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "KoHatchBackground.h" 0009 0010 #include <KoShapeSavingContext.h> 0011 0012 #include <KoXmlNS.h> 0013 #include <KoUnit.h> 0014 0015 0016 #include <FlakeDebug.h> 0017 0018 #include <QColor> 0019 #include <QString> 0020 #include <QPainter> 0021 #include <QPainterPath> 0022 0023 class KoHatchBackground::Private : public QSharedData 0024 { 0025 public: 0026 Private() 0027 : QSharedData() 0028 , angle(0.0) 0029 , distance(1.0) 0030 , style(KoHatchBackground::Single) 0031 {} 0032 0033 QColor lineColor; 0034 int angle; 0035 qreal distance; 0036 KoHatchBackground::HatchStyle style; 0037 QString name; 0038 }; 0039 0040 KoHatchBackground::KoHatchBackground() 0041 : KoColorBackground() 0042 , d(new Private) 0043 { 0044 } 0045 0046 KoHatchBackground::~KoHatchBackground() 0047 { 0048 } 0049 0050 void KoHatchBackground::paint(QPainter &painter, const QPainterPath &fillPath) const 0051 { 0052 if (color().isValid()) { 0053 // paint background color if set by using the color background 0054 KoColorBackground::paint(painter, fillPath); 0055 } 0056 0057 const QRectF targetRect = fillPath.boundingRect(); 0058 painter.save(); 0059 painter.setClipPath(fillPath); 0060 QPen pen(d->lineColor); 0061 // we set the pen width to 0.5 pt for the hatch. This is not defined in the spec. 0062 pen.setWidthF(0.5); 0063 painter.setPen(pen); 0064 QVector<QLineF> lines; 0065 0066 // The different styles are handled by painting the lines multiple times with a different 0067 // angel offset as basically it just means we paint the lines also at a different angle. 0068 // This are the angle offsets we need to apply to the different lines of a style. 0069 // -90 is for single, 0 for the 2nd line in double and -45 for the 3th line in triple. 0070 const int angleOffset[] = {-90, 0, -45 }; 0071 // The number of loops is defined by the style. 0072 int loops = (d->style == Single) ? 1 : (d->style == Double) ? 2 : 3; 0073 0074 for (int i = 0; i < loops; ++i) { 0075 int angle = d->angle - angleOffset[i]; 0076 qreal cosAngle = ::cos(angle/180.0*M_PI); 0077 // if cos is nearly 0 the lines are horizontal. Use a special case for that 0078 if (qAbs(cosAngle) > 0.00001) { 0079 qreal xDiff = tan(angle/180.0*M_PI) * targetRect.height(); 0080 // calculate the distance we need to increase x when creating the lines so that the 0081 // distance between the lines is also correct for rotated lines. 0082 qreal xOffset = qAbs(d->distance / cosAngle); 0083 0084 // if the lines go to the right we need to start more to the left. Get the correct start. 0085 qreal xStart = 0; 0086 while (-xDiff < xStart) { 0087 xStart -= xOffset; 0088 } 0089 0090 // if the lines go to the left we need to stop more at the right. Get the correct end offset 0091 qreal xEndOffset = 0; 0092 if (xDiff < 0) { 0093 while (xDiff < -xEndOffset) { 0094 xEndOffset += xOffset; 0095 } 0096 } 0097 // create line objects. 0098 lines.reserve(lines.size() + int((targetRect.width() + xEndOffset - xStart) / xOffset) + 1); 0099 for (qreal x = xStart; x < targetRect.width() + xEndOffset; x += xOffset) { 0100 lines.append(QLineF(x, 0, x + xDiff, targetRect.height())); 0101 } 0102 } 0103 else { 0104 // horizontal lines 0105 lines.reserve(lines.size() + int(targetRect.height()/d->distance) + 1); 0106 for (qreal y = 0; y < targetRect.height(); y += d->distance) { 0107 lines.append(QLineF(0, y, targetRect.width(), y)); 0108 } 0109 } 0110 } 0111 0112 painter.drawLines(lines); 0113 painter.restore(); 0114 }