class GraphicsContextPlatformPrivate : public Noncopyable {
public:
- GraphicsContextPlatformPrivate(QPainter* painter);
+ GraphicsContextPlatformPrivate(QPainter*, const QColor& initialSolidColor);
~GraphicsContextPlatformPrivate();
inline QPainter* p() const
return shadow.m_type != ContextShadow::NoShadow;
}
+ inline void clearCurrentPath()
+ {
+ if (!currentPath.elementCount())
+ return;
+ currentPath = QPainterPath();
+ }
+
QRectF clipBoundingRect() const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
};
-GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p)
+GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, const QColor& initialSolidColor)
+ : antiAliasingForRectsAndLines(false)
+ , layerCount(0)
+ , solidColor(initialSolidColor)
+ , imageInterpolationQuality(InterpolationDefault)
+ , painter(p)
{
- painter = p;
- layerCount = 0;
-
- solidColor = QBrush(Qt::black);
+ if (!painter)
+ return;
- imageInterpolationQuality = InterpolationDefault;
+ // Use the default the QPainter was constructed with.
+ antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
- if (painter) {
- // use the default the QPainter was constructed with
- antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
- // FIXME: Maybe only enable in SVG mode?
- painter->setRenderHint(QPainter::Antialiasing, true);
- painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
- } else
- antiAliasingForRectsAndLines = false;
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
}
GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
{
}
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* painter)
: m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(context))
+ , m_data(new GraphicsContextPlatformPrivate(painter, fillColor()))
{
- setPaintingDisabled(!context);
- if (context) {
- // Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor(), DeviceColorSpace);
- setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
+ setPaintingDisabled(!painter);
- // Make sure we start with the correct join mode.
- setLineJoin(MiterJoin);
- }
+ if (!painter)
+ return;
+
+ // solidColor is initialized with the fillColor().
+ painter->setBrush(m_data->solidColor);
+
+ QPen pen(painter->pen());
+ pen.setColor(strokeColor());
+ pen.setJoinStyle(toQtLineJoin(MiterJoin));
+ painter->setPen(pen);
}
GraphicsContext::~GraphicsContext()
for (size_t i = 1; i < numPoints; ++i)
path.lineTo(points[i]);
path.setFillRule(Qt::WindingFill);
- m_data->p()->setClipPath(path, Qt::IntersectClip);
-}
-
-QPen GraphicsContext::pen()
-{
- if (paintingDisabled())
- return QPen();
QPainter* p = m_data->p();
- return p->pen();
+
+ bool painterWasAntialiased = p->testRenderHint(QPainter::Antialiasing);
+
+ if (painterWasAntialiased != antialiased)
+ p->setRenderHint(QPainter::Antialiasing, antialiased);
+
+ p->setClipPath(path, Qt::IntersectClip);
+
+ if (painterWasAntialiased != antialiased)
+ p->setRenderHint(QPainter::Antialiasing, painterWasAntialiased);
}
void GraphicsContext::fillPath()
} else
p->fillPath(path, p->brush());
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
void GraphicsContext::strokePath()
p->strokePath(path, pen);
} else
p->strokePath(path, pen);
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY)
if (paintingDisabled() || !color.isValid())
return;
- Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
+ Path path;
+ path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
QPainter* p = m_data->p();
if (m_data->hasShadow()) {
- p->translate(m_data->shadow.offset());
- p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
- p->translate(-m_data->shadow.offset());
+ ContextShadow* shadow = contextShadow();
+
+ if (shadow->m_type != ContextShadow::BlurShadow) {
+ // We do not need any layer for simple shadow.
+ p->translate(m_data->shadow.offset());
+ p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
+ p->translate(-m_data->shadow.offset());
+ } else {
+ QPainter* shadowPainter = shadow->beginShadowLayer(p, rect);
+ if (shadowPainter) {
+ shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
+ shadowPainter->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
+ shadow->endShadowLayer(p);
+ }
+ }
}
p->fillPath(path.platformPath(), QColor(color));
}
void GraphicsContext::beginPath()
{
- m_data->currentPath = QPainterPath();
+ m_data->clearCurrentPath();
}
void GraphicsContext::addPath(const Path& path)
QPainter* p = m_data->p();
QPainterPath newPath = m_data->currentPath;
newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
- p->setClipPath(newPath);
+ p->setClipPath(newPath, Qt::IntersectClip);
}
void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color)
if (paintingDisabled())
return;
+ IntPoint startPoint = origin;
IntPoint endPoint = origin + IntSize(width, 0);
- drawLine(origin, endPoint);
+
+ // If paintengine type is X11 to avoid artifacts
+ // like bug https://bugs.webkit.org/show_bug.cgi?id=42248
+#if defined(Q_WS_X11)
+ QPainter* p = m_data->p();
+ if (p->paintEngine()->type() == QPaintEngine::X11) {
+ // If stroke thickness is odd we need decrease Y coordinate by 1 pixel,
+ // because inside method adjustLineToPixelBoundaries(...), which
+ // called from drawLine(...), Y coordinate will be increased by 0.5f
+ // and then inside Qt painting engine will be rounded to next greater
+ // integer value.
+ float strokeWidth = strokeThickness();
+ if (static_cast<int>(strokeWidth) % 2) {
+ startPoint.setY(startPoint.y() - 1);
+ endPoint.setY(endPoint.y() - 1);
+ }
+ }
+#endif // defined(Q_WS_X11)
+
+ drawLine(startPoint, endPoint);
}
void GraphicsContext::drawLineForTextChecking(const IntPoint&, int, TextCheckingLineStyle)
}
}
-IntPoint GraphicsContext::origin()
-{
- if (paintingDisabled())
- return IntPoint();
- const QTransform &transform = m_data->p()->transform();
- return IntPoint(qRound(transform.dx()), qRound(transform.dy()));
-}
-
void GraphicsContext::rotate(float radians)
{
if (paintingDisabled())
}
}
-void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
-{
- if (paintingDisabled())
- return;
-
- QPainter* p = m_data->p();
- QPainterPath newClip;
- newClip.setFillRule(Qt::OddEvenFill);
- if (p->hasClipping()) {
- newClip.addRect(m_data->clipBoundingRect());
- newClip.addEllipse(QRect(rect));
- p->setClipPath(newClip, Qt::IntersectClip);
- } else {
- QRect clipOutRect(rect);
- QRect window(p->window());
- clipOutRect &= window;
- newClip.addRect(window);
- newClip.addEllipse(clipOutRect);
- p->setClipPath(newClip);
- }
-}
-
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
int thickness)
{