summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/Library_vclplug_qt5.mk2
-rw-r--r--vcl/qt5/Qt5Frame.cxx76
-rw-r--r--vcl/qt5/Qt5Frame.hxx24
-rw-r--r--vcl/qt5/Qt5Graphics_GDI.cxx17
-rw-r--r--vcl/qt5/Qt5Instance.cxx35
-rw-r--r--vcl/qt5/Qt5Instance.hxx3
-rw-r--r--vcl/qt5/Qt5Tools.cxx28
-rw-r--r--vcl/qt5/Qt5Tools.hxx17
-rw-r--r--vcl/qt5/Qt5VirtualDevice.cxx5
-rw-r--r--vcl/qt5/Qt5Widget.cxx38
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 );
}