1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "basictoolsplugin.h" |
52 | |
53 | #include <QInputDialog> |
54 | #include <QPainter> |
55 | #include <QRandomGenerator> |
56 | #include <QtMath> |
57 | |
58 | //! [0] |
59 | QStringList BasicToolsPlugin::brushes() const |
60 | { |
61 | return {tr(s: "Pencil" ), tr(s: "Air Brush" ), tr(s: "Random Letters" )}; |
62 | } |
63 | //! [0] |
64 | |
65 | //! [1] |
66 | QRect BasicToolsPlugin::mousePress(const QString &brush, QPainter &painter, |
67 | const QPoint &pos) |
68 | { |
69 | return mouseMove(brush, painter, oldPos: pos, newPos: pos); |
70 | } |
71 | //! [1] |
72 | |
73 | //! [2] |
74 | QRect BasicToolsPlugin::mouseMove(const QString &brush, QPainter &painter, |
75 | const QPoint &oldPos, const QPoint &newPos) |
76 | { |
77 | painter.save(); |
78 | |
79 | int rad = painter.pen().width() / 2; |
80 | QRect boundingRect = QRect(oldPos, newPos).normalized() |
81 | .adjusted(xp1: -rad, yp1: -rad, xp2: +rad, yp2: +rad); |
82 | QColor color = painter.pen().color(); |
83 | int thickness = painter.pen().width(); |
84 | QColor transparentColor(color.red(), color.green(), color.blue(), 0); |
85 | //! [2] //! [3] |
86 | |
87 | if (brush == tr(s: "Pencil" )) { |
88 | painter.drawLine(p1: oldPos, p2: newPos); |
89 | } else if (brush == tr(s: "Air Brush" )) { |
90 | int numSteps = 2 + (newPos - oldPos).manhattanLength() / 2; |
91 | |
92 | painter.setBrush(QBrush(color, Qt::Dense6Pattern)); |
93 | painter.setPen(Qt::NoPen); |
94 | |
95 | for (int i = 0; i < numSteps; ++i) { |
96 | int x = oldPos.x() + i * (newPos.x() - oldPos.x()) / (numSteps - 1); |
97 | int y = oldPos.y() + i * (newPos.y() - oldPos.y()) / (numSteps - 1); |
98 | |
99 | painter.drawEllipse(x: x - (thickness / 2), y: y - (thickness / 2), |
100 | w: thickness, h: thickness); |
101 | } |
102 | } else if (brush == tr(s: "Random Letters" )) { |
103 | QChar ch(QRandomGenerator::global()->bounded(lowest: 'A', highest: 'Z' + 1)); |
104 | |
105 | QFont biggerFont = painter.font(); |
106 | biggerFont.setBold(true); |
107 | biggerFont.setPointSize(biggerFont.pointSize() + thickness); |
108 | painter.setFont(biggerFont); |
109 | |
110 | painter.drawText(p: newPos, s: QString(ch)); |
111 | |
112 | QFontMetrics metrics(painter.font()); |
113 | boundingRect = metrics.boundingRect(ch); |
114 | boundingRect.translate(p: newPos); |
115 | boundingRect.adjust(dx1: -10, dy1: -10, dx2: +10, dy2: +10); |
116 | } |
117 | painter.restore(); |
118 | return boundingRect; |
119 | } |
120 | //! [3] |
121 | |
122 | //! [4] |
123 | QRect BasicToolsPlugin::mouseRelease(const QString & /* brush */, |
124 | QPainter & /* painter */, |
125 | const QPoint & /* pos */) |
126 | { |
127 | return QRect(0, 0, 0, 0); |
128 | } |
129 | //! [4] |
130 | |
131 | //! [5] |
132 | QStringList BasicToolsPlugin::shapes() const |
133 | { |
134 | return {tr(s: "Circle" ), tr(s: "Star" ), tr(s: "Text..." )}; |
135 | } |
136 | //! [5] |
137 | |
138 | //! [6] |
139 | QPainterPath BasicToolsPlugin::generateShape(const QString &shape, |
140 | QWidget *parent) |
141 | { |
142 | QPainterPath path; |
143 | |
144 | if (shape == tr(s: "Circle" )) { |
145 | path.addEllipse(x: 0, y: 0, w: 50, h: 50); |
146 | } else if (shape == tr(s: "Star" )) { |
147 | path.moveTo(x: 90, y: 50); |
148 | for (int i = 1; i < 5; ++i) { |
149 | path.lineTo(x: 50 + 40 * std::cos(x: 0.8 * i * M_PI), |
150 | y: 50 + 40 * std::sin(x: 0.8 * i * M_PI)); |
151 | } |
152 | path.closeSubpath(); |
153 | } else if (shape == tr(s: "Text..." )) { |
154 | QString text = QInputDialog::getText(parent, title: tr(s: "Text Shape" ), |
155 | label: tr(s: "Enter text:" ), |
156 | echo: QLineEdit::Normal, text: tr(s: "Qt" )); |
157 | if (!text.isEmpty()) { |
158 | QFont timesFont("Times" , 50); |
159 | timesFont.setStyleStrategy(QFont::ForceOutline); |
160 | path.addText(x: 0, y: 0, f: timesFont, text); |
161 | } |
162 | } |
163 | |
164 | return path; |
165 | } |
166 | //! [6] |
167 | |
168 | //! [7] |
169 | QStringList BasicToolsPlugin::filters() const |
170 | { |
171 | return {tr(s: "Invert Pixels" ), tr(s: "Swap RGB" ), tr(s: "Grayscale" )}; |
172 | } |
173 | //! [7] |
174 | |
175 | //! [8] |
176 | QImage BasicToolsPlugin::filterImage(const QString &filter, const QImage &image, |
177 | QWidget * /* parent */) |
178 | { |
179 | QImage result = image.convertToFormat(f: QImage::Format_RGB32); |
180 | |
181 | if (filter == tr(s: "Invert Pixels" )) { |
182 | result.invertPixels(); |
183 | } else if (filter == tr(s: "Swap RGB" )) { |
184 | result = result.rgbSwapped(); |
185 | } else if (filter == tr(s: "Grayscale" )) { |
186 | for (int y = 0; y < result.height(); ++y) { |
187 | for (int x = 0; x < result.width(); ++x) { |
188 | QRgb pixel = result.pixel(x, y); |
189 | int gray = qGray(rgb: pixel); |
190 | int alpha = qAlpha(rgb: pixel); |
191 | result.setPixel(x, y, index_or_rgb: qRgba(r: gray, g: gray, b: gray, a: alpha)); |
192 | } |
193 | } |
194 | } |
195 | return result; |
196 | } |
197 | //! [8] |
198 | |