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 | |
23 | QPaintDeviceColorProxy::QPaintDeviceColorProxy(QPaintDevice* proxiedDevice, const QHash<QColor, QColor>& replacements) |
24 | : m_proxiedDevice(proxiedDevice) |
25 | , m_engine(new QPaintEngineColorProxy) |
26 | , m_replacements(replacements) |
27 | { |
28 | } |
29 | |
30 | QPaintDeviceColorProxy::~QPaintDeviceColorProxy() |
31 | { |
32 | delete m_engine; |
33 | } |
34 | |
35 | QPaintDevice* QPaintDeviceColorProxy::proxiedDevice() const |
36 | { |
37 | return m_proxiedDevice; |
38 | } |
39 | |
40 | QPaintEngine* QPaintDeviceColorProxy::paintEngine() const |
41 | { |
42 | return m_engine; |
43 | } |
44 | |
45 | int 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 | |
68 | QBrush 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 | |
93 | QColor QPaintDeviceColorProxy::map(const QColor& color) const |
94 | { |
95 | return m_replacements.value(color, color); |
96 | } |
97 | |
98 | QPen 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 | |
109 | QPaintEngineColorProxy::QPaintEngineColorProxy() |
110 | : m_proxy(0) |
111 | , m_painter(new QPainter) |
112 | { |
113 | } |
114 | |
115 | QPaintEngineColorProxy::~QPaintEngineColorProxy() |
116 | { |
117 | if (m_proxy) |
118 | { |
119 | end(); |
120 | } |
121 | delete m_painter; |
122 | } |
123 | |
124 | bool 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 | |
154 | bool QPaintEngineColorProxy::end() |
155 | { |
156 | if (!m_proxy) |
157 | { |
158 | return false; |
159 | } |
160 | m_proxy = 0; |
161 | return m_painter->end(); |
162 | } |
163 | |
164 | void QPaintEngineColorProxy::drawEllipse(const QRectF& rect) |
165 | { |
166 | if (m_proxy) |
167 | { |
168 | m_painter->drawEllipse(rect); |
169 | } |
170 | } |
171 | |
172 | void QPaintEngineColorProxy::drawEllipse(const QRect& rect) |
173 | { |
174 | if (m_proxy) |
175 | { |
176 | m_painter->drawEllipse(rect); |
177 | } |
178 | } |
179 | |
180 | void 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 | |
188 | void QPaintEngineColorProxy::drawLines(const QLineF* lines, int lineCount) |
189 | { |
190 | if (m_proxy) |
191 | { |
192 | m_painter->drawLines(lines, lineCount); |
193 | } |
194 | } |
195 | |
196 | void QPaintEngineColorProxy::drawLines(const QLine* lines, int lineCount) |
197 | { |
198 | if (m_proxy) |
199 | { |
200 | m_painter->drawLines(lines, lineCount); |
201 | } |
202 | } |
203 | |
204 | void QPaintEngineColorProxy::drawPath(const QPainterPath& path) |
205 | { |
206 | if (m_proxy) |
207 | { |
208 | m_painter->drawPath(path); |
209 | } |
210 | } |
211 | |
212 | void 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 | |
220 | void QPaintEngineColorProxy::drawPoints(const QPointF* points, int pointCount) |
221 | { |
222 | if (m_proxy) |
223 | { |
224 | m_painter->drawPoints(points, pointCount); |
225 | } |
226 | } |
227 | |
228 | void QPaintEngineColorProxy::drawPoints(const QPoint* points, int pointCount) |
229 | { |
230 | if (m_proxy) |
231 | { |
232 | m_painter->drawPoints(points, pointCount); |
233 | } |
234 | } |
235 | |
236 | void 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 | |
244 | void 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 | |
252 | void QPaintEngineColorProxy::drawRects(const QRectF* rects, int rectCount) |
253 | { |
254 | if (m_proxy) |
255 | { |
256 | m_painter->drawRects(rects, rectCount); |
257 | } |
258 | } |
259 | |
260 | void QPaintEngineColorProxy::drawRects(const QRect* rects, int rectCount) |
261 | { |
262 | if (m_proxy) |
263 | { |
264 | m_painter->drawRects(rects, rectCount); |
265 | } |
266 | } |
267 | |
268 | void QPaintEngineColorProxy::drawTextItem(const QPointF& p, const QTextItem& textItem) |
269 | { |
270 | if (m_proxy) |
271 | { |
272 | m_painter->drawTextItem(p, textItem); |
273 | } |
274 | } |
275 | |
276 | void 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 | |
284 | QPaintEngine::Type QPaintEngineColorProxy::type() const |
285 | { |
286 | return QPaintEngine::User; |
287 | } |
288 | |
289 | void 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 | |