1/***************************************************************************
2 * Copyright 2010 Stefan Majewsky <majewsky@gmx.net> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU Library General Public License *
6 * version 2 as published by the Free Software Foundation *
7 * *
8 * This program is distributed in the hope that it will be useful, *
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 * GNU Library General Public License for more details. *
12 * *
13 * You should have received a copy of the GNU Library General Public *
14 * License along with this program; if not, write to the *
15 * Free Software Foundation, Inc., *
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
17 ***************************************************************************/
18
19#include "colorproxy_p.h"
20
21//BEGIN QPaintDeviceColorProxy
22
23QPaintDeviceColorProxy::QPaintDeviceColorProxy(QPaintDevice* proxiedDevice, const QHash<QColor, QColor>& replacements)
24 : m_proxiedDevice(proxiedDevice)
25 , m_engine(new QPaintEngineColorProxy)
26 , m_replacements(replacements)
27{
28}
29
30QPaintDeviceColorProxy::~QPaintDeviceColorProxy()
31{
32 delete m_engine;
33}
34
35QPaintDevice* QPaintDeviceColorProxy::proxiedDevice() const
36{
37 return m_proxiedDevice;
38}
39
40QPaintEngine* QPaintDeviceColorProxy::paintEngine() const
41{
42 return m_engine;
43}
44
45int QPaintDeviceColorProxy::metric(QPaintDevice::PaintDeviceMetric metric) const
46{
47 //return m_proxiedDevice->metric(metric);
48 //This does not work because m_proxiedDevice->QPaintDevice::metric() is
49 //protected, so we have to do the monkey dance instead.
50
51 typedef int (QPaintDevice::*MetricFunction)(void) const;
52 static const MetricFunction metricFunctions[] = {
53 0,
54 &QPaintDevice::width, // QPaintDevice::PdmWidth == 1
55 &QPaintDevice::height,
56 &QPaintDevice::widthMM,
57 &QPaintDevice::heightMM,
58 &QPaintDevice::colorCount,
59 &QPaintDevice::depth,
60 &QPaintDevice::logicalDpiX,
61 &QPaintDevice::logicalDpiY,
62 &QPaintDevice::physicalDpiX,
63 &QPaintDevice::physicalDpiY
64 };
65 return (m_proxiedDevice->*metricFunctions[metric])();
66}
67
68QBrush QPaintDeviceColorProxy::map(const QBrush& brush) const
69{
70 const Qt::BrushStyle style = brush.style();
71 const bool isGradient = style == Qt::LinearGradientPattern
72 || style == Qt::RadialGradientPattern
73 || style == Qt::ConicalGradientPattern;
74 //copy the given brush and map the contained color
75 if (!isGradient)
76 {
77 QBrush result(brush);
78 result.setColor(map(brush.color()));
79 return result;
80 }
81 //for gradients, map colors of gradient stops
82 QGradient newGradient(*brush.gradient());
83 QGradientStops stops = newGradient.stops();
84 for (int i = 0; i < stops.size(); ++i)
85 stops[i].second = map(stops[i].second);
86 newGradient.setStops(stops);
87 //there is no QBrush::setGradient(), so we have to clone the instance by hand
88 QBrush result(newGradient);
89 result.setTransform(brush.transform());
90 return result;
91}
92
93QColor QPaintDeviceColorProxy::map(const QColor& color) const
94{
95 return m_replacements.value(color, color);
96}
97
98QPen QPaintDeviceColorProxy::map(const QPen& pen) const
99{
100 QPen result(pen);
101 result.setBrush(map(pen.brush()));
102 return result;
103}
104
105//END QPaintDeviceColorProxy
106
107//BEGIN QPaintEngineColorProxy
108
109QPaintEngineColorProxy::QPaintEngineColorProxy()
110 : m_proxy(0)
111 , m_painter(new QPainter)
112{
113}
114
115QPaintEngineColorProxy::~QPaintEngineColorProxy()
116{
117 if (m_proxy)
118 {
119 end();
120 }
121 delete m_painter;
122}
123
124bool QPaintEngineColorProxy::begin(QPaintDevice* device)
125{
126 //previous operation not ended?
127 if (m_proxy)
128 {
129 return false;
130 }
131 //allow only proxy devices
132 QPaintDeviceColorProxy* proxyDevice = dynamic_cast<QPaintDeviceColorProxy*>(device);
133 if (!proxyDevice)
134 {
135 return false;
136 }
137 //check proxied device
138 QPaintDevice* proxiedDevice = proxyDevice->proxiedDevice();
139 if (!proxiedDevice)
140 {
141 return false;
142 }
143 //start to paint on proxied device
144 m_painter = new QPainter;
145 if (!m_painter->begin(proxiedDevice))
146 {
147 return false;
148 }
149 //success
150 m_proxy = proxyDevice;
151 return true;
152}
153
154bool QPaintEngineColorProxy::end()
155{
156 if (!m_proxy)
157 {
158 return false;
159 }
160 m_proxy = 0;
161 return m_painter->end();
162}
163
164void QPaintEngineColorProxy::drawEllipse(const QRectF& rect)
165{
166 if (m_proxy)
167 {
168 m_painter->drawEllipse(rect);
169 }
170}
171
172void QPaintEngineColorProxy::drawEllipse(const QRect& rect)
173{
174 if (m_proxy)
175 {
176 m_painter->drawEllipse(rect);
177 }
178}
179
180void QPaintEngineColorProxy::drawImage(const QRectF& rectangle, const QImage& image, const QRectF& sr, Qt::ImageConversionFlags flags)
181{
182 if (m_proxy)
183 {
184 m_painter->drawImage(rectangle, image, sr, flags);
185 }
186}
187
188void QPaintEngineColorProxy::drawLines(const QLineF* lines, int lineCount)
189{
190 if (m_proxy)
191 {
192 m_painter->drawLines(lines, lineCount);
193 }
194}
195
196void QPaintEngineColorProxy::drawLines(const QLine* lines, int lineCount)
197{
198 if (m_proxy)
199 {
200 m_painter->drawLines(lines, lineCount);
201 }
202}
203
204void QPaintEngineColorProxy::drawPath(const QPainterPath& path)
205{
206 if (m_proxy)
207 {
208 m_painter->drawPath(path);
209 }
210}
211
212void QPaintEngineColorProxy::drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr)
213{
214 if (m_proxy)
215 {
216 m_painter->drawPixmap(r, pm, sr);
217 }
218}
219
220void QPaintEngineColorProxy::drawPoints(const QPointF* points, int pointCount)
221{
222 if (m_proxy)
223 {
224 m_painter->drawPoints(points, pointCount);
225 }
226}
227
228void QPaintEngineColorProxy::drawPoints(const QPoint* points, int pointCount)
229{
230 if (m_proxy)
231 {
232 m_painter->drawPoints(points, pointCount);
233 }
234}
235
236void QPaintEngineColorProxy::drawPolygon(const QPointF* points, int pointCount, QPaintEngine::PolygonDrawMode mode)
237{
238 if (m_proxy)
239 {
240 m_painter->drawPolygon(points, pointCount, mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
241 }
242}
243
244void QPaintEngineColorProxy::drawPolygon(const QPoint* points, int pointCount, QPaintEngine::PolygonDrawMode mode)
245{
246 if (m_proxy)
247 {
248 m_painter->drawPolygon(points, pointCount, mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
249 }
250}
251
252void QPaintEngineColorProxy::drawRects(const QRectF* rects, int rectCount)
253{
254 if (m_proxy)
255 {
256 m_painter->drawRects(rects, rectCount);
257 }
258}
259
260void QPaintEngineColorProxy::drawRects(const QRect* rects, int rectCount)
261{
262 if (m_proxy)
263 {
264 m_painter->drawRects(rects, rectCount);
265 }
266}
267
268void QPaintEngineColorProxy::drawTextItem(const QPointF& p, const QTextItem& textItem)
269{
270 if (m_proxy)
271 {
272 m_painter->drawTextItem(p, textItem);
273 }
274}
275
276void QPaintEngineColorProxy::drawTiledPixmap(const QRectF& rect, const QPixmap& pixmap, const QPointF& p)
277{
278 if (m_proxy)
279 {
280 m_painter->drawTiledPixmap(rect, pixmap, p);
281 }
282}
283
284QPaintEngine::Type QPaintEngineColorProxy::type() const
285{
286 return QPaintEngine::User;
287}
288
289void QPaintEngineColorProxy::updateState(const QPaintEngineState& state)
290{
291 if (!m_proxy)
292 {
293 return;
294 }
295 const QPaintEngine::DirtyFlags flags = state.state();
296 if (flags & QPaintEngine::DirtyBackground)
297 {
298 const QBrush brush = state.backgroundBrush();
299 QBrush mappedBrush = m_proxy->map(brush);
300 if (mappedBrush != brush)
301 //pass changed brush back to own painter
302 painter()->setBackground(mappedBrush);
303 m_painter->setBackground(mappedBrush);
304 }
305 if (flags & QPaintEngine::DirtyBackgroundMode)
306 {
307 m_painter->setBackgroundMode(state.backgroundMode());
308 }
309 if (flags & QPaintEngine::DirtyBrush)
310 {
311 const QBrush brush = state.brush();
312 QBrush mappedBrush = m_proxy->map(brush);
313 if (mappedBrush != brush)
314 //pass changed brush back to own painter
315 painter()->setBrush(mappedBrush);
316 m_painter->setBrush(mappedBrush);
317 }
318 if (flags & QPaintEngine::DirtyBrushOrigin)
319 {
320 m_painter->setBrushOrigin(state.brushOrigin());
321 }
322 if (flags & QPaintEngine::DirtyClipEnabled)
323 {
324 m_painter->setClipping(state.isClipEnabled());
325 }
326 if (flags & QPaintEngine::DirtyClipPath)
327 {
328 m_painter->setClipPath(state.clipPath(), state.clipOperation());
329 }
330 if (flags & QPaintEngine::DirtyClipRegion)
331 {
332 m_painter->setClipRegion(state.clipRegion(), state.clipOperation());
333 }
334 if (flags & QPaintEngine::DirtyCompositionMode)
335 {
336 m_painter->setCompositionMode(state.compositionMode());
337 }
338 if (flags & QPaintEngine::DirtyFont)
339 {
340 m_painter->setFont(state.font());
341 }
342 if (flags & QPaintEngine::DirtyHints)
343 {
344 m_painter->setRenderHints(state.renderHints());
345 }
346 if (flags & QPaintEngine::DirtyPen)
347 {
348 const QPen pen = state.pen();
349 QPen mappedPen = m_proxy->map(pen);
350 if (mappedPen != pen)
351 //pass changed pen back to own painter
352 painter()->setPen(mappedPen);
353 m_painter->setPen(mappedPen);
354 }
355 if (flags & QPaintEngine::DirtyTransform)
356 {
357 m_painter->setTransform(state.transform());
358 }
359}
360
361//END QPaintEngineColorProxy
362