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