office-gobmx/vcl/qt5/Qt5SvpGraphics.cxx
Luca Carlon 358991e3b0 tdf#127687 Qt5 introduce basic HiDPI scaling
For tdf#124292, Qt's own HiDPI scaling was explicitly disabled,
but it turns out, you can't really scale QStyle painting then.

This patch series had a 2nd approach also used by Gtk+ currently,
which relied on the scaling of ths Cairo surface, which works
surprisingly good, but has to lie about the real DPI value, so
nothing is scaled twice. Also all icons are then scaled instead
of rendered with the proper resolution.

When HiDPI support in Qt is enabled, and the application is
started using QT_SCALE_FACTOR=1.25, Qt simply lowers the reported
resolution, keeps the logical DPI value of 96 and changes the
devicePixelRatio to the specified value. But LO still expects
the real DPI values and sizes, so we have to multiply a lot of
rectangles, sizes and positions.

The current result is far from perfect, which you can see with
the various graphics glitches, but it at least doesn't crash
anymore in the ControlType::Editbox sizing code.

The main problem is all the up and downscaling in the
getNativeControlRegion code, so LO knows the size of the widgets
for the correct layouting, since there seem to be no API to
get the scaled values from Qt / QStyle.

Change-Id: I687b1df6ef27724ce68326d256e9addccd72e759
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86239
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2020-03-09 14:19:49 +01:00

114 lines
3.3 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <salbmp.hxx>
#include <config_cairo_canvas.h>
#include <Qt5Data.hxx>
#include <Qt5Frame.hxx>
#include <Qt5Graphics_Controls.hxx>
#include <Qt5SvpGraphics.hxx>
#include <Qt5SvpSurface.hxx>
#include <Qt5Tools.hxx>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtWidgets/QWidget>
Qt5SvpGraphics::Qt5SvpGraphics(Qt5Frame* pFrame)
: SvpSalGraphics()
, m_pFrame(pFrame)
{
if (!Qt5Data::noNativeControls())
m_pWidgetDraw.reset(new Qt5Graphics_Controls(*this));
if (m_pFrame)
setDevicePixelRatioF(m_pFrame->devicePixelRatioF());
}
Qt5SvpGraphics::~Qt5SvpGraphics() {}
void Qt5SvpGraphics::updateQWidget() const
{
if (!m_pFrame)
return;
QWidget* pQWidget = m_pFrame->GetQWidget();
if (pQWidget)
pQWidget->update(pQWidget->rect());
}
#if ENABLE_CAIRO_CANVAS
bool Qt5SvpGraphics::SupportsCairo() const { return true; }
cairo::SurfaceSharedPtr
Qt5SvpGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const
{
return std::make_shared<cairo::Qt5SvpSurface>(rSurface);
}
cairo::SurfaceSharedPtr Qt5SvpGraphics::CreateSurface(const OutputDevice& /*rRefDevice*/, int x,
int y, int width, int height) const
{
return std::make_shared<cairo::Qt5SvpSurface>(this, x, y, width, height);
}
#endif
static void QImage2BitmapBuffer(QImage& rImg, BitmapBuffer& rBuf)
{
assert(rImg.width());
assert(rImg.height());
rBuf.mnWidth = rImg.width();
rBuf.mnHeight = rImg.height();
rBuf.mnBitCount = getFormatBits(rImg.format());
rBuf.mpBits = rImg.bits();
rBuf.mnScanlineSize = rImg.bytesPerLine();
}
void Qt5SvpGraphics::handleDamage(const tools::Rectangle& rDamagedRegion)
{
assert(m_pWidgetDraw);
assert(dynamic_cast<Qt5Graphics_Controls*>(m_pWidgetDraw.get()));
assert(!rDamagedRegion.IsEmpty());
QImage* pImage = static_cast<Qt5Graphics_Controls*>(m_pWidgetDraw.get())->getImage();
assert(pImage);
if (pImage->width() == 0 || pImage->height() == 0)
return;
BitmapBuffer aBuffer;
QImage2BitmapBuffer(*pImage, aBuffer);
SalTwoRect aTR(0, 0, pImage->width(), pImage->height(), rDamagedRegion.getX(),
rDamagedRegion.getY(), rDamagedRegion.GetWidth(), rDamagedRegion.GetHeight());
drawBitmap(aTR, &aBuffer, CAIRO_OPERATOR_OVER);
}
void Qt5SvpGraphics::GetResolution(sal_Int32& rDPIX, sal_Int32& rDPIY)
{
char* pForceDpi;
if ((pForceDpi = getenv("SAL_FORCEDPI")))
{
OString sForceDPI(pForceDpi);
rDPIX = rDPIY = sForceDPI.toInt32();
return;
}
if (!m_pFrame || !m_pFrame->GetQWidget()->window()->windowHandle())
return;
QScreen* pScreen = m_pFrame->GetQWidget()->window()->windowHandle()->screen();
rDPIX = pScreen->logicalDotsPerInchX() * pScreen->devicePixelRatio() + 0.5;
rDPIY = pScreen->logicalDotsPerInchY() * pScreen->devicePixelRatio() + 0.5;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */