Skip to content

Commit

Permalink
Finish fixing qtwebkit#461 by attaching proper scale to images
Browse files Browse the repository at this point in the history
Also scale FloatRects correctly, as per the review.
  • Loading branch information
jkozera committed May 5, 2017
1 parent 4a7f18e commit 1ba9f7c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 21 deletions.
20 changes: 12 additions & 8 deletions Source/WebCore/platform/graphics/qt/ImageBufferDataQt.cpp
Expand Up @@ -351,7 +351,7 @@ GraphicsSurfaceToken ImageBufferDataPrivateAccelerated::graphicsSurfaceToken() c
// ---------------------- ImageBufferDataPrivateUnaccelerated

struct ImageBufferDataPrivateUnaccelerated final : public ImageBufferDataPrivate {
ImageBufferDataPrivateUnaccelerated(const IntSize&);
ImageBufferDataPrivateUnaccelerated(const IntSize&, float scale);
QPaintDevice* paintDevice() final { return m_pixmap.isNull() ? 0 : &m_pixmap; }
QImage toQImage() const final;
RefPtr<Image> image() const final;
Expand All @@ -371,11 +371,13 @@ struct ImageBufferDataPrivateUnaccelerated final : public ImageBufferDataPrivate
RefPtr<Image> m_image;
};

ImageBufferDataPrivateUnaccelerated::ImageBufferDataPrivateUnaccelerated(const IntSize& size)
ImageBufferDataPrivateUnaccelerated::ImageBufferDataPrivateUnaccelerated(const IntSize& size, float scale)
: m_pixmap(size)
, m_image(StillImage::createForRendering(&m_pixmap))
{
m_pixmap.fill(QColor(Qt::transparent));
// needs proper pixel ratio for drawing on HiDPI devices:
m_pixmap.setDevicePixelRatio(scale);
}

