diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-24 19:49:45 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2017-11-06 12:05:32 +0100 |
commit | 185c9724fd8445695f9233f8120c71e80392767d (patch) | |
tree | 83763dd484ce6c4a236cee00df4cdfdeeafcbbc3 | |
parent | 2ffb83daa4358aaad0cba7ddb67847282ac6fcce (diff) |
QT5 implement cairo rendering path
Instead of QImage, this uses cairo_surface_t internally and just
blits the composed image in the Qt5Widgets paint function.
To enable this rendering path set SAL_VCL_QT5_USE_CAIRO.
Change-Id: Ieddda9bad2596ce46d7d07d4d7060e40d44997db
-rw-r--r-- | vcl/Library_vclplug_qt5.mk | 2 | ||||
-rw-r--r-- | vcl/qt5/Qt5Frame.cxx | 76 | ||||
-rw-r--r-- | vcl/qt5/Qt5Frame.hxx | 24 | ||||
-rw-r--r-- | vcl/qt5/Qt5Graphics_GDI.cxx | 17 | ||||
-rw-r--r-- | vcl/qt5/Qt5Instance.cxx | 35 | ||||
-rw-r--r-- | vcl/qt5/Qt5Instance.hxx | 3 | ||||
-rw-r--r-- | vcl/qt5/Qt5Tools.cxx | 28 | ||||
-rw-r--r-- | vcl/qt5/Qt5Tools.hxx | 17 | ||||
-rw-r--r-- | vcl/qt5/Qt5VirtualDevice.cxx | 5 | ||||
-rw-r--r-- | vcl/qt5/Qt5Widget.cxx | 38 |
10 files changed, 206 insertions, 39 deletions
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk index 8274d90e8820..333812f939bb 100644 --- a/vcl/Library_vclplug_qt5.mk +++ b/vcl/Library_vclplug_qt5.mk @@ -54,6 +54,7 @@ $(eval $(call gb_Library_use_libraries,vclplug_qt5,\ $(eval $(call gb_Library_use_externals,vclplug_qt5,\ boost_headers \ + cairo \ icuuc \ qt5 \ epoxy \ @@ -89,6 +90,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\ vcl/qt5/Qt5Object \ vcl/qt5/Qt5Printer \ vcl/qt5/Qt5Timer \ + vcl/qt5/Qt5Tools \ vcl/qt5/Qt5VirtualDevice \ vcl/qt5/Qt5Widget \ )) diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx index ff9dc769f00b..b6939863a125 100644 --- a/vcl/qt5/Qt5Frame.cxx +++ b/vcl/qt5/Qt5Frame.cxx @@ -32,12 +32,27 @@ #include <saldatabasic.hxx> #include <vcl/syswin.hxx> -Qt5Frame::Qt5Frame( Qt5Frame* pParent, SalFrameStyleFlags nStyle ) - : m_bGraphicsInUse( false ) +#include <cairo.h> +#include <headless/svpgdi.hxx> + +static void SvpDamageHandler( void *handle, + sal_Int32 nExtentsX, sal_Int32 nExtentsY, + sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight ) +{ + Qt5Frame* pThis = static_cast< Qt5Frame* >( handle ); + pThis->Damage( nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight ); +} + +Qt5Frame::Qt5Frame( Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo ) + : m_bUseCairo( bUseCairo ) + , m_bGraphicsInUse( false ) { Qt5Instance *pInst = static_cast<Qt5Instance*>( GetSalData()->m_pInstance ); pInst->insertFrame( this ); + m_aDamageHandler.handle = this; + m_aDamageHandler.damaged = ::SvpDamageHandler; + if( nStyle & SalFrameStyleFlags::DEFAULT ) // ensure default style { nStyle |= SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::CLOSEABLE; @@ -85,11 +100,24 @@ Qt5Frame::~Qt5Frame() pInst->eraseFrame( this ); } +void Qt5Frame::Damage( sal_Int32 nExtentsX, sal_Int32 nExtentsY, + sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight) const +{ + m_pQWidget->update( nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight ); +} + void Qt5Frame::TriggerPaintEvent() { QSize aSize( m_pQWidget->size() ); - SalPaintEvent aPaintEvt(0, 0, aSize.width(), aSize.height(), true); - CallCallback(SalEvent::Paint, &aPaintEvt); + SalPaintEvent aPaintEvt( 0, 0, aSize.width(), aSize.height(), true ); + CallCallback( SalEvent::Paint, &aPaintEvt ); +} + +void Qt5Frame::TriggerPaintEvent( QRect aRect ) +{ + SalPaintEvent aPaintEvt( aRect.x(), aRect.y(), + aRect.width(), aRect.height(), true ); + CallCallback( SalEvent::Paint, &aPaintEvt ); } SalGraphics* Qt5Frame::AcquireGraphics() @@ -97,22 +125,43 @@ SalGraphics* Qt5Frame::AcquireGraphics() if( m_bGraphicsInUse ) return nullptr; - if( !m_pGraphics.get() ) - { - m_pGraphics.reset( new Qt5Graphics( this ) ); - m_pQImage.reset( new QImage( m_pQWidget->size(), QImage::Format_ARGB32 ) ); - m_pGraphics->ChangeQImage( m_pQImage.get() ); - TriggerPaintEvent(); - } m_bGraphicsInUse = true; - return m_pGraphics.get(); + if( m_bUseCairo ) + { + if( !m_pSvpGraphics.get() ) + { + int width = m_pQWidget->size().width(); + int height = m_pQWidget->size().height(); + m_pSvpGraphics.reset( new SvpSalGraphics() ); + m_pSurface.reset( cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height )); + m_pSvpGraphics->setSurface( m_pSurface.get(), basegfx::B2IVector(width, height) ); + cairo_surface_set_user_data( m_pSurface.get(), SvpSalGraphics::getDamageKey(), + &m_aDamageHandler, nullptr ); + TriggerPaintEvent(); + } + return m_pSvpGraphics.get(); + } + else + { + if( !m_pQt5Graphics.get() ) + { + m_pQt5Graphics.reset( new Qt5Graphics( this ) ); + m_pQImage.reset( new QImage( m_pQWidget->size(), Qt5_DefaultFormat32 ) ); + m_pQt5Graphics->ChangeQImage( m_pQImage.get() ); + TriggerPaintEvent(); + } + return m_pQt5Graphics.get(); + } } void Qt5Frame::ReleaseGraphics( SalGraphics* pSalGraph ) { (void) pSalGraph; - assert( pSalGraph == m_pGraphics.get() ); + if( m_bUseCairo ) + assert( pSalGraph == m_pSvpGraphics.get() ); + else + assert( pSalGraph == m_pQt5Graphics.get() ); m_bGraphicsInUse = false; } @@ -269,7 +318,6 @@ bool Qt5Frame::GetWindowState( SalFrameState* pState ) WindowStateMask::Height; } - TriggerPaintEvent(); return true; } diff --git a/vcl/qt5/Qt5Frame.hxx b/vcl/qt5/Qt5Frame.hxx index 209561780414..538b5eabed9c 100644 --- a/vcl/qt5/Qt5Frame.hxx +++ b/vcl/qt5/Qt5Frame.hxx @@ -21,7 +21,9 @@ #include <salframe.hxx> -#include <memory> +#include "Qt5Tools.hxx" + +#include <headless/svpgdi.hxx> class Qt5Graphics; class Qt5Instance; @@ -29,15 +31,22 @@ class Qt5Widget; class QWidget; class QPaintDevice; class QImage; +class SvpSalGraphics; class Qt5Frame : public SalFrame { friend class Qt5Widget; - std::unique_ptr< QWidget > m_pQWidget; - std::unique_ptr< QImage > m_pQImage; - std::unique_ptr< Qt5Graphics > m_pGraphics; + std::unique_ptr< QWidget > m_pQWidget; + + const bool m_bUseCairo; + std::unique_ptr< QImage > m_pQImage; + std::unique_ptr< Qt5Graphics > m_pQt5Graphics; + UniqueCairoSurface m_pSurface; + std::unique_ptr< SvpSalGraphics> m_pSvpGraphics; + DamageHandler m_aDamageHandler; + bool m_bGraphicsInUse; SalFrameStyleFlags m_nStyle; Qt5Frame *m_pParent; @@ -53,14 +62,19 @@ class Qt5Frame } void TriggerPaintEvent(); + void TriggerPaintEvent( QRect aRect ); public: Qt5Frame( Qt5Frame* pParent, - SalFrameStyleFlags nSalFrameStyle ); + SalFrameStyleFlags nSalFrameStyle, + bool bUseCairo ); virtual ~Qt5Frame() override; QWidget* GetQWidget() const { return m_pQWidget.get(); } + void Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, + sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight) const; + virtual SalGraphics* AcquireGraphics() override; virtual void ReleaseGraphics( SalGraphics* pGraphics ) override; diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index b790278cdce0..d44055b8e841 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -194,6 +194,7 @@ void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBi PreparePainter(); const QImage *pImage = static_cast< const Qt5Bitmap* >( &rSalBitmap )->GetQImage(); + assert( pImage ); m_pPainter->drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ), *pImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY, @@ -208,12 +209,24 @@ void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, const SalBitmap& rTransparentBitmap ) { + if( rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 + || rPosAry.mnDestWidth <= 0 || rPosAry.mnDestHeight <= 0 ) + return; + + assert( rPosAry.mnSrcWidth == rPosAry.mnDestWidth ); + assert( rPosAry.mnSrcHeight == rPosAry.mnDestHeight ); } void Qt5Graphics::drawMask( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - SalColor nMaskColor ) + const SalBitmap& rSalBitmap, + SalColor nMaskColor ) { + if( rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 + || rPosAry.mnDestWidth <= 0 || rPosAry.mnDestHeight <= 0 ) + return; + + assert( rPosAry.mnSrcWidth == rPosAry.mnDestWidth ); + assert( rPosAry.mnSrcHeight == rPosAry.mnDestHeight ); } SalBitmap* Qt5Graphics::getBitmap( long nX, long nY, long nWidth, long nHeight ) diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx index dd2daf7e8b8b..4e36c6684936 100644 --- a/vcl/qt5/Qt5Instance.cxx +++ b/vcl/qt5/Qt5Instance.cxx @@ -27,8 +27,11 @@ #include "Qt5Object.hxx" #include "Qt5Bitmap.hxx" +#include <headless/svpvd.hxx> + #include <QtCore/QThread> #include <QtWidgets/QApplication> +#include <QtWidgets/QWidget> #include <QtCore/QAbstractEventDispatcher> #include <vclpluginapi.h> @@ -38,9 +41,10 @@ #include <headless/svpdummies.hxx> #include <headless/svpbmp.hxx> -Qt5Instance::Qt5Instance( SalYieldMutex* pMutex ) +Qt5Instance::Qt5Instance( SalYieldMutex* pMutex, bool bUseCairo ) : SalGenericInstance( pMutex ) , m_postUserEventId( -1 ) + , m_bUseCairo( bUseCairo ) { m_postUserEventId = QEvent::registerEventType(); @@ -61,13 +65,13 @@ Qt5Instance::~Qt5Instance() SalFrame* Qt5Instance::CreateChildFrame( SystemParentData* /*pParent*/, SalFrameStyleFlags nStyle ) { - return new Qt5Frame( nullptr, nStyle ); + return new Qt5Frame( nullptr, nStyle, m_bUseCairo ); } SalFrame* Qt5Instance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) { assert( !pParent || dynamic_cast<Qt5Frame*>( pParent ) ); - return new Qt5Frame( static_cast<Qt5Frame*>( pParent ), nStyle ); + return new Qt5Frame( static_cast<Qt5Frame*>( pParent ), nStyle, m_bUseCairo ); } void Qt5Instance::DestroyFrame( SalFrame* pFrame ) @@ -91,9 +95,18 @@ SalVirtualDevice* Qt5Instance::CreateVirtualDevice( SalGraphics* /* pGraphics */ DeviceFormat eFormat, const SystemGraphicsData* /* pData */ ) { - Qt5VirtualDevice* pVD = new Qt5VirtualDevice( eFormat, 1 ); - pVD->SetSize( nDX, nDY ); - return pVD; + if ( m_bUseCairo ) + { + SvpSalVirtualDevice *pVD = new SvpSalVirtualDevice( eFormat, 1 ); + pVD->SetSize( nDX, nDY ); + return pVD; + } + else + { + Qt5VirtualDevice* pVD = new Qt5VirtualDevice( eFormat, 1 ); + pVD->SetSize( nDX, nDY ); + return pVD; + } } SalTimer* Qt5Instance::CreateSalTimer() @@ -108,7 +121,10 @@ SalSystem* Qt5Instance::CreateSalSystem() SalBitmap* Qt5Instance::CreateSalBitmap() { - return new Qt5Bitmap(); + if ( m_bUseCairo ) + return new SvpSalBitmap(); + else + return new Qt5Bitmap(); } bool Qt5Instance::ImplYield( bool bWait, bool bHandleAllCurrentEvents ) @@ -198,7 +214,7 @@ extern "C" { VCLPLUG_QT5_PUBLIC SalInstance* create_SalInstance() { OString aVersion( qVersion() ); - SAL_INFO( "vcl.kf5", "qt version string is " << aVersion ); + SAL_INFO( "vcl.qt5", "qt version string is " << aVersion ); QApplication *pQApplication; char **pFakeArgvFreeable = nullptr; @@ -261,7 +277,8 @@ extern "C" { QApplication::setQuitOnLastWindowClosed(false); - Qt5Instance* pInstance = new Qt5Instance( new SalYieldMutex() ); + const bool bUseCairo = (nullptr != getenv( "SAL_VCL_QT5_USE_CAIRO" )); + Qt5Instance* pInstance = new Qt5Instance( new SalYieldMutex(), bUseCairo ); // initialize SalData new Qt5Data( pInstance ); diff --git a/vcl/qt5/Qt5Instance.hxx b/vcl/qt5/Qt5Instance.hxx index ff0cacc7be97..0fea7673b59c 100644 --- a/vcl/qt5/Qt5Instance.hxx +++ b/vcl/qt5/Qt5Instance.hxx @@ -39,6 +39,7 @@ class Qt5Instance osl::Condition m_aWaitingYieldCond; int m_postUserEventId; + const bool m_bUseCairo; public: std::unique_ptr< QApplication > m_pQApplication; @@ -53,7 +54,7 @@ Q_SIGNALS: bool ImplYieldSignal( bool bWait, bool bHandleAllCurrentEvents ); public: - explicit Qt5Instance( SalYieldMutex* pMutex ); + explicit Qt5Instance( SalYieldMutex* pMutex, bool bUseCairo = false ); virtual ~Qt5Instance() override; virtual SalFrame* CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) override; diff --git a/vcl/qt5/Qt5Tools.cxx b/vcl/qt5/Qt5Tools.cxx new file mode 100644 index 000000000000..5ce038b2b054 --- /dev/null +++ b/vcl/qt5/Qt5Tools.cxx @@ -0,0 +1,28 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "Qt5Tools.hxx" + +#include <cairo.h> + +void CairoDeleter::operator()(cairo_surface_t *pSurface) const +{ + cairo_surface_destroy( pSurface ); +} + diff --git a/vcl/qt5/Qt5Tools.hxx b/vcl/qt5/Qt5Tools.hxx index 40c34d9d4303..e429f4d9c56c 100644 --- a/vcl/qt5/Qt5Tools.hxx +++ b/vcl/qt5/Qt5Tools.hxx @@ -25,8 +25,11 @@ #include <QtGui/QImage> #include <rtl/string.hxx> +#include <rtl/ustring.hxx> #include <tools/gen.hxx> +#include <memory> + inline OUString toOUString(const QString& s) { // QString stores UTF16, just like OUString @@ -55,6 +58,8 @@ inline Size toSize( const QSize& rSize ) return Size( rSize.width(), rSize.height() ); } +static constexpr QImage::Format Qt5_DefaultFormat32 = QImage::Format_ARGB32; + inline QImage::Format getBitFormat( sal_uInt16 nBitCount ) { switch ( nBitCount ) @@ -63,7 +68,7 @@ inline QImage::Format getBitFormat( sal_uInt16 nBitCount ) case 8 : return QImage::Format_Indexed8; case 16 : return QImage::Format_RGB16; case 24 : return QImage::Format_RGB888; - case 32 : return QImage::Format_ARGB32; + case 32 : return Qt5_DefaultFormat32; default : std::abort(); break; @@ -79,11 +84,19 @@ inline sal_uInt16 getFormatBits( QImage::Format eFormat ) case QImage::Format_Indexed8 : return 8; case QImage::Format_RGB16 : return 16; case QImage::Format_RGB888 : return 24; - case QImage::Format_ARGB32 : return 32; + case Qt5_DefaultFormat32 : return 32; default : std::abort(); return 0; } } +typedef struct _cairo_surface cairo_surface_t; +struct CairoDeleter +{ + void operator()(cairo_surface_t *pSurface) const; +}; + +typedef std::unique_ptr<cairo_surface_t, CairoDeleter> UniqueCairoSurface; + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qt5/Qt5VirtualDevice.cxx b/vcl/qt5/Qt5VirtualDevice.cxx index 10f286049456..51ba1782c331 100644 --- a/vcl/qt5/Qt5VirtualDevice.cxx +++ b/vcl/qt5/Qt5VirtualDevice.cxx @@ -20,6 +20,7 @@ #include "Qt5VirtualDevice.hxx" #include "Qt5Graphics.hxx" +#include "Qt5Tools.hxx" #include <QtGui/QImage> @@ -76,9 +77,9 @@ bool Qt5VirtualDevice::SetSizeUsingBuffer( long nNewDX, long nNewDY, else { if ( pBuffer ) - m_pImage.reset( new QImage( pBuffer, nNewDX, nNewDY, QImage::Format_ARGB32 ) ); + m_pImage.reset( new QImage( pBuffer, nNewDX, nNewDY, Qt5_DefaultFormat32 ) ); else - m_pImage.reset( new QImage( nNewDX, nNewDY, QImage::Format_ARGB32 ) ); + m_pImage.reset( new QImage( nNewDX, nNewDY, Qt5_DefaultFormat32 ) ); } m_pImage->setDevicePixelRatio( m_fScale ); diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx index 739708148876..7682a4717ae0 100644 --- a/vcl/qt5/Qt5Widget.cxx +++ b/vcl/qt5/Qt5Widget.cxx @@ -22,11 +22,15 @@ #include "Qt5Frame.hxx" #include "Qt5Graphics.hxx" +#include "Qt5Tools.hxx" #include <QtGui/QImage> #include <QtGui/QPainter> #include <QtGui/QPaintEvent> +#include <cairo.h> +#include <headless/svpgdi.hxx> + Qt5Widget::Qt5Widget( Qt5Frame &rFrame, QWidget *parent, Qt::WindowFlags f ) : QWidget( parent, f ) , m_pFrame( &rFrame ) @@ -41,14 +45,40 @@ Qt5Widget::~Qt5Widget() void Qt5Widget::paintEvent( QPaintEvent *pEvent ) { QPainter p( this ); - p.drawImage( pEvent->rect().topLeft(), *m_pFrame->m_pQImage, pEvent->rect() ); + if( m_pFrame->m_bUseCairo ) + { + cairo_surface_t *pSurface = m_pFrame->m_pSurface.get(); + cairo_surface_flush( pSurface ); + + QImage aImage( cairo_image_surface_get_data( pSurface ), + size().width(), size().height(), Qt5_DefaultFormat32 ); + p.drawImage( QPoint( 0, 0 ), aImage ); + p.drawImage( pEvent->rect().topLeft(), aImage, pEvent->rect() ); + } + else + p.drawImage( pEvent->rect().topLeft(), + *m_pFrame->m_pQImage, pEvent->rect() ); } void Qt5Widget::resizeEvent( QResizeEvent* ) { - QImage *pImage = new QImage( m_pFrame->m_pQWidget->size(), QImage::Format_ARGB32 ); - m_pFrame->m_pGraphics->ChangeQImage( pImage ); - m_pFrame->m_pQImage.reset( pImage ); + if( m_pFrame->m_bUseCairo ) + { + int width = size().width(); + int height = size().height(); + cairo_surface_t *pSurface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height ); + cairo_surface_set_user_data( pSurface, SvpSalGraphics::getDamageKey(), + &m_pFrame->m_aDamageHandler, nullptr ); + m_pFrame->m_pSvpGraphics->setSurface( pSurface, basegfx::B2IVector(width, height) ); + m_pFrame->m_pSurface.reset( pSurface ); + } + else + { + QImage *pImage = new QImage( size(), Qt5_DefaultFormat32 ); + m_pFrame->m_pQt5Graphics->ChangeQImage( pImage ); + m_pFrame->m_pQImage.reset( pImage ); + } + m_pFrame->CallCallback( SalEvent::Resize, nullptr ); } |