File indexing completed on 2024-04-28 04:05:02
0001 /* 0002 SPDX-FileCopyrightText: 2010 Stefan Majewsky <majewsky@gmx.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only 0005 */ 0006 0007 #include "colorproxy_p.h" 0008 0009 // Qt 0010 #include <QPainterPath> 0011 0012 // BEGIN QPaintDeviceColorProxy 0013 0014 QPaintDeviceColorProxy::QPaintDeviceColorProxy(QPaintDevice *proxiedDevice, const QHash<QColor, QColor> &replacements) 0015 : m_proxiedDevice(proxiedDevice) 0016 , m_engine(new QPaintEngineColorProxy) 0017 , m_replacements(replacements) 0018 { 0019 } 0020 0021 QPaintDeviceColorProxy::~QPaintDeviceColorProxy() 0022 { 0023 delete m_engine; 0024 } 0025 0026 QPaintDevice *QPaintDeviceColorProxy::proxiedDevice() const 0027 { 0028 return m_proxiedDevice; 0029 } 0030 0031 QPaintEngine *QPaintDeviceColorProxy::paintEngine() const 0032 { 0033 return m_engine; 0034 } 0035 0036 int QPaintDeviceColorProxy::metric(QPaintDevice::PaintDeviceMetric metric) const 0037 { 0038 // return m_proxiedDevice->metric(metric); 0039 // This does not work because m_proxiedDevice->QPaintDevice::metric() is 0040 // protected, so we have to do the monkey dance instead. 0041 0042 typedef int (QPaintDevice::*MetricFunction)(void) const; 0043 static const MetricFunction metricFunctions[] = {nullptr, 0044 &QPaintDevice::width, // QPaintDevice::PdmWidth == 1 0045 &QPaintDevice::height, 0046 &QPaintDevice::widthMM, 0047 &QPaintDevice::heightMM, 0048 &QPaintDevice::colorCount, 0049 &QPaintDevice::depth, 0050 &QPaintDevice::logicalDpiX, 0051 &QPaintDevice::logicalDpiY, 0052 &QPaintDevice::physicalDpiX, 0053 &QPaintDevice::physicalDpiY}; 0054 return (m_proxiedDevice->*metricFunctions[metric])(); 0055 } 0056 0057 QBrush QPaintDeviceColorProxy::map(const QBrush &brush) const 0058 { 0059 const Qt::BrushStyle style = brush.style(); 0060 const bool isGradient = style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern || style == Qt::ConicalGradientPattern; 0061 // copy the given brush and map the contained color 0062 if (!isGradient) { 0063 QBrush result(brush); 0064 result.setColor(map(brush.color())); 0065 return result; 0066 } 0067 // for gradients, map colors of gradient stops 0068 QGradient newGradient(*brush.gradient()); 0069 QGradientStops stops = newGradient.stops(); 0070 for (QGradientStop &stop : stops) { 0071 stop.second = map(stop.second); 0072 } 0073 newGradient.setStops(stops); 0074 // there is no QBrush::setGradient(), so we have to clone the instance by hand 0075 QBrush result(newGradient); 0076 result.setTransform(brush.transform()); 0077 return result; 0078 } 0079 0080 QColor QPaintDeviceColorProxy::map(const QColor &color) const 0081 { 0082 return m_replacements.value(color, color); 0083 } 0084 0085 QPen QPaintDeviceColorProxy::map(const QPen &pen) const 0086 { 0087 QPen result(pen); 0088 result.setBrush(map(pen.brush())); 0089 return result; 0090 } 0091 0092 // END QPaintDeviceColorProxy 0093 0094 // BEGIN QPaintEngineColorProxy 0095 0096 QPaintEngineColorProxy::QPaintEngineColorProxy() 0097 : m_proxy(nullptr) 0098 , m_painter(new QPainter) 0099 { 0100 } 0101 0102 QPaintEngineColorProxy::~QPaintEngineColorProxy() 0103 { 0104 if (m_proxy) { 0105 end(); 0106 } 0107 delete m_painter; 0108 } 0109 0110 bool QPaintEngineColorProxy::begin(QPaintDevice *device) 0111 { 0112 // previous operation not ended? 0113 if (m_proxy) { 0114 return false; 0115 } 0116 // allow only proxy devices 0117 QPaintDeviceColorProxy *proxyDevice = dynamic_cast<QPaintDeviceColorProxy *>(device); 0118 if (!proxyDevice) { 0119 return false; 0120 } 0121 // check proxied device 0122 QPaintDevice *proxiedDevice = proxyDevice->proxiedDevice(); 0123 if (!proxiedDevice) { 0124 return false; 0125 } 0126 // start to paint on proxied device 0127 m_painter = new QPainter; 0128 if (!m_painter->begin(proxiedDevice)) { 0129 return false; 0130 } 0131 // success 0132 m_proxy = proxyDevice; 0133 return true; 0134 } 0135 0136 bool QPaintEngineColorProxy::end() 0137 { 0138 if (!m_proxy) { 0139 return false; 0140 } 0141 m_proxy = nullptr; 0142 return m_painter->end(); 0143 } 0144 0145 void QPaintEngineColorProxy::drawEllipse(const QRectF &rect) 0146 { 0147 if (m_proxy) { 0148 m_painter->drawEllipse(rect); 0149 } 0150 } 0151 0152 void QPaintEngineColorProxy::drawEllipse(const QRect &rect) 0153 { 0154 if (m_proxy) { 0155 m_painter->drawEllipse(rect); 0156 } 0157 } 0158 0159 void QPaintEngineColorProxy::drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags) 0160 { 0161 if (m_proxy) { 0162 m_painter->drawImage(rectangle, image, sr, flags); 0163 } 0164 } 0165 0166 void QPaintEngineColorProxy::drawLines(const QLineF *lines, int lineCount) 0167 { 0168 if (m_proxy) { 0169 m_painter->drawLines(lines, lineCount); 0170 } 0171 } 0172 0173 void QPaintEngineColorProxy::drawLines(const QLine *lines, int lineCount) 0174 { 0175 if (m_proxy) { 0176 m_painter->drawLines(lines, lineCount); 0177 } 0178 } 0179 0180 void QPaintEngineColorProxy::drawPath(const QPainterPath &path) 0181 { 0182 if (m_proxy) { 0183 m_painter->drawPath(path); 0184 } 0185 } 0186 0187 void QPaintEngineColorProxy::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) 0188 { 0189 if (m_proxy) { 0190 m_painter->drawPixmap(r, pm, sr); 0191 } 0192 } 0193 0194 void QPaintEngineColorProxy::drawPoints(const QPointF *points, int pointCount) 0195 { 0196 if (m_proxy) { 0197 m_painter->drawPoints(points, pointCount); 0198 } 0199 } 0200 0201 void QPaintEngineColorProxy::drawPoints(const QPoint *points, int pointCount) 0202 { 0203 if (m_proxy) { 0204 m_painter->drawPoints(points, pointCount); 0205 } 0206 } 0207 0208 void QPaintEngineColorProxy::drawPolygon(const QPointF *points, int pointCount, QPaintEngine::PolygonDrawMode mode) 0209 { 0210 if (m_proxy) { 0211 m_painter->drawPolygon(points, pointCount, mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); 0212 } 0213 } 0214 0215 void QPaintEngineColorProxy::drawPolygon(const QPoint *points, int pointCount, QPaintEngine::PolygonDrawMode mode) 0216 { 0217 if (m_proxy) { 0218 m_painter->drawPolygon(points, pointCount, mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); 0219 } 0220 } 0221 0222 void QPaintEngineColorProxy::drawRects(const QRectF *rects, int rectCount) 0223 { 0224 if (m_proxy) { 0225 m_painter->drawRects(rects, rectCount); 0226 } 0227 } 0228 0229 void QPaintEngineColorProxy::drawRects(const QRect *rects, int rectCount) 0230 { 0231 if (m_proxy) { 0232 m_painter->drawRects(rects, rectCount); 0233 } 0234 } 0235 0236 void QPaintEngineColorProxy::drawTextItem(const QPointF &p, const QTextItem &textItem) 0237 { 0238 if (m_proxy) { 0239 m_painter->drawTextItem(p, textItem); 0240 } 0241 } 0242 0243 void QPaintEngineColorProxy::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) 0244 { 0245 if (m_proxy) { 0246 m_painter->drawTiledPixmap(rect, pixmap, p); 0247 } 0248 } 0249 0250 QPaintEngine::Type QPaintEngineColorProxy::type() const 0251 { 0252 return QPaintEngine::User; 0253 } 0254 0255 void QPaintEngineColorProxy::updateState(const QPaintEngineState &state) 0256 { 0257 if (!m_proxy) { 0258 return; 0259 } 0260 const QPaintEngine::DirtyFlags flags = state.state(); 0261 if (flags & QPaintEngine::DirtyBackground) { 0262 const QBrush brush = state.backgroundBrush(); 0263 QBrush mappedBrush = m_proxy->map(brush); 0264 if (mappedBrush != brush) 0265 // pass changed brush back to own painter 0266 painter()->setBackground(mappedBrush); 0267 m_painter->setBackground(mappedBrush); 0268 } 0269 if (flags & QPaintEngine::DirtyBackgroundMode) { 0270 m_painter->setBackgroundMode(state.backgroundMode()); 0271 } 0272 if (flags & QPaintEngine::DirtyBrush) { 0273 const QBrush brush = state.brush(); 0274 QBrush mappedBrush = m_proxy->map(brush); 0275 if (mappedBrush != brush) 0276 // pass changed brush back to own painter 0277 painter()->setBrush(mappedBrush); 0278 m_painter->setBrush(mappedBrush); 0279 } 0280 if (flags & QPaintEngine::DirtyBrushOrigin) { 0281 m_painter->setBrushOrigin(state.brushOrigin()); 0282 } 0283 if (flags & QPaintEngine::DirtyClipEnabled) { 0284 m_painter->setClipping(state.isClipEnabled()); 0285 } 0286 if (flags & QPaintEngine::DirtyClipPath) { 0287 m_painter->setClipPath(state.clipPath(), state.clipOperation()); 0288 } 0289 if (flags & QPaintEngine::DirtyClipRegion) { 0290 m_painter->setClipRegion(state.clipRegion(), state.clipOperation()); 0291 } 0292 if (flags & QPaintEngine::DirtyCompositionMode) { 0293 m_painter->setCompositionMode(state.compositionMode()); 0294 } 0295 if (flags & QPaintEngine::DirtyFont) { 0296 m_painter->setFont(state.font()); 0297 } 0298 if (flags & QPaintEngine::DirtyHints) { 0299 m_painter->setRenderHints(state.renderHints()); 0300 } 0301 if (flags & QPaintEngine::DirtyPen) { 0302 const QPen pen = state.pen(); 0303 QPen mappedPen = m_proxy->map(pen); 0304 if (mappedPen != pen) 0305 // pass changed pen back to own painter 0306 painter()->setPen(mappedPen); 0307 m_painter->setPen(mappedPen); 0308 } 0309 if (flags & QPaintEngine::DirtyTransform) { 0310 m_painter->setTransform(state.transform()); 0311 } 0312 } 0313 0314 // END QPaintEngineColorProxy