QImage ImageBufferDataPrivateUnaccelerated::toQImage() const
Expand Down Expand Up @@ -474,13 +476,14 @@ void ImageBufferDataPrivateUnaccelerated::platformTransformColorSpace(const Vect

// ---------------------- ImageBufferData

ImageBufferData::ImageBufferData(const IntSize& size, float resolutionScale)
ImageBufferData::ImageBufferData(const FloatSize& size, float resolutionScale)
{
m_painter = new QPainter;

IntSize scaledSize(size);
// we need to copy it, to scale without converting to int first, to retain precision:
FloatSize scaledSize(size);
scaledSize.scale(resolutionScale);
m_impl = new ImageBufferDataPrivateUnaccelerated(scaledSize);
m_impl = new ImageBufferDataPrivateUnaccelerated(IntSize(scaledSize), resolutionScale);

if (!m_impl->paintDevice())
return;
Expand All @@ -491,13 +494,14 @@ ImageBufferData::ImageBufferData(const IntSize& size, float resolutionScale)
}

#if ENABLE(ACCELERATED_2D_CANVAS)
ImageBufferData::ImageBufferData(const IntSize& size, float resolutionScale, QOpenGLContext* compatibleContext)
ImageBufferData::ImageBufferData(const FloatSize& size, float resolutionScale, QOpenGLContext* compatibleContext)
{
m_painter = new QPainter;

IntSize scaledSize(size);
// we need to copy it, to scale without converting to int first, to retain precision:
FloatSize scaledSize(size);
scaledSize.scale(resolutionScale);
m_impl = new ImageBufferDataPrivateAccelerated(scaledSize, compatibleContext);
m_impl = new ImageBufferDataPrivateAccelerated(IntSize(scaledSize), compatibleContext);

if (!m_impl->paintDevice())
return;
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h
Expand Up @@ -65,9 +65,9 @@ struct ImageBufferDataPrivate {

class ImageBufferData {
public:
ImageBufferData(const IntSize&, float resolutionScale);
ImageBufferData(const FloatSize&, float resolutionScale);
#if ENABLE(ACCELERATED_2D_CANVAS)
ImageBufferData(const IntSize&, float resolutionScale, QOpenGLContext*);
ImageBufferData(const FloatSize&, float resolutionScale, QOpenGLContext*);
#endif
~ImageBufferData();
QPainter* m_painter;
Expand Down
33 changes: 22 additions & 11 deletions Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
Expand Up @@ -68,16 +68,18 @@ ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace,
#endif

ImageBuffer::ImageBuffer(const FloatSize& size, float resolutionScale, ColorSpace, RenderingMode /*renderingMode*/, bool& success)
: m_data(IntSize(size), resolutionScale)
, m_size(size)
: m_data(size, resolutionScale)
, m_logicalSize(size)
, m_resolutionScale(resolutionScale)
{
success = m_data.m_painter && m_data.m_painter->isActive();
if (!success)
return;

m_size.scale(resolutionScale);
// we need to copy it, to scale without converting to int first, to retain precision:
FloatSize sizeScaled(size);
sizeScaled.scale(resolutionScale);
m_size = IntSize(sizeScaled);

m_data.m_context = std::make_unique<GraphicsContext>(m_data.m_painter);
}
Expand Down Expand Up @@ -145,8 +147,11 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}

template <Multiply multiplied>
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& unscaledRect, float scale, const ImageBufferData& imageData, const IntSize& size)
{
IntRect rect(unscaledRect);
rect.scale(scale);

float area = 4.0f * rect.width() * rect.height();
if (area > static_cast<float>(std::numeric_limits<int>::max()))
return 0;
Expand All @@ -161,6 +166,8 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe
// Let drawImage deal with the conversion.
// FIXME: This is inefficient for accelerated ImageBuffers when only part of the imageData is read.
QPainter painter(&image);
// this painter needs the same scaling as the whole buffer, to copy HiDPI images properly:
painter.setWorldTransform(QTransform::fromScale(scale, scale));
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.drawImage(QPoint(0, 0), imageData.m_impl->toQImage(), rect);
painter.end();
Expand All @@ -170,18 +177,18 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe

PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
IntRect scaledRect(rect);
float scale = 1.0;
if (coordinateSystem == LogicalCoordinateSystem)
scaledRect.scale(m_resolutionScale);
return getImageData<Unmultiplied>(scaledRect, m_data, m_size);
scale = m_resolutionScale;
return getImageData<Unmultiplied>(rect, scale, m_data, m_size);
}

PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
IntRect scaledRect(rect);
float scale = 1.0;
if (coordinateSystem == LogicalCoordinateSystem)
scaledRect.scale(m_resolutionScale);
return getImageData<Premultiplied>(scaledRect, m_data, m_size);
scale = m_resolutionScale;
return getImageData<Premultiplied>(rect, scale, m_data, m_size);
}

void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem)
Expand All @@ -201,17 +208,21 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
m_data.m_painter->setClipping(false);
}

// source rect & size need scaling from the device coords to image coords
IntSize scaledSourceSize(sourceSize);
IntRect scaledSourceRect(sourceRect);
if (coordinateSystem == LogicalCoordinateSystem) {
scaledSourceSize.scale(m_resolutionScale);
scaledSourceRect.scale(m_resolutionScale);
}

// Let drawImage deal with the conversion.
QImage::Format format = (multiplied == Unmultiplied) ? QImage::Format_RGBA8888 : QImage::Format_RGBA8888_Premultiplied;
QImage image(source->data(), scaledSourceSize.width(), scaledSourceSize.height(), format);
image.setDevicePixelRatio(m_resolutionScale);

m_data.m_painter->setCompositionMode(QPainter::CompositionMode_Source);
m_data.m_painter->drawImage(destPoint + sourceRect.location(), image, sourceRect);
m_data.m_painter->drawImage(destPoint + sourceRect.location(), image, scaledSourceRect);

if (!isPainting)
m_data.m_painter->end();
Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/platform/graphics/qt/StillImageQt.cpp
Expand Up @@ -83,6 +83,9 @@ void StillImage::draw(GraphicsContext& ctxt, const FloatRect& dst,
FloatRect normalizedSrc = src.normalized();
FloatRect normalizedDst = dst.normalized();

// source rect needs scaling from the device coords to image coords
normalizedSrc.scale(m_pixmap->devicePixelRatio());

CompositeOperator previousOperator = ctxt.compositeOperation();
BlendMode previousBlendMode = ctxt.blendModeOperation();
ctxt.setCompositeOperation(op, blendMode);
Expand Down

0 comments on commit 1ba9f7c

Please sign in to comment.