[Libreoffice-commits] core.git: Branch 'private/jmux/qt5' - 10 commits - config_host/config_qt5.h.in vcl/inc vcl/Library_vcl.mk vcl/Library_vclplug_qt5.mk vcl/qt5 vcl/source vcl/unx

Jan-Marek Glogowski glogow at fbihome.de
Fri Nov 3 17:25:46 UTC 2017


Rebased ref, commits from common ancestor:
commit 390090dc2ac20827f3f0ba8e39fd447dfcb2331e
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 16:11:09 2017 +0100

    QT5 implement Graphics damage tracking
    
    Since we implement SalGraphics handling like the gtk3 backend, we
    need damage tracking to queue updates.
    
    Since there is no native damage tracking in Qt5, we have to log
    the damage in our subclassed QPainter, which will queue an update
    on destruction.
    
    Change-Id: Ife17770750a5be9959c2fc2633b422908d196869

diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index d82b7d2fcd31..fba78d738883 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -91,6 +91,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_qt5,\
     vcl/qt5/Qt5Instance \
     vcl/qt5/Qt5Instance_Print \
     vcl/qt5/Qt5Object \
+    vcl/qt5/Qt5Painter \
     vcl/qt5/Qt5Printer \
     vcl/qt5/Qt5Timer \
     vcl/qt5/Qt5Tools \
diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index 676e9e54664e..eae47c5f21e9 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -18,7 +18,11 @@
  */
 
 #include "Qt5Graphics.hxx"
+
 #include "Qt5Frame.hxx"
+#include "Qt5Painter.hxx"
+
+#include <qt5/Qt5Font.hxx>
 
 #include <QtWidgets/QWidget>
 
@@ -46,30 +50,6 @@ Qt5Graphics::~Qt5Graphics()
         delete m_pTextStyle[ i ];
 }
 
-void Qt5Graphics::PreparePainter( QPainter& rPainter, sal_uInt8 nTransparency )
-{
-    if ( m_pQImage )
-        rPainter.begin( m_pQImage );
-    else
-    {
-        assert( dynamic_cast< QPaintDevice* >( m_pFrame->GetQWidget() ) );
-        rPainter.begin( m_pFrame->GetQWidget() );
-    }
-    if ( !m_aClipPath.isEmpty() )
-        rPainter.setClipPath( m_aClipPath );
-    else
-        rPainter.setClipRegion( m_aClipRegion );
-    if ( SALCOLOR_NONE != m_aLineColor )
-    {
-        QColor aColor = QColor::fromRgb( QRgb( m_aLineColor ) );
-        aColor.setAlpha( nTransparency );
-        rPainter.setPen( aColor );
-    }
-    else
-        rPainter.setPen( Qt::NoPen );
-    rPainter.setCompositionMode( m_eCompositionMode );
-}
-
 void Qt5Graphics::ChangeQImage( QImage *pQImage )
 {
     m_pQImage = pQImage;
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index 52c1c90ec5df..9ffe2c47e461 100644
--- a/vcl/qt5/Qt5Graphics.hxx
+++ b/vcl/qt5/Qt5Graphics.hxx
@@ -30,16 +30,14 @@
 class Qt5Font;
 class Qt5FontFace;
 class Qt5Frame;
+class Qt5Painter;
 class PhysicalFontCollection;
 class QImage;
 
-#define PREPARE_PAINTER \
-    QPainter aPainter; \
-    PreparePainter( aPainter );
-
 class Qt5Graphics : public SalGraphics
 {
     friend class Qt5Bitmap;
+    friend class Qt5Painter;
 
     Qt5Frame                     *m_pFrame;
     QImage                       *m_pQImage;
@@ -55,7 +53,6 @@ class Qt5Graphics : public SalGraphics
     SalColor                      m_aTextColor;
 
     Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage );
-    void PreparePainter( QPainter &rPainter, sal_uInt8 nTransparency = 0xff );
 
 public:
     Qt5Graphics( Qt5Frame *pFrame )
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index f8434bb3bc32..a1e407e088e1 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -20,8 +20,7 @@
 #include "Qt5Graphics.hxx"
 
 #include "Qt5Bitmap.hxx"
-#include "Qt5Frame.hxx"
-#include "Qt5Tools.hxx"
+#include "Qt5Painter.hxx"
 
 #include <QtGui/QPainter>
 #include <QtGui/QScreen>
@@ -164,48 +163,88 @@ void Qt5Graphics::ResetClipRegion()
 
 void Qt5Graphics::drawPixel( long nX, long nY )
 {
-    PREPARE_PAINTER;
+    Qt5Painter aPainter( *this );
     aPainter.drawPoint( nX, nY );
+    aPainter.update( nX, nY, 1, 1 );
 }
 
 void Qt5Graphics::drawPixel( long nX, long nY, SalColor nSalColor )
 {
-    PREPARE_PAINTER;
+    Qt5Painter aPainter( *this );
     aPainter.setPen( QColor( QRgb( nSalColor )  ) );
     aPainter.setPen( Qt::SolidLine );
     aPainter.drawPoint( nX, nY );
+    aPainter.update( nX, nY, 1, 1 );
 }
 
 void Qt5Graphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
 {
-    PREPARE_PAINTER;
+    Qt5Painter aPainter( *this );
     aPainter.drawLine( nX1, nY1, nX2, nY2 );
+
+    long tmp;
+    if ( nX1 > nX2 )
+    {
+        tmp = nX1;
+        nX1 = nX2;
+        nX2 = tmp;
+    }
+    if ( nY1 > nY2 )
+    {
+        tmp = nY1;
+        nY1 = nY2;
+        nY2 = tmp;
+    }
+    aPainter.update( nX1, nY1, nX2 - nX1, nY2 - nY1 );
 }
 
 void Qt5Graphics::drawRect( long nX, long nY, long nWidth, long nHeight )
 {
-    PREPARE_PAINTER;
-    aPainter.drawRect( nX, nY, nWidth, nHeight );
+    if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor )
+        return;
+
+    Qt5Painter aPainter( *this, true );
+    if ( SALCOLOR_NONE != m_aFillColor )
+        aPainter.fillRect( nX, nY, nWidth, nHeight, aPainter.brush() );
+    else
+        aPainter.drawRect( nX, nY, nWidth, nHeight );
+    aPainter.update( nX, nY, nWidth, nHeight );
 }
 
 void Qt5Graphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    PREPARE_PAINTER;
+    if ( 0 == nPoints )
+        return;
+
+    Qt5Painter aPainter( *this );
     QPoint *pPoints = new QPoint[ nPoints ];
+    QPoint aTopLeft( pPtAry->mnX, pPtAry->mnY );
+    QPoint aBottomRight = aTopLeft;
     for ( sal_uInt32 i = 0; i < nPoints; ++i, ++pPtAry )
+    {
         pPoints[ i ] = QPoint( pPtAry->mnX, pPtAry->mnY );
+        if ( pPtAry->mnX < aTopLeft.x() )
+            aTopLeft.setX( pPtAry->mnX );
+        if ( pPtAry->mnY < aTopLeft.y() )
+            aTopLeft.setY( pPtAry->mnY );
+        if ( pPtAry->mnX > aBottomRight.x() )
+            aBottomRight.setX( pPtAry->mnX );
+        if ( pPtAry->mnY > aBottomRight.y())
+            aBottomRight.setY( pPtAry->mnY );
+    }
     aPainter.drawPolyline( pPoints, nPoints );
     delete [] pPoints;
+    aPainter.update( QRect( aTopLeft, aBottomRight ) );
 }
 
 void Qt5Graphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    PREPARE_PAINTER;
-    QPoint *pPoints = new QPoint[ nPoints ];
+    Qt5Painter aPainter( *this, true );
+    QPolygon aPolygon( nPoints );
     for ( sal_uInt32 i = 0; i < nPoints; ++i, ++pPtAry )
-        pPoints[ i ] = QPoint( pPtAry->mnX, pPtAry->mnY );
-    aPainter.drawPolygon( pPoints, nPoints );
-    delete [] pPoints;
+        aPolygon.setPoint( i, pPtAry->mnX, pPtAry->mnY );
+    aPainter.drawPolygon( aPolygon );
+    aPainter.update( aPolygon.boundingRect() );
 }
 
 void Qt5Graphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
@@ -227,14 +266,9 @@ bool Qt5Graphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly,
                                m_aLineColor != SALCOLOR_NONE ) )
         return true;
 
-    PREPARE_PAINTER;
-
-    QBrush aBrush = aPainter.brush();
-    aBrush.setStyle( SALCOLOR_NONE == m_aFillColor ? Qt::NoBrush : Qt::SolidPattern );
-    aPainter.setBrush( aBrush );
-
+    Qt5Painter aPainter( *this, true, 255 * (1.0 - fTransparency) );
     aPainter.drawPath( aPath );
-
+    aPainter.update( aPath.boundingRect() );
     return true;
 }
 
@@ -277,8 +311,7 @@ bool Qt5Graphics::drawPolyLine( const basegfx::B2DPolygon& rPolyLine,
     AddPolygonToPath( aPath, rPolyLine, rPolyLine.isClosed(),
                       !getAntiAliasB2DDraw(), true );
 
-    QPainter aPainter;
-    PreparePainter( aPainter, 255 * fTransparency );
+    Qt5Painter aPainter( *this, false, 255 * (1.0 - fTransparency) );
 
     // setup line attributes
     QPen aPen = aPainter.pen();
@@ -305,6 +338,7 @@ bool Qt5Graphics::drawPolyLine( const basegfx::B2DPolygon& rPolyLine,
 
     aPainter.setPen( aPen );
     aPainter.drawPath( aPath );
+    aPainter.update( aPath.boundingRect() );
     return true;
 }
 
@@ -345,11 +379,12 @@ void Qt5Graphics::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics
     else
         pImage = static_cast< Qt5Graphics* >( pSrcGraphics )->m_pQImage;
 
-    PREPARE_PAINTER;
-
+    Qt5Painter aPainter( *this );
     aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
         *pImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
                         rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
+    aPainter.update( rPosAry.mnDestX, rPosAry.mnDestY,
+                     rPosAry.mnDestWidth, rPosAry.mnDestHeight );
 }
 
 void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
@@ -361,7 +396,7 @@ void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBi
     assert( rPosAry.mnSrcWidth == rPosAry.mnDestWidth );
     assert( rPosAry.mnSrcHeight == rPosAry.mnDestHeight );
 
-    PREPARE_PAINTER;
+    Qt5Painter aPainter( *this );
 
     const QImage *pImage = static_cast< const Qt5Bitmap* >( &rSalBitmap )->GetQImage();
     assert( pImage );
@@ -369,10 +404,8 @@ void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBi
     aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
         *pImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
                         rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
-
-    // Workaround to get updates
-    if ( m_pFrame )
-        m_pFrame->GetQWidget()->update();
+    aPainter.update( rPosAry.mnDestX, rPosAry.mnDestY,
+                     rPosAry.mnDestWidth, rPosAry.mnDestHeight );
 }
 
 void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry,
@@ -487,8 +520,8 @@ bool Qt5Graphics::drawAlphaBitmap( const SalTwoRect& rPosAry,
     QImage aImage;
     if ( !getAlphaImage( rSourceBitmap, rAlphaBitmap, aImage ) )
         return false;
-    PREPARE_PAINTER;
 
+    Qt5Painter aPainter( *this );
     aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
         aImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
                        rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
@@ -510,8 +543,7 @@ bool Qt5Graphics::drawTransformedBitmap( const basegfx::B2DPoint& rNull,
         aImage = pBitmap->convertToFormat( Qt5_DefaultFormat32 );
     }
 
-    PREPARE_PAINTER;
-
+    Qt5Painter aPainter( *this );
     const basegfx::B2DVector aXRel = rX - rNull;
     const basegfx::B2DVector aYRel = rY - rNull;
     aPainter.setTransform( QTransform(
@@ -519,6 +551,7 @@ bool Qt5Graphics::drawTransformedBitmap( const basegfx::B2DPoint& rNull,
         aYRel.getX() / aImage.height(), aYRel.getY() / aImage.height(),
         rNull.getX(), rNull.getY() ));
     aPainter.drawImage( QPoint(0, 0), aImage );
+    aPainter.update( aImage.rect() );
     return true;
 }
 
@@ -528,16 +561,12 @@ bool Qt5Graphics::drawAlphaRect( long nX, long nY, long nWidth,
     if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor )
         return true;
 
-    QPainter aPainter;
-    PreparePainter( aPainter, 255 - nTransparency );
+    Qt5Painter aPainter( *this, true, nTransparency );
     if ( SALCOLOR_NONE != m_aFillColor )
-    {
-        QColor aFillColor = QColor::fromRgb( QRgb( m_aFillColor ) );
-        aFillColor.setAlpha( nTransparency );
-        aPainter.fillRect( nX, nY, nWidth, nHeight, aFillColor );
-    }
+        aPainter.fillRect( nX, nY, nWidth, nHeight, aPainter.brush() );
     else
         aPainter.drawRect( nX, nY, nWidth, nHeight );
+    aPainter.update( nX, nY, nWidth, nHeight );
     return true;
 }
 
diff --git a/vcl/qt5/Qt5Painter.cxx b/vcl/qt5/Qt5Painter.cxx
new file mode 100644
index 000000000000..ab7789f854e5
--- /dev/null
+++ b/vcl/qt5/Qt5Painter.cxx
@@ -0,0 +1,56 @@
+/* -*- 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 "Qt5Painter.hxx"
+
+#include <QtGui/QColor>
+
+Qt5Painter::Qt5Painter( Qt5Graphics &rGraphics,
+                        bool bPrepareBrush, sal_uInt8 nTransparency )
+    : m_rGraphics( rGraphics )
+{
+    if ( rGraphics.m_pQImage )
+        begin( rGraphics.m_pQImage );
+    else
+    {
+        assert( rGraphics.m_pFrame );
+        begin( rGraphics.m_pFrame->GetQWidget() );
+    }
+    if ( !rGraphics.m_aClipPath.isEmpty() )
+        setClipPath( rGraphics.m_aClipPath );
+    else
+        setClipRegion( rGraphics.m_aClipRegion );
+    if ( SALCOLOR_NONE != rGraphics.m_aLineColor )
+    {
+        QColor aColor = QColor::fromRgb( QRgb( rGraphics.m_aLineColor ) );
+        aColor.setAlpha( nTransparency );
+        setPen( aColor );
+    }
+    else
+        setPen( Qt::NoPen );
+    if ( bPrepareBrush && SALCOLOR_NONE != rGraphics.m_aFillColor )
+    {
+        QColor aColor = QColor::fromRgb( QRgb( rGraphics.m_aFillColor ) );
+        aColor.setAlpha( nTransparency );
+        setBrush( Qt::SolidPattern );
+        setBrush( aColor );
+    }
+    setCompositionMode( rGraphics.m_eCompositionMode );
+}
+
diff --git a/vcl/qt5/Qt5Painter.hxx b/vcl/qt5/Qt5Painter.hxx
new file mode 100644
index 000000000000..864ac38fbb0f
--- /dev/null
+++ b/vcl/qt5/Qt5Painter.hxx
@@ -0,0 +1,67 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <QtCore/QRectF>
+#include <QtGui/QPainter>
+#include <QtWidgets/QWidget>
+
+#include "Qt5Frame.hxx"
+#include "Qt5Graphics.hxx"
+
+class Qt5Painter final : public QPainter
+{
+    Qt5Graphics &m_rGraphics;
+    QRegion      m_aRegion;
+
+public:
+    Qt5Painter( Qt5Graphics& rGraphics, bool bPrepareBrush = false,
+                sal_uInt8 nTransparency = 255 );
+    ~Qt5Painter()
+    {
+        if ( m_rGraphics.m_pFrame && !m_aRegion.isEmpty() )
+            m_rGraphics.m_pFrame->GetQWidget()->update( m_aRegion );
+    }
+
+    void update(int nx, int ny, int nw, int nh)
+    {
+        if ( m_rGraphics.m_pFrame )
+            m_aRegion += QRect( nx, ny, nw, nh );
+    }
+
+    void update(const QRect &rRect)
+    {
+        if ( m_rGraphics.m_pFrame )
+            m_aRegion += rRect;
+    }
+
+    void update(const QRectF &rRectF)
+    {
+        update( rRectF.toAlignedRect() );
+    }
+
+    void update()
+    {
+        if ( m_rGraphics.m_pFrame )
+            m_aRegion += m_rGraphics.m_pFrame->GetQWidget()->rect();
+    }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit eb9813e55f35d7f3ac115803f2d7bdec3323badc
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 20:50:19 2017 +0100

    QT5 implement alpha based drawing
    
    Change-Id: Ide2ef42110798ed061f7e32e49e38b6428c22c01

diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index 727e2dd9e833..676e9e54664e 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -91,6 +91,7 @@ bool Qt5Graphics::supportsOperation( OutDevSupportType eType ) const
     switch( eType )
     {
     case OutDevSupportType::B2DDraw:
+    case OutDevSupportType::TransparentRect:
         return true;
     default:
         return false;
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 60efb28fba30..f8434bb3bc32 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -436,27 +436,109 @@ bool Qt5Graphics::blendAlphaBitmap( const SalTwoRect&,
     return false;
 }
 
-bool Qt5Graphics::drawAlphaBitmap( const SalTwoRect&,
-                                             const SalBitmap& rSourceBitmap,
-                                             const SalBitmap& rAlphaBitmap )
+static bool getAlphaImage( const SalBitmap& rSourceBitmap,
+                           const SalBitmap& rAlphaBitmap,
+                           QImage &rAlphaImage )
 {
-    return false;
+    if (rAlphaBitmap.GetBitCount() != 8 && rAlphaBitmap.GetBitCount() != 1)
+    {
+        SAL_WARN( "vcl.gdi", "unsupported alpha depth case: "
+                  << rAlphaBitmap.GetBitCount() );
+        return false;
+    }
+
+    const QImage *pBitmap = static_cast< const Qt5Bitmap* >( &rSourceBitmap )->GetQImage();
+    const QImage *pAlpha = static_cast< const Qt5Bitmap* >( &rAlphaBitmap )->GetQImage();
+    rAlphaImage = pBitmap->convertToFormat( Qt5_DefaultFormat32 );
+
+    if ( rAlphaBitmap.GetBitCount() == 8 )
+    {
+        for (int y = 0; y < rAlphaImage.height(); ++y )
+        {
+            uchar* image_line = rAlphaImage.scanLine( y );
+            const uchar* alpha_line = pAlpha->scanLine( y );
+            for (int x = 0; x < rAlphaImage.width(); ++x, image_line += 4 )
+                image_line[ 3 ] = 255 - alpha_line[ x ];
+        }
+    }
+    else
+    {
+        for (int y = 0; y < rAlphaImage.height(); ++y )
+        {
+            uchar* image_line = rAlphaImage.scanLine( y );
+            const uchar* alpha_line = pAlpha->scanLine( y );
+            for (int x = 0; x < rAlphaImage.width(); ++x, image_line += 4 )
+            {
+                if ( x && !(x % 8) )
+                    ++alpha_line;
+                if ( 0 == (*alpha_line & (1 << (x % 8))) )
+                    image_line[0] = 0;
+            }
+        }
+    }
+
+    return true;
 }
 
-bool Qt5Graphics::drawTransformedBitmap(
-                                            const basegfx::B2DPoint& rNull,
-                                            const basegfx::B2DPoint& rX,
-                                            const basegfx::B2DPoint& rY,
-                                            const SalBitmap& rSourceBitmap,
-                                            const SalBitmap* pAlphaBitmap)
+bool Qt5Graphics::drawAlphaBitmap( const SalTwoRect& rPosAry,
+                                   const SalBitmap& rSourceBitmap,
+                                   const SalBitmap& rAlphaBitmap )
 {
-    return false;
+    QImage aImage;
+    if ( !getAlphaImage( rSourceBitmap, rAlphaBitmap, aImage ) )
+        return false;
+    PREPARE_PAINTER;
+
+    aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
+        aImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
+                       rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
+    return true;
+}
+
+bool Qt5Graphics::drawTransformedBitmap( const basegfx::B2DPoint& rNull,
+                                         const basegfx::B2DPoint& rX,
+                                         const basegfx::B2DPoint& rY,
+                                         const SalBitmap& rSourceBitmap,
+                                         const SalBitmap* pAlphaBitmap )
+{
+    QImage aImage;
+    if ( pAlphaBitmap && !getAlphaImage( rSourceBitmap, *pAlphaBitmap, aImage ) )
+        return false;
+    else
+    {
+        const QImage *pBitmap = static_cast< const Qt5Bitmap* >( &rSourceBitmap )->GetQImage();
+        aImage = pBitmap->convertToFormat( Qt5_DefaultFormat32 );
+    }
+
+    PREPARE_PAINTER;
+
+    const basegfx::B2DVector aXRel = rX - rNull;
+    const basegfx::B2DVector aYRel = rY - rNull;
+    aPainter.setTransform( QTransform(
+        aXRel.getX() / aImage.width(),  aXRel.getY() / aImage.width(),
+        aYRel.getX() / aImage.height(), aYRel.getY() / aImage.height(),
+        rNull.getX(), rNull.getY() ));
+    aPainter.drawImage( QPoint(0, 0), aImage );
+    return true;
 }
 
 bool Qt5Graphics::drawAlphaRect( long nX, long nY, long nWidth,
-                                           long nHeight, sal_uInt8 nTransparency )
+                                 long nHeight, sal_uInt8 nTransparency )
 {
-    return false;
+    if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor )
+        return true;
+
+    QPainter aPainter;
+    PreparePainter( aPainter, 255 - nTransparency );
+    if ( SALCOLOR_NONE != m_aFillColor )
+    {
+        QColor aFillColor = QColor::fromRgb( QRgb( m_aFillColor ) );
+        aFillColor.setAlpha( nTransparency );
+        aPainter.fillRect( nX, nY, nWidth, nHeight, aFillColor );
+    }
+    else
+        aPainter.drawRect( nX, nY, nWidth, nHeight );
+    return true;
 }
 
 void Qt5Graphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
commit 0fd0695073d96a9d892908e37af4367c7891dee1
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 20:31:42 2017 +0100

    QT5 port quarz Polgon and PolyPolygon handling
    
    Change-Id: I53807bff3db9c9e4300f03e56857381cad7c9431

diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index e49c959879a8..727e2dd9e833 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -55,7 +55,10 @@ void Qt5Graphics::PreparePainter( QPainter& rPainter, sal_uInt8 nTransparency )
         assert( dynamic_cast< QPaintDevice* >( m_pFrame->GetQWidget() ) );
         rPainter.begin( m_pFrame->GetQWidget() );
     }
-    rPainter.setClipRegion( m_aClipRegion );
+    if ( !m_aClipPath.isEmpty() )
+        rPainter.setClipPath( m_aClipPath );
+    else
+        rPainter.setClipRegion( m_aClipRegion );
     if ( SALCOLOR_NONE != m_aLineColor )
     {
         QColor aColor = QColor::fromRgb( QRgb( m_aLineColor ) );
@@ -83,9 +86,15 @@ SystemGraphicsData Qt5Graphics::GetGraphicsData() const
     return SystemGraphicsData();
 }
 
-bool Qt5Graphics::supportsOperation( OutDevSupportType ) const
+bool Qt5Graphics::supportsOperation( OutDevSupportType eType ) const
 {
-    return false;
+    switch( eType )
+    {
+    case OutDevSupportType::B2DDraw:
+        return true;
+    default:
+        return false;
+    }
 }
 
 #if ENABLE_CAIRO_CANVAS
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index 6077f4122e12..52c1c90ec5df 100644
--- a/vcl/qt5/Qt5Graphics.hxx
+++ b/vcl/qt5/Qt5Graphics.hxx
@@ -24,6 +24,7 @@
 #include <memory>
 
 #include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
 #include <QtGui/QRegion>
 
 class Qt5Font;
@@ -43,6 +44,7 @@ class Qt5Graphics : public SalGraphics
     Qt5Frame                     *m_pFrame;
     QImage                       *m_pQImage;
     QRegion                       m_aClipRegion;
+    QPainterPath                  m_aClipPath;
     SalColor                      m_aLineColor;
     SalColor                      m_aFillColor;
     QPainter::CompositionMode     m_eCompositionMode;
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index 89d1758f09ea..60efb28fba30 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -28,10 +28,101 @@
 #include <QtGui/QWindow>
 #include <QtWidgets/QWidget>
 
+static const basegfx::B2DPoint aHalfPointOfs ( 0.5, 0.5 );
+
+static void AddPolygonToPath( QPainterPath& rPath,
+                              const basegfx::B2DPolygon& rPolygon,
+                              bool bClosePath, bool bPixelSnap, bool bLineDraw )
+{
+    // short circuit if there is nothing to do
+    const int nPointCount = rPolygon.count();
+    if( nPointCount <= 0 )
+        return;
+
+    const bool bHasCurves = rPolygon.areControlPointsUsed();
+    for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ )
+    {
+        int nClosedIdx = nPointIdx;
+        if( nPointIdx >= nPointCount )
+        {
+            // prepare to close last curve segment if needed
+            if( bClosePath && (nPointIdx == nPointCount) )
+                nClosedIdx = 0;
+            else
+                break;
+        }
+
+        basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx );
+
+        if( bPixelSnap )
+        {
+            // snap device coordinates to full pixels
+            aPoint.setX( basegfx::fround( aPoint.getX() ) );
+            aPoint.setY( basegfx::fround( aPoint.getY() ) );
+        }
+
+        if( bLineDraw )
+            aPoint += aHalfPointOfs;
+        if( !nPointIdx )
+        {
+            // first point => just move there
+            rPath.moveTo( aPoint.getX(), aPoint.getY() );
+            continue;
+        }
+
+        bool bPendingCurve = false;
+        if( bHasCurves )
+        {
+            bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx );
+            bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx );
+        }
+
+        if( !bPendingCurve )    // line segment
+            rPath.lineTo( aPoint.getX(), aPoint.getY() );
+        else                    // cubic bezier segment
+        {
+            basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx );
+            basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx );
+            if( bLineDraw )
+            {
+                aCP1 += aHalfPointOfs;
+                aCP2 += aHalfPointOfs;
+            }
+            rPath.cubicTo( aCP1.getX(), aCP1.getY(),
+                           aCP2.getX(), aCP2.getY(), aPoint.getX(), aPoint.getY() );
+        }
+    }
+
+    if( bClosePath )
+        rPath.closeSubpath();
+}
+
+static bool AddPolyPolygonToPath( QPainterPath& rPath,
+                                  const basegfx::B2DPolyPolygon& rPolyPoly,
+                                  bool bPixelSnap, bool bLineDraw )
+{
+    const int nPolyCount = rPolyPoly.count();
+    if( nPolyCount <= 0 )
+        return false;
+    for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
+    {
+        const basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx );
+        AddPolygonToPath( rPath, rPolygon, true, bPixelSnap, bLineDraw );
+    }
+    return true;
+}
+
 bool Qt5Graphics::setClipRegion( const vcl::Region& rRegion )
 {
     if ( rRegion.IsRectangle() )
+    {
         m_aClipRegion = toQRect( rRegion.GetBoundRect() );
+        if ( !m_aClipPath.isEmpty() )
+        {
+            QPainterPath aPath;
+            m_aClipPath.swap( aPath );
+        }
+    }
     else if( !rRegion.HasPolyPolygonOrB2DPolyPolygon() )
     {
         QRegion aQRegion;
@@ -40,10 +131,23 @@ bool Qt5Graphics::setClipRegion( const vcl::Region& rRegion )
         for ( auto & rRect : aRectangles )
             aQRegion += toQRect( rRect );
         m_aClipRegion = aQRegion;
+        if ( !m_aClipPath.isEmpty() )
+        {
+            QPainterPath aPath;
+            m_aClipPath.swap( aPath );
+        }
     }
     else
     {
-        QPolygon aPolygon;
+        QPainterPath aPath;
+        const basegfx::B2DPolyPolygon aPolyClip( rRegion.GetAsB2DPolyPolygon() );
+        AddPolyPolygonToPath( aPath, aPolyClip, !getAntiAliasB2DDraw(), false );
+        m_aClipPath.swap( aPath );
+        if ( !m_aClipRegion.isEmpty() )
+        {
+            QRegion aRegion;
+            m_aClipRegion.swap( aRegion );
+        }
     }
     return true;
 }
@@ -51,6 +155,11 @@ bool Qt5Graphics::setClipRegion( const vcl::Region& rRegion )
 void Qt5Graphics::ResetClipRegion()
 {
     m_aClipRegion = QRegion( m_pQImage->rect() );
+    if ( !m_aClipPath.isEmpty() )
+    {
+        QPainterPath aPath;
+        m_aClipPath.swap( aPath );
+    }
 }
 
 void Qt5Graphics::drawPixel( long nX, long nY )
@@ -101,13 +210,32 @@ void Qt5Graphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 
 void Qt5Graphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
 {
-    if( 0 == nPoly )
-        return;
 }
 
-bool Qt5Graphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency )
+bool Qt5Graphics::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly,
+                                   double fTransparency )
 {
-    return false;
+    // ignore invisible polygons
+    if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor )
+        return true;
+    if( (fTransparency >= 1.0) || (fTransparency < 0) )
+        return true;
+
+    QPainterPath aPath;
+    // ignore empty polygons
+    if( !AddPolyPolygonToPath( aPath, rPolyPoly, !getAntiAliasB2DDraw(),
+                               m_aLineColor != SALCOLOR_NONE ) )
+        return true;
+
+    PREPARE_PAINTER;
+
+    QBrush aBrush = aPainter.brush();
+    aBrush.setStyle( SALCOLOR_NONE == m_aFillColor ? Qt::NoBrush : Qt::SolidPattern );
+    aPainter.setBrush( aBrush );
+
+    aPainter.drawPath( aPath );
+
+    return true;
 }
 
 bool Qt5Graphics::drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry )
@@ -126,14 +254,58 @@ bool Qt5Graphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPo
     return false;
 }
 
-bool Qt5Graphics::drawPolyLine( const basegfx::B2DPolygon&,
+bool Qt5Graphics::drawPolyLine( const basegfx::B2DPolygon& rPolyLine,
                                 double fTransparency,
                                 const basegfx::B2DVector& rLineWidths,
-                                basegfx::B2DLineJoin,
+                                basegfx::B2DLineJoin eLineJoin,
                                 css::drawing::LineCap eLineCap,
                                 double fMiterMinimumAngle )
 {
-    return false;
+    if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor )
+        return true;
+
+    if( basegfx::B2DLineJoin::NONE == eLineJoin )
+        return false;
+
+    // short circuit if there is nothing to do
+    const int nPointCount = rPolyLine.count();
+    if( nPointCount <= 0 )
+        return true;
+
+    // setup poly-polygon path
+    QPainterPath aPath;
+    AddPolygonToPath( aPath, rPolyLine, rPolyLine.isClosed(),
+                      !getAntiAliasB2DDraw(), true );
+
+    QPainter aPainter;
+    PreparePainter( aPainter, 255 * fTransparency );
+
+    // setup line attributes
+    QPen aPen = aPainter.pen();
+    aPen.setWidth( rLineWidths.getX() );
+
+    switch( eLineJoin )
+    {
+    case basegfx::B2DLineJoin::NONE: std::abort(); return false;
+    case basegfx::B2DLineJoin::Bevel: aPen.setJoinStyle( Qt::BevelJoin ); break;
+    case basegfx::B2DLineJoin::Round: aPen.setJoinStyle( Qt::RoundJoin ); break;
+    case basegfx::B2DLineJoin::Miter:
+        aPen.setMiterLimit( 1.0 / sin(fMiterMinimumAngle / 2.0) );
+        aPen.setJoinStyle( Qt::MiterJoin );
+        break;
+    }
+
+    switch(eLineCap)
+    {
+    default: // css::drawing::LineCap_BUTT:
+        aPen.setCapStyle( Qt::FlatCap ); break;
+    case css::drawing::LineCap_ROUND: aPen.setCapStyle( Qt::RoundCap ); break;
+    case css::drawing::LineCap_SQUARE: aPen.setCapStyle( Qt::SquareCap ); break;
+    }
+
+    aPainter.setPen( aPen );
+    aPainter.drawPath( aPath );
+    return true;
 }
 
 bool Qt5Graphics::drawGradient( const tools::PolyPolygon&, const Gradient& )
commit a498ee8ab412d4b7c3ed803b8ce02c82c96eb49b
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 20:22:56 2017 +0100

    QT5 unify Graphics constructors
    
    Change-Id: I85ce73e0e79927fa9233230bc4a9134db4c513dc

diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index 7c33c2781df4..e49c959879a8 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -26,19 +26,12 @@
 
 #include <QtGui/QImage>
 
-Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame )
+Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage )
     : m_pFrame( pFrame )
-    , m_pQImage( nullptr )
-    , m_pFontCollection( nullptr )
-    , m_pFontData{ nullptr, }
-    , m_pTextStyle{ nullptr, }
-    , m_aTextColor( MAKE_SALCOLOR(0x00, 0x00, 0x00) )
-{
-}
-
-Qt5Graphics::Qt5Graphics( QImage *pQImage )
-    : m_pFrame( nullptr )
     , m_pQImage( pQImage )
+    , m_aLineColor( MAKE_SALCOLOR(0x00, 0x00, 0x00) )
+    , m_aFillColor( MAKE_SALCOLOR(0xFF, 0xFF, 0XFF) )
+    , m_eCompositionMode( QPainter::CompositionMode_SourceOver )
     , m_pFontCollection( nullptr )
     , m_pFontData{ nullptr, }
     , m_pTextStyle{ nullptr, }
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index 30fcc2f7d5fe..6077f4122e12 100644
--- a/vcl/qt5/Qt5Graphics.hxx
+++ b/vcl/qt5/Qt5Graphics.hxx
@@ -52,11 +52,14 @@ class Qt5Graphics : public SalGraphics
     Qt5Font                      *m_pTextStyle[ MAX_FALLBACK ];
     SalColor                      m_aTextColor;
 
+    Qt5Graphics( Qt5Frame *pFrame, QImage *pQImage );
     void PreparePainter( QPainter &rPainter, sal_uInt8 nTransparency = 0xff );
 
 public:
-    Qt5Graphics( Qt5Frame *pFrame );
-    Qt5Graphics( QImage *pImage );
+    Qt5Graphics( Qt5Frame *pFrame )
+        : Qt5Graphics( pFrame, nullptr ) {}
+    Qt5Graphics( QImage *pQImage )
+        : Qt5Graphics( nullptr, pQImage ) {}
     virtual ~Qt5Graphics() override;
 
     void ChangeQImage( QImage *pImage );
commit 65403a16362e7cfed8e014b1079c6aa43b19f852
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 20:19:45 2017 +0100

    QT5 always generate a QPainter
    
    Change-Id: Ie8684cd4be56fb6d88d9643a6326307590115a80

diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index aebb486c2453..7c33c2781df4 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -53,25 +53,31 @@ Qt5Graphics::~Qt5Graphics()
         delete m_pTextStyle[ i ];
 }
 
-void Qt5Graphics::PreparePainter()
+void Qt5Graphics::PreparePainter( QPainter& rPainter, sal_uInt8 nTransparency )
 {
-    if ( m_pPainter.get() )
-        return;
     if ( m_pQImage )
-        m_pPainter.reset( new QPainter( m_pQImage ) );
+        rPainter.begin( m_pQImage );
     else
     {
         assert( dynamic_cast< QPaintDevice* >( m_pFrame->GetQWidget() ) );
-        m_pPainter.reset( new QPainter( m_pFrame->GetQWidget() ) );
+        rPainter.begin( m_pFrame->GetQWidget() );
     }
-    if (!m_aClipRegion.isEmpty())
-        m_pPainter->setClipRegion( m_aClipRegion );
+    rPainter.setClipRegion( m_aClipRegion );
+    if ( SALCOLOR_NONE != m_aLineColor )
+    {
+        QColor aColor = QColor::fromRgb( QRgb( m_aLineColor ) );
+        aColor.setAlpha( nTransparency );
+        rPainter.setPen( aColor );
+    }
+    else
+        rPainter.setPen( Qt::NoPen );
+    rPainter.setCompositionMode( m_eCompositionMode );
 }
 
 void Qt5Graphics::ChangeQImage( QImage *pQImage )
 {
-    m_pPainter.reset();
     m_pQImage = pQImage;
+    ResetClipRegion();
 }
 
 SalGraphicsImpl* Qt5Graphics::GetImpl() const
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index d9f74a05b919..30fcc2f7d5fe 100644
--- a/vcl/qt5/Qt5Graphics.hxx
+++ b/vcl/qt5/Qt5Graphics.hxx
@@ -23,6 +23,7 @@
 
 #include <memory>
 
+#include <QtGui/QPainter>
 #include <QtGui/QRegion>
 
 class Qt5Font;
@@ -30,7 +31,10 @@ class Qt5FontFace;
 class Qt5Frame;
 class PhysicalFontCollection;
 class QImage;
-class QPainter;
+
+#define PREPARE_PAINTER \
+    QPainter aPainter; \
+    PreparePainter( aPainter );
 
 class Qt5Graphics : public SalGraphics
 {
@@ -39,14 +43,16 @@ class Qt5Graphics : public SalGraphics
     Qt5Frame                     *m_pFrame;
     QImage                       *m_pQImage;
     QRegion                       m_aClipRegion;
-    std::unique_ptr< QPainter >   m_pPainter;
+    SalColor                      m_aLineColor;
+    SalColor                      m_aFillColor;
+    QPainter::CompositionMode     m_eCompositionMode;
 
     PhysicalFontCollection       *m_pFontCollection;
     const Qt5FontFace            *m_pFontData[ MAX_FALLBACK ];
     Qt5Font                      *m_pTextStyle[ MAX_FALLBACK ];
     SalColor                      m_aTextColor;
 
-    void PreparePainter();
+    void PreparePainter( QPainter &rPainter, sal_uInt8 nTransparency = 0xff );
 
 public:
     Qt5Graphics( Qt5Frame *pFrame );
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index d44055b8e841..89d1758f09ea 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -30,7 +30,6 @@
 
 bool Qt5Graphics::setClipRegion( const vcl::Region& rRegion )
 {
-    PreparePainter();
     if ( rRegion.IsRectangle() )
         m_aClipRegion = toQRect( rRegion.GetBoundRect() );
     else if( !rRegion.HasPolyPolygonOrB2DPolyPolygon() )
@@ -46,58 +45,57 @@ bool Qt5Graphics::setClipRegion( const vcl::Region& rRegion )
     {
         QPolygon aPolygon;
     }
-    m_pPainter->setClipRegion( m_aClipRegion );
     return true;
 }
 
 void Qt5Graphics::ResetClipRegion()
 {
     m_aClipRegion = QRegion( m_pQImage->rect() );
-    PreparePainter();
 }
 
 void Qt5Graphics::drawPixel( long nX, long nY )
 {
-    PreparePainter();
-    m_pPainter->drawPoint( nX, nY );
+    PREPARE_PAINTER;
+    aPainter.drawPoint( nX, nY );
 }
 
 void Qt5Graphics::drawPixel( long nX, long nY, SalColor nSalColor )
 {
-    PreparePainter();
-    m_pPainter->setPen( QColor( QRgb( nSalColor )  ) );
-    m_pPainter->drawPoint( nX, nY );
+    PREPARE_PAINTER;
+    aPainter.setPen( QColor( QRgb( nSalColor )  ) );
+    aPainter.setPen( Qt::SolidLine );
+    aPainter.drawPoint( nX, nY );
 }
 
 void Qt5Graphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
 {
-    PreparePainter();
-    m_pPainter->drawLine( nX1, nY1, nX2, nY2 );
+    PREPARE_PAINTER;
+    aPainter.drawLine( nX1, nY1, nX2, nY2 );
 }
 
 void Qt5Graphics::drawRect( long nX, long nY, long nWidth, long nHeight )
 {
-    PreparePainter();
-    m_pPainter->drawRect( nX, nY, nWidth, nHeight );
+    PREPARE_PAINTER;
+    aPainter.drawRect( nX, nY, nWidth, nHeight );
 }
 
 void Qt5Graphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    PreparePainter();
+    PREPARE_PAINTER;
     QPoint *pPoints = new QPoint[ nPoints ];
     for ( sal_uInt32 i = 0; i < nPoints; ++i, ++pPtAry )
         pPoints[ i ] = QPoint( pPtAry->mnX, pPtAry->mnY );
-    m_pPainter->drawPolyline( pPoints, nPoints );
+    aPainter.drawPolyline( pPoints, nPoints );
     delete [] pPoints;
 }
 
 void Qt5Graphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
-    PreparePainter();
+    PREPARE_PAINTER;
     QPoint *pPoints = new QPoint[ nPoints ];
     for ( sal_uInt32 i = 0; i < nPoints; ++i, ++pPtAry )
         pPoints[ i ] = QPoint( pPtAry->mnX, pPtAry->mnY );
-    m_pPainter->drawPolygon( pPoints, nPoints );
+    aPainter.drawPolygon( pPoints, nPoints );
     delete [] pPoints;
 }
 
@@ -163,8 +161,7 @@ void Qt5Graphics::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics
     assert( rPosAry.mnSrcWidth == rPosAry.mnDestWidth );
     assert( rPosAry.mnSrcHeight == rPosAry.mnDestHeight );
 
-    QImage *pImage;
-    QImage aImage;
+    QImage aImage, *pImage = &aImage;
     if ( !pSrcGraphics || this == pSrcGraphics )
     {
         if ( rPosAry.mnDestX == rPosAry.mnSrcX
@@ -172,13 +169,13 @@ void Qt5Graphics::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics
             return;
         aImage = pImage->copy( rPosAry.mnSrcX, rPosAry.mnSrcY,
                                rPosAry.mnSrcWidth, rPosAry.mnSrcHeight );
-        pImage = &aImage;
     }
     else
         pImage = static_cast< Qt5Graphics* >( pSrcGraphics )->m_pQImage;
 
-    PreparePainter();
-    m_pPainter->drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
+    PREPARE_PAINTER;
+
+    aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
         *pImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
                         rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
 }
@@ -192,11 +189,12 @@ void Qt5Graphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBi
     assert( rPosAry.mnSrcWidth == rPosAry.mnDestWidth );
     assert( rPosAry.mnSrcHeight == rPosAry.mnDestHeight );
 
-    PreparePainter();
+    PREPARE_PAINTER;
+
     const QImage *pImage = static_cast< const Qt5Bitmap* >( &rSalBitmap )->GetQImage();
     assert( pImage );
 
-    m_pPainter->drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
+    aPainter.drawImage( QPoint( rPosAry.mnDestX, rPosAry.mnDestY ),
         *pImage, QRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
                         rPosAry.mnSrcWidth, rPosAry.mnSrcHeight) );
 
@@ -319,22 +317,30 @@ long Qt5Graphics::GetGraphicsWidth() const
 
 void Qt5Graphics::SetLineColor()
 {
+    m_aLineColor = SALCOLOR_NONE;
 }
 
 void Qt5Graphics::SetLineColor( SalColor nSalColor )
 {
+    m_aLineColor = nSalColor;
 }
 
 void Qt5Graphics::SetFillColor()
 {
+    m_aFillColor = SALCOLOR_NONE;
 }
 
 void Qt5Graphics::SetFillColor( SalColor nSalColor )
 {
+    m_aFillColor = nSalColor;
 }
 
 void Qt5Graphics::SetXORMode( bool bSet )
 {
+    if ( bSet )
+        m_eCompositionMode = QPainter::CompositionMode_Xor;
+    else
+        m_eCompositionMode = QPainter::CompositionMode_SourceOver;
 }
 
 void Qt5Graphics::SetROPLineColor( SalROPColor nROPColor )
commit 421f98c3f15c15ba55f8f406bd70768ad11d1b85
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 19:55:18 2017 +0100

    QT5 implement some mouse handling
    
    Scrollwheel handling seems to work with mouse, but not correct
    when using a touchpad - at least for me.
    
    Change-Id: I4f1b32205516912e31f9c52605ba2bf4ec6059a8

diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 683f35146e2e..445029627279 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -30,6 +30,8 @@
 #include <QtGui/QIcon>
 #include <QtGui/QWindow>
 #include <QtGui/QScreen>
+#include <QtGui/QWindow>
+#include <QtWidgets/QApplication>
 
 #include <saldatabasic.hxx>
 #include <vcl/layout.hxx>
@@ -490,7 +492,12 @@ const SystemEnvData* Qt5Frame::GetSystemData() const
 
 SalFrame::SalPointerState Qt5Frame::GetPointerState()
 {
-    return SalPointerState();
+    SalPointerState aState;
+    QPoint pos = QCursor::pos();
+    aState.maPos = Point( pos.x(), pos.y() );
+    aState.mnState = GetMouseModCode( qApp->mouseButtons() ) |
+                     GetKeyModCode( qApp->keyboardModifiers() );
+    return aState;
 }
 
 KeyIndicatorState Qt5Frame::GetIndicatorState()
diff --git a/vcl/qt5/Qt5Tools.cxx b/vcl/qt5/Qt5Tools.cxx
index 5ce038b2b054..ec090a69dcbd 100644
--- a/vcl/qt5/Qt5Tools.cxx
+++ b/vcl/qt5/Qt5Tools.cxx
@@ -21,8 +21,37 @@
 
 #include <cairo.h>
 
+#include <vcl/event.hxx>
+
 void CairoDeleter::operator()(cairo_surface_t *pSurface) const
 {
     cairo_surface_destroy( pSurface );
 }
 
+sal_uInt16 GetKeyModCode( Qt::KeyboardModifiers eKeyModifiers )
+{
+    sal_uInt16 nCode = 0;
+    if( eKeyModifiers & Qt::ShiftModifier )
+        nCode |= KEY_SHIFT;
+    if( eKeyModifiers & Qt::ControlModifier )
+        nCode |= KEY_MOD1;
+    if( eKeyModifiers & Qt::AltModifier )
+        nCode |= KEY_MOD2;
+    if( eKeyModifiers & Qt::MetaModifier )
+        nCode |= KEY_MOD3;
+    return nCode;
+}
+
+sal_uInt16 GetMouseModCode( Qt::MouseButtons eButtons )
+{
+    sal_uInt16 nCode = 0;
+    if( eButtons & Qt::LeftButton )
+        nCode |= MOUSE_LEFT;
+    if( eButtons & Qt::MidButton )
+        nCode |= MOUSE_MIDDLE;
+    if( eButtons & Qt::RightButton )
+        nCode |= MOUSE_RIGHT;
+    return nCode;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Tools.hxx b/vcl/qt5/Qt5Tools.hxx
index e429f4d9c56c..b45f3c6c0738 100644
--- a/vcl/qt5/Qt5Tools.hxx
+++ b/vcl/qt5/Qt5Tools.hxx
@@ -99,4 +99,7 @@ struct CairoDeleter
 
 typedef std::unique_ptr<cairo_surface_t, CairoDeleter> UniqueCairoSurface;
 
+sal_uInt16 GetKeyModCode( Qt::KeyboardModifiers eKeyModifiers );
+sal_uInt16 GetMouseModCode( Qt::MouseButtons eButtons );
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx
index f553057fd517..195b5f2b341e 100644
--- a/vcl/qt5/Qt5Widget.cxx
+++ b/vcl/qt5/Qt5Widget.cxx
@@ -25,8 +25,10 @@
 #include "Qt5Tools.hxx"
 
 #include <QtGui/QImage>
+#include <QtGui/QMouseEvent>
 #include <QtGui/QPainter>
 #include <QtGui/QPaintEvent>
+#include <QtGui/QWheelEvent>
 
 #include <cairo.h>
 #include <headless/svpgdi.hxx>
@@ -36,6 +38,7 @@ Qt5Widget::Qt5Widget( Qt5Frame &rFrame, QWidget *parent, Qt::WindowFlags f )
     , m_pFrame( &rFrame )
 {
     create();
+    setMouseTracking( true );
 }
 
 Qt5Widget::~Qt5Widget()
@@ -81,4 +84,88 @@ void Qt5Widget::resizeEvent( QResizeEvent* )
     m_pFrame->CallCallback( SalEvent::Resize, nullptr );
 }
 
+void Qt5Widget::mouseButtonEvent( QMouseEvent *pEvent, bool bReleased )
+{
+    SalMouseEvent aEvent;
+    switch( pEvent->button() )
+    {
+    case Qt::LeftButton: aEvent.mnButton = MOUSE_LEFT; break;
+    case Qt::MidButton: aEvent.mnButton = MOUSE_MIDDLE; break;
+    case Qt::RightButton: aEvent.mnButton = MOUSE_RIGHT; break;
+    default: return;
+    }
+
+    aEvent.mnTime   = pEvent->timestamp();
+    aEvent.mnX      = (long) pEvent->pos().x();
+    aEvent.mnY      = (long) pEvent->pos().y();
+    aEvent.mnCode   = GetKeyModCode( pEvent->modifiers() ) |
+                      GetMouseModCode( pEvent->buttons() );
+
+    SalEvent nEventType;
+    if ( bReleased )
+        nEventType = SalEvent::MouseButtonUp;
+    else
+        nEventType = SalEvent::MouseButtonDown;
+    m_pFrame->CallCallback( nEventType, &aEvent );
+}
+
+void Qt5Widget::mousePressEvent( QMouseEvent *pEvent )
+{
+    mouseButtonEvent( pEvent, false );
+}
+
+void Qt5Widget::mouseReleaseEvent( QMouseEvent *pEvent )
+{
+    mouseButtonEvent( pEvent, true );
+}
+
+void Qt5Widget::mouseMoveEvent( QMouseEvent *pEvent )
+{
+    SalMouseEvent aEvent;
+    aEvent.mnTime = pEvent->timestamp();
+    aEvent.mnX    = pEvent->pos().x();
+    aEvent.mnY    = pEvent->pos().y();
+    aEvent.mnCode = GetKeyModCode( pEvent->modifiers() ) |
+                    GetMouseModCode( pEvent->buttons() );
+    aEvent.mnButton = 0;
+
+    m_pFrame->CallCallback( SalEvent::MouseMove, &aEvent );
+    pEvent->accept();
+}
+
+void Qt5Widget::wheelEvent( QWheelEvent *pEvent )
+{
+    SalWheelMouseEvent aEvent;
+
+    aEvent.mnTime = pEvent->timestamp();
+    aEvent.mnX    = pEvent->pos().x();
+    aEvent.mnY    = pEvent->pos().y();
+    aEvent.mnCode = GetKeyModCode( pEvent->modifiers() ) |
+                    GetMouseModCode( pEvent->buttons() );
+
+    int nDelta = pEvent->angleDelta().x();
+    aEvent.mbHorz = true;
+    if ( !nDelta )
+    {
+        nDelta = pEvent->angleDelta().y();
+        aEvent.mbHorz = false;
+    }
+    if ( !nDelta )
+        return;
+    nDelta /= 8;
+
+    aEvent.mnDelta = nDelta;
+    aEvent.mnNotchDelta = nDelta > 0 ? 1 : -1;
+    aEvent.mnScrollLines = 3;
+
+    m_pFrame->CallCallback( SalEvent::WheelMouse, &aEvent );
+    pEvent->accept();
+}
+
+void Qt5Widget::moveEvent( QMoveEvent* )
+{
+    m_pFrame->CallCallback( SalEvent::Move, nullptr );
+}
+
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Widget.hxx b/vcl/qt5/Qt5Widget.hxx
index 3f6b32dfd613..83375278c738 100644
--- a/vcl/qt5/Qt5Widget.hxx
+++ b/vcl/qt5/Qt5Widget.hxx
@@ -23,8 +23,11 @@
 
 class Qt5Frame;
 class Qt5Object;
+class QMouseEvent;
+class QMoveEvent;
 class QPaintEvent;
 class QResizeEvent;
+class QWheelEvent;
 
 class Qt5Widget
     : public QWidget
@@ -33,8 +36,15 @@ class Qt5Widget
 
     Qt5Frame  *m_pFrame;
 
+    void mouseButtonEvent( QMouseEvent*, bool );
+
     void paintEvent( QPaintEvent* ) override;
     void resizeEvent( QResizeEvent* ) override;
+    void moveEvent( QMoveEvent* ) override;
+    void mouseMoveEvent( QMouseEvent*) override;
+    void mousePressEvent( QMouseEvent*) override;
+    void mouseReleaseEvent( QMouseEvent*) override;
+    void wheelEvent( QWheelEvent* ) override;
 
 public:
     Qt5Widget( Qt5Frame &rFrame,
commit ac46f795402fc6deafeedb583e134be4ba28dd03
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 19:44:40 2017 +0100

    QT5 port more of the gtk3 positioning code
    
    Change-Id: I36631c332ddffbca73768cdc4a596213e0b026ef

diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index 0eb1a6e6bc05..683f35146e2e 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -29,8 +29,10 @@
 #include <QtCore/QSize>
 #include <QtGui/QIcon>
 #include <QtGui/QWindow>
+#include <QtGui/QScreen>
 
 #include <saldatabasic.hxx>
+#include <vcl/layout.hxx>
 #include <vcl/syswin.hxx>
 
 #include <cairo.h>
@@ -48,6 +50,8 @@ Qt5Frame::Qt5Frame( Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo
     : m_bUseCairo( bUseCairo )
     , m_bGraphicsInUse( false )
     , m_ePointerStyle( PointerStyle::Arrow )
+    , m_bDefaultSize( true )
+    , m_bDefaultPos( true )
 {
     Qt5Instance *pInst = static_cast<Qt5Instance*>( GetSalData()->m_pInstance );
     pInst->insertFrame( this );
@@ -240,8 +244,70 @@ void Qt5Frame::SetMaxClientSize( long nWidth, long nHeight )
         m_pQWidget->setMaximumSize( nWidth, nHeight );
 }
 
+void Qt5Frame::Center()
+{
+    if ( m_pParent )
+    {
+        QWidget *pWindow = m_pParent->GetQWidget()->window();
+        m_pQWidget->move(
+            pWindow->frameGeometry().topLeft() +
+            pWindow->rect().center() - m_pQWidget->rect().center() );
+    }
+}
+
+Size Qt5Frame::CalcDefaultSize()
+{
+    assert( m_pQWidget->isWindow() );
+    QScreen *pScreen = m_pQWidget->windowHandle()->screen();
+    if( !pScreen )
+        return Size();
+    return bestmaxFrameSizeForScreenSize( toSize( pScreen->size() ) );
+}
+
+void Qt5Frame::SetDefaultSize()
+{
+    Size aDefSize = CalcDefaultSize();
+    SetPosSize( 0, 0, aDefSize.Width(), aDefSize.Height(),
+                SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
+}
+
 void Qt5Frame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags )
 {
+    if( !m_pQWidget->isWindow() || isChild( true, false ) )
+        return;
+
+
+    if( (nFlags & ( SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT )) &&
+        (nWidth > 0 && nHeight > 0 ) // sometimes stupid things happen
+            )
+    {
+        m_bDefaultSize = false;
+        if( isChild( false ) || !m_pQWidget->isMaximized() )
+        {
+            m_pQWidget->resize( nWidth, nHeight );
+        }
+    }
+    else if( m_bDefaultSize )
+        SetDefaultSize();
+
+    m_bDefaultSize = false;
+
+    if( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) )
+    {
+        if( m_pParent )
+        {
+            QRect aRect = m_pParent->GetQWidget()->geometry();
+            nX += aRect.x();
+            nY += aRect.y();
+        }
+
+        m_bDefaultPos = false;
+        m_pQWidget->move( nX, nY );
+    }
+    else if( m_bDefaultPos )
+        Center();
+
+    m_bDefaultPos = false;
 }
 
 void Qt5Frame::GetClientSize( long& rWidth, long& rHeight )
@@ -252,6 +318,14 @@ void Qt5Frame::GetClientSize( long& rWidth, long& rHeight )
 
 void Qt5Frame::GetWorkArea( tools::Rectangle& rRect )
 {
+    if( !m_pQWidget->isWindow() )
+        return;
+    QScreen *pScreen = m_pQWidget->windowHandle()->screen();
+    if( !pScreen )
+        return;
+
+    QSize aSize = pScreen->availableVirtualSize();
+    rRect = tools::Rectangle( 0, 0, aSize.width(), aSize.height() );
 }
 
 SalFrame* Qt5Frame::GetParent() const
@@ -277,16 +351,26 @@ void Qt5Frame::SetWindowState( const SalFrameState* pState )
     else if( pState->mnMask & (WindowStateMask::X | WindowStateMask::Y |
                                WindowStateMask::Width | WindowStateMask::Height ) )
     {
-        QRect rect = m_pQWidget->geometry();
-        if ( pState->mnMask & WindowStateMask::X )
-            rect.setX( pState->mnX );
-        if ( pState->mnMask & WindowStateMask::Y )
-            rect.setY( pState->mnY );
-        if ( pState->mnMask & WindowStateMask::Width )
-            rect.setWidth( pState->mnWidth );
-        if ( pState->mnMask & WindowStateMask::Height )
-            rect.setHeight( pState->mnHeight );
-        m_pQWidget->setGeometry( rect );
+        sal_uInt16 nPosSizeFlags = 0;
+        QPoint aPos = m_pQWidget->pos();
+        QPoint aParentPos;
+        if( m_pParent )
+            aParentPos = m_pParent->GetQWidget()->window()->pos();
+        long nX = pState->mnX - aParentPos.x();
+        long nY = pState->mnY - aParentPos.y();
+        if( pState->mnMask & WindowStateMask::X )
+            nPosSizeFlags |= SAL_FRAME_POSSIZE_X;
+        else
+            nX = aPos.x() - aParentPos.x();
+        if( pState->mnMask & WindowStateMask::Y )
+            nPosSizeFlags |= SAL_FRAME_POSSIZE_Y;
+        else
+            nY = aPos.y() - aParentPos.y();
+        if( pState->mnMask & WindowStateMask::Width )
+            nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH;
+        if( pState->mnMask & WindowStateMask::Height )
+            nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT;
+        SetPosSize( nX, nY, pState->mnWidth, pState->mnHeight, nPosSizeFlags );
     }
     else if( pState->mnMask & WindowStateMask::State && ! isChild() )
     {
@@ -320,6 +404,7 @@ bool Qt5Frame::GetWindowState( SalFrameState* pState )
                            WindowStateMask::Height;
     }
 
+
     return true;
 }
 
diff --git a/vcl/qt5/Qt5Frame.hxx b/vcl/qt5/Qt5Frame.hxx
index 1d736bfb280f..5863c925a83b 100644
--- a/vcl/qt5/Qt5Frame.hxx
+++ b/vcl/qt5/Qt5Frame.hxx
@@ -52,6 +52,13 @@ class Qt5Frame
     Qt5Frame                       *m_pParent;
     PointerStyle                    m_ePointerStyle;
 
+    bool                            m_bDefaultSize;
+    bool                            m_bDefaultPos;
+
+    void                        Center();
+    Size                        CalcDefaultSize();
+    void                        SetDefaultSize();
+
     bool isChild( bool bPlug = true, bool bSysChild = true )
     {
         SalFrameStyleFlags nMask = SalFrameStyleFlags::NONE;
commit 860ea62d758a39842225c8c163c2e5e83697f294
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 19:39:18 2017 +0100

    QT5 rotate generated bitmap
    
    QImage stores the scanlines from top => bottom.
    
    Change-Id: I0a176066ab631179b8460b61a6c2b07ad2179d31

diff --git a/vcl/qt5/Qt5Bitmap.cxx b/vcl/qt5/Qt5Bitmap.cxx
index 524eaf6048c2..6fcff9e05663 100644
--- a/vcl/qt5/Qt5Bitmap.cxx
+++ b/vcl/qt5/Qt5Bitmap.cxx
@@ -193,23 +193,23 @@ BitmapBuffer* Qt5Bitmap::AcquireBuffer( BitmapAccessMode nMode )
     switch( pBuffer->mnBitCount )
     {
         case 1:
-            pBuffer->mnFormat = ScanlineFormat::N1BitLsbPal;
+            pBuffer->mnFormat = ScanlineFormat::N1BitLsbPal | ScanlineFormat::TopDown;
             pBuffer->maPalette = m_aPalette;
             break;
         case 4:
-            pBuffer->mnFormat = ScanlineFormat::N4BitMsnPal;
+            pBuffer->mnFormat = ScanlineFormat::N4BitMsnPal | ScanlineFormat::TopDown;
             pBuffer->maPalette = m_aPalette;
             break;
         case 8:
-            pBuffer->mnFormat = ScanlineFormat::N8BitPal;
+            pBuffer->mnFormat = ScanlineFormat::N8BitPal | ScanlineFormat::TopDown;
             pBuffer->maPalette = m_aPalette;
             break;
         case 16:
         {
 #ifdef OSL_BIGENDIAN
-            pBuffer->mnFormat= ScanlineFormat::N16BitTcMsbMask;
+            pBuffer->mnFormat= ScanlineFormat::N16BitTcMsbMask | ScanlineFormat::TopDown;
 #else
-            pBuffer->mnFormat= ScanlineFormat::N16BitTcLsbMask;
+            pBuffer->mnFormat= ScanlineFormat::N16BitTcLsbMask | ScanlineFormat::TopDown;
 #endif
             ColorMaskElement aRedMask(0xf800); // 5
             aRedMask.CalcMaskShift();
@@ -222,12 +222,12 @@ BitmapBuffer* Qt5Bitmap::AcquireBuffer( BitmapAccessMode nMode )
             break;
         }
         case 24:
-            pBuffer->mnFormat = ScanlineFormat::N24BitTcRgb;
+            pBuffer->mnFormat = ScanlineFormat::N24BitTcRgb | ScanlineFormat::TopDown;
             pBuffer->maPalette = aEmptyPalette;
             break;
         case 32:
         {
-            pBuffer->mnFormat = ScanlineFormat::N32BitTcArgb;
+            pBuffer->mnFormat = ScanlineFormat::N32BitTcArgb | ScanlineFormat::TopDown;
             pBuffer->maPalette = aEmptyPalette;
             break;
         }
@@ -239,6 +239,15 @@ BitmapBuffer* Qt5Bitmap::AcquireBuffer( BitmapAccessMode nMode )
 void Qt5Bitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode )
 {
     m_aPalette = pBuffer->maPalette;
+    auto count = m_aPalette.GetEntryCount();
+    if( pBuffer->mnBitCount != 4 && count )
+    {
+        QVector<QRgb> aColorTable( count );
+        for ( unsigned i = 0; i < count; ++i )
+            aColorTable[ i ] = qRgb( m_aPalette[ i ].GetRed(),
+                m_aPalette[ i ].GetGreen(), m_aPalette[ i ].GetBlue() );
+        m_pImage->setColorTable( aColorTable );
+    }
     delete pBuffer;
 }
 
commit 97730c41e6f2eae87e727b12df01afbecfa28f22
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 19:32:45 2017 +0100

    QT5 implement cursor support
    
    Change-Id: Ie47b8def36d67255b61eab04bc7e3818bb1d8ea8

diff --git a/vcl/qt5/Qt5Data.cxx b/vcl/qt5/Qt5Data.cxx
index f8d4483bf761..f05e30ce662f 100644
--- a/vcl/qt5/Qt5Data.cxx
+++ b/vcl/qt5/Qt5Data.cxx
@@ -17,14 +17,19 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <QtWidgets/QStyle>
-#include <QtWidgets/QApplication>
-
 #include "Qt5Data.hxx"
 
+#include <QtGui/QCursor>
+#include <QtGui/QBitmap>
+
+#include <unx/x11_cursors/salcursors.h>
+
 Qt5Data::Qt5Data( SalInstance *pInstance )
     : GenericUnixSalData( SAL_DATA_QT5, pInstance )
 {
+    for (QCursor* & rpCsr : m_aCursors)
+        rpCsr = nullptr;
+
     ImplSVData *pSVData = ImplGetSVData();
 
     // draw toolbars on separate lines
@@ -35,8 +40,162 @@ Qt5Data::Qt5Data( SalInstance *pInstance )
 
 Qt5Data::~Qt5Data()
 {
+    for (QCursor* & rpCsr : m_aCursors)
+        delete rpCsr;
+}
+
+static QCursor* getQCursorFromXBM( const unsigned char *pBitmap,
+                                   const unsigned char *pMask,
+                                   int nWidth, int nHeight,
+                                   int nXHot, int nYHot )
+{
+    QBitmap aPixmap;
+    aPixmap.loadFromData( pBitmap, nWidth * nHeight / 8, "XPM" );
+    QBitmap aMask;
+    aMask.loadFromData( pMask, nWidth * nHeight / 8, "XPM" );
+    aPixmap.setMask( aMask );
+    return new QCursor( aPixmap, nXHot, nYHot );
 }
 
+#define MAKE_CURSOR( vcl_name, name ) \
+    case vcl_name: \
+        pCursor = getQCursorFromXBM( name##curs##_bits, name##mask##_bits, \
+                                     name##curs_width, name##curs_height, \
+                                     name##curs_x_hot, name##curs_y_hot ); \
+        break
+
+#define MAP_BUILTIN( vcl_name, qt_enum ) \
+    case vcl_name: \
+        pCursor = new QCursor( qt_enum ); \
+        break
+
+QCursor& Qt5Data::getCursor( PointerStyle ePointerStyle )
+{
+    if ( !m_aCursors[ ePointerStyle ] )
+    {
+        QCursor *pCursor = nullptr;
+
+        switch( ePointerStyle )
+        {
+            MAP_BUILTIN( PointerStyle::Arrow, Qt::ArrowCursor );
+            MAP_BUILTIN( PointerStyle::Text, Qt::IBeamCursor );
+            MAP_BUILTIN( PointerStyle::Help, Qt::WhatsThisCursor );
+            MAP_BUILTIN( PointerStyle::Cross, Qt::CrossCursor );
+            MAP_BUILTIN( PointerStyle::Wait, Qt::WaitCursor );
+            MAP_BUILTIN( PointerStyle::NSize, Qt::SizeVerCursor );
+            MAP_BUILTIN( PointerStyle::SSize, Qt::SizeVerCursor );
+            MAP_BUILTIN( PointerStyle::WSize, Qt::SizeHorCursor );
+            MAP_BUILTIN( PointerStyle::ESize, Qt::SizeHorCursor );
+
+            MAP_BUILTIN( PointerStyle::NWSize, Qt::SizeFDiagCursor );
+            MAP_BUILTIN( PointerStyle::NESize, Qt::SizeBDiagCursor );
+            MAP_BUILTIN( PointerStyle::SWSize, Qt::SizeBDiagCursor );
+            MAP_BUILTIN( PointerStyle::SESize, Qt::SizeFDiagCursor );
+#if 0
+            MAP_BUILTIN( PointerStyle::WindowNSize, GDK_TOP_SIDE );
+            MAP_BUILTIN( PointerStyle::WindowSSize, GDK_BOTTOM_SIDE );
+            MAP_BUILTIN( PointerStyle::WindowWSize, GDK_LEFT_SIDE );
+            MAP_BUILTIN( PointerStyle::WindowESize, GDK_RIGHT_SIDE );
+#endif
+            MAP_BUILTIN( PointerStyle::WindowNWSize, Qt::SizeFDiagCursor );
+            MAP_BUILTIN( PointerStyle::WindowNESize, Qt::SizeBDiagCursor );
+            MAP_BUILTIN( PointerStyle::WindowSWSize, Qt::SizeBDiagCursor );
+            MAP_BUILTIN( PointerStyle::WindowSESize, Qt::SizeFDiagCursor );
+
+            MAP_BUILTIN( PointerStyle::HSizeBar, Qt::SizeHorCursor );
+            MAP_BUILTIN( PointerStyle::VSizeBar, Qt::SizeVerCursor );
+
+            MAP_BUILTIN( PointerStyle::RefHand, Qt::OpenHandCursor );
+            MAP_BUILTIN( PointerStyle::Hand, Qt::OpenHandCursor );
+#if 0
+            MAP_BUILTIN( PointerStyle::Pen, GDK_PENCIL );
+#endif
+            MAP_BUILTIN( PointerStyle::HSplit, Qt::SizeHorCursor );
+            MAP_BUILTIN( PointerStyle::VSplit, Qt::SizeVerCursor );
+
+            MAP_BUILTIN( PointerStyle::Move, Qt::SizeAllCursor );
+
+            MAP_BUILTIN( PointerStyle::Null, Qt::BlankCursor );
+            MAKE_CURSOR( PointerStyle::Magnify, magnify_ );
+            MAKE_CURSOR( PointerStyle::Fill, fill_ );
+            MAKE_CURSOR( PointerStyle::MoveData, movedata_ );
+            MAKE_CURSOR( PointerStyle::CopyData, copydata_ );
+            MAKE_CURSOR( PointerStyle::MoveFile, movefile_ );
+            MAKE_CURSOR( PointerStyle::CopyFile, copyfile_ );
+            MAKE_CURSOR( PointerStyle::MoveFiles, movefiles_ );
+            MAKE_CURSOR( PointerStyle::CopyFiles, copyfiles_ );
+            MAKE_CURSOR( PointerStyle::NotAllowed, nodrop_ );
+            MAKE_CURSOR( PointerStyle::Rotate, rotate_ );
+            MAKE_CURSOR( PointerStyle::HShear, hshear_ );
+            MAKE_CURSOR( PointerStyle::VShear, vshear_ );
+            MAKE_CURSOR( PointerStyle::DrawLine, drawline_ );
+            MAKE_CURSOR( PointerStyle::DrawRect, drawrect_ );
+            MAKE_CURSOR( PointerStyle::DrawPolygon, drawpolygon_ );
+            MAKE_CURSOR( PointerStyle::DrawBezier, drawbezier_ );
+            MAKE_CURSOR( PointerStyle::DrawArc, drawarc_ );
+            MAKE_CURSOR( PointerStyle::DrawPie, drawpie_ );
+            MAKE_CURSOR( PointerStyle::DrawCircleCut, drawcirclecut_ );
+            MAKE_CURSOR( PointerStyle::DrawEllipse, drawellipse_ );
+            MAKE_CURSOR( PointerStyle::DrawConnect, drawconnect_ );
+            MAKE_CURSOR( PointerStyle::DrawText, drawtext_ );
+            MAKE_CURSOR( PointerStyle::Mirror, mirror_ );
+            MAKE_CURSOR( PointerStyle::Crook, crook_ );
+            MAKE_CURSOR( PointerStyle::Crop, crop_ );
+            MAKE_CURSOR( PointerStyle::MovePoint, movepoint_ );
+            MAKE_CURSOR( PointerStyle::MoveBezierWeight, movebezierweight_ );
+            MAKE_CURSOR( PointerStyle::DrawFreehand, drawfreehand_ );
+            MAKE_CURSOR( PointerStyle::DrawCaption, drawcaption_ );
+            MAKE_CURSOR( PointerStyle::LinkData, linkdata_ );
+            MAKE_CURSOR( PointerStyle::MoveDataLink, movedlnk_ );
+            MAKE_CURSOR( PointerStyle::CopyDataLink, copydlnk_ );
+            MAKE_CURSOR( PointerStyle::LinkFile, linkfile_ );
+            MAKE_CURSOR( PointerStyle::MoveFileLink, moveflnk_ );
+            MAKE_CURSOR( PointerStyle::CopyFileLink, copyflnk_ );
+            MAKE_CURSOR( PointerStyle::Chart, chart_ );
+            MAKE_CURSOR( PointerStyle::Detective, detective_ );
+            MAKE_CURSOR( PointerStyle::PivotCol, pivotcol_ );
+            MAKE_CURSOR( PointerStyle::PivotRow, pivotrow_ );
+            MAKE_CURSOR( PointerStyle::PivotField, pivotfld_ );
+            MAKE_CURSOR( PointerStyle::PivotDelete, pivotdel_ );
+            MAKE_CURSOR( PointerStyle::Chain, chain_ );
+            MAKE_CURSOR( PointerStyle::ChainNotAllowed, chainnot_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollN, asn_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollS, ass_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollW, asw_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollE, ase_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollNW, asnw_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollNE, asne_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollSW, assw_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollSE, asse_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollNS, asns_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollWE, aswe_ );
+            MAKE_CURSOR( PointerStyle::AutoScrollNSWE, asnswe_ );
+            MAKE_CURSOR( PointerStyle::TextVertical, vertcurs_ );
+
+            MAKE_CURSOR( PointerStyle::TabSelectS, tblsels_ );
+            MAKE_CURSOR( PointerStyle::TabSelectE, tblsele_ );
+            MAKE_CURSOR( PointerStyle::TabSelectSE, tblselse_ );
+            MAKE_CURSOR( PointerStyle::TabSelectW, tblselw_ );
+            MAKE_CURSOR( PointerStyle::TabSelectSW, tblselsw_ );
+
+            MAKE_CURSOR( PointerStyle::HideWhitespace, hidewhitespace_ );
+            MAKE_CURSOR( PointerStyle::ShowWhitespace, showwhitespace_ );
+        default:
+            break;
+        }
+        if( !pCursor )
+        {
+            pCursor = new QCursor( Qt::ArrowCursor );
+            SAL_WARN( "vcl.qt5", "pointer " << static_cast<int>(ePointerStyle) << "not implemented" );
+        }
+
+        m_aCursors[ ePointerStyle ] = pCursor;
+    }
+
+    return *m_aCursors[ ePointerStyle ];
+}
+
+
 void Qt5Data::ErrorTrapPush()
 {
 }
diff --git a/vcl/qt5/Qt5Data.hxx b/vcl/qt5/Qt5Data.hxx
index 31859ce9637c..75e1a813e1f9 100644
--- a/vcl/qt5/Qt5Data.hxx
+++ b/vcl/qt5/Qt5Data.hxx
@@ -21,14 +21,23 @@
 
 #include <unx/gendata.hxx>
 
+#include <o3tl/enumarray.hxx>
+#include <vcl/ptrstyle.hxx>
+
+class QCursor;
+
 class Qt5Data : public GenericUnixSalData
 {
+    o3tl::enumarray<PointerStyle, QCursor*> m_aCursors;
+
 public:
     explicit Qt5Data( SalInstance *pInstance );
     virtual ~Qt5Data() override;
 
     virtual void ErrorTrapPush() override;
     virtual bool ErrorTrapPop( bool bIgnoreError = true ) override;
+
+    QCursor& getCursor( PointerStyle ePointerStyle );
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Frame.cxx b/vcl/qt5/Qt5Frame.cxx
index b6939863a125..0eb1a6e6bc05 100644
--- a/vcl/qt5/Qt5Frame.cxx
+++ b/vcl/qt5/Qt5Frame.cxx
@@ -23,6 +23,7 @@
 #include "Qt5Instance.hxx"
 #include "Qt5Graphics.hxx"
 #include "Qt5Widget.hxx"
+#include "Qt5Data.hxx"
 
 #include <QtCore/QPoint>
 #include <QtCore/QSize>
@@ -46,6 +47,7 @@ static void SvpDamageHandler( void *handle,
 Qt5Frame::Qt5Frame( Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo )
     : m_bUseCairo( bUseCairo )
     , m_bGraphicsInUse( false )
+    , m_ePointerStyle( PointerStyle::Arrow )
 {
     Qt5Instance *pInst = static_cast<Qt5Instance*>( GetSalData()->m_pInstance );
     pInst->insertFrame( this );
@@ -339,6 +341,14 @@ void Qt5Frame::ToTop( SalFrameToTop nFlags )
 
 void Qt5Frame::SetPointer( PointerStyle ePointerStyle )
 {
+    QWindow *pWindow = m_pQWidget->window()->windowHandle();
+    if( !pWindow )
+        return;
+    if( ePointerStyle == m_ePointerStyle )
+        return;
+    m_ePointerStyle = ePointerStyle;
+
+    pWindow->setCursor( static_cast<Qt5Data*>( GetSalData() )->getCursor( ePointerStyle ) );
 }
 
 void Qt5Frame::CaptureMouse( bool bMouse )
diff --git a/vcl/qt5/Qt5Frame.hxx b/vcl/qt5/Qt5Frame.hxx
index 538b5eabed9c..1d736bfb280f 100644
--- a/vcl/qt5/Qt5Frame.hxx
+++ b/vcl/qt5/Qt5Frame.hxx
@@ -50,6 +50,7 @@ class Qt5Frame
     bool                            m_bGraphicsInUse;
     SalFrameStyleFlags              m_nStyle;
     Qt5Frame                       *m_pParent;
+    PointerStyle                    m_ePointerStyle;
 
     bool isChild( bool bPlug = true, bool bSysChild = true )
     {
commit de16439d513e4049d94b5a6b64189e5e6f446922
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Mon Oct 30 19:05:41 2017 +0100

    QT5 first stab on implementing CommonSalLayout
    
    CommonSalLayout doesn't really have an interface. It's cluttered
    with #ifdefs. Therefore we have to move the Qt5Font into the VCL
    library. Someone should refactor this...
    Eventually that would cut down the public interface of VCL again.
    
    Doesn't render any text yet, but reports some sizes.
    
    Change-Id: I12f32affb05b37e070c6cbc80db01779f84590b6

diff --git a/config_host/config_qt5.h.in b/config_host/config_qt5.h.in
index cdce1af7800c..51bb58566f2b 100644
--- a/config_host/config_qt5.h.in
+++ b/config_host/config_qt5.h.in
@@ -5,6 +5,7 @@ Settings for QT5 integration.
 #ifndef CONFIG_QT5_H
 #define CONFIG_QT5_H
 
+#define ENABLE_QT5 0
 #define QT5_HAVE_GLIB 0
 
 #endif
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index cbe6de3afce7..699d6abd67f5 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -719,4 +719,22 @@ ifeq ($(OS),WNT)
 $(eval $(call gb_Library_use_package,vcl,postprocess_images))
 endif
 
+ifeq ($(ENABLE_QT5),TRUE)
+$(eval $(call gb_Library_use_externals,vcl,\
+	qt5 \
+))
+$(eval $(call gb_Library_add_defs,vcl,\
+    $(QT5_CFLAGS) \
+))
+$(eval $(call gb_Library_add_libs,vcl,\
+    $(QT5_LIBS) \
+))
+$(eval $(call gb_Library_add_cxxflags,vcl,\
+    $(QT5_CFLAGS) \
+))
+$(eval $(call gb_Library_add_exception_objects,vcl,\
+    vcl/qt5/Qt5Font \
+))
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vclplug_qt5.mk b/vcl/Library_vclplug_qt5.mk
index 333812f939bb..d82b7d2fcd31 100644
--- a/vcl/Library_vclplug_qt5.mk
+++ b/vcl/Library_vclplug_qt5.mk
@@ -53,11 +53,14 @@ $(eval $(call gb_Library_use_libraries,vclplug_qt5,\
 ))
 
 $(eval $(call gb_Library_use_externals,vclplug_qt5,\
-	boost_headers \
-	cairo \
-	icuuc \
-	qt5 \
-	epoxy \
+    boost_headers \
+    cairo \
+    epoxy \
+    graphite \
+    harfbuzz \
+    icu_headers \
+    icuuc \
+    qt5 \
 ))
 
 $(eval $(call gb_Library_add_defs,vclplug_qt5,\
diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index 02eef73a1dc8..a8808bac8414 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -20,6 +20,8 @@
 #ifndef INCLUDED_VCL_INC_COMMONSALLAYOUT_HXX
 #define INCLUDED_VCL_INC_COMMONSALLAYOUT_HXX
 
+#include <config_qt5.h>
+
 #include <com/sun/star/i18n/XBreakIterator.hpp>
 
 #ifdef _WIN32
@@ -37,7 +39,11 @@
 #include <hb-icu.h>
 #include <hb-ot.h>
 
-class CommonSalLayout : public GenericSalLayout
+#if ENABLE_QT5
+class Qt5Font;
+#endif
+
+class VCL_DLLPUBLIC CommonSalLayout : public GenericSalLayout
 {
     hb_font_t*              mpHbFont;
     const FontSelectPattern& mrFontSelData;
@@ -50,7 +56,11 @@ class CommonSalLayout : public GenericSalLayout
 #elif defined(MACOSX) || defined(IOS)
     const CoreTextStyle&    mrCoreTextStyle;
 #else
-    FreetypeFont&           mrFreetypeFont;
+    FreetypeFont*           mpFreetypeFont;
+#if ENABLE_QT5
+    const bool              mbUseQt5;
+    Qt5Font*                mpQFont;
+#endif
 #endif
 
     void                    ParseFeatures(const OUString& name);
@@ -67,16 +77,24 @@ class CommonSalLayout : public GenericSalLayout
 public:
 #if defined(_WIN32)
     explicit                CommonSalLayout(HDC, WinFontInstance&, const WinFontFace&);
-    const FontSelectPattern& getFontSelData() const { return mrFontSelData; };
+    const FontSelectPattern& getFontSelData() const { return mrFontSelData; }
     HFONT                   getHFONT() const { return mhFont; }
     WinFontInstance&        getWinFontInstance() const { return mrWinFontInstance; }
     bool                    hasHScale() const;
 #elif defined(MACOSX) || defined(IOS)
     explicit                CommonSalLayout(const CoreTextStyle&);
-    const CoreTextStyle&    getFontData() const { return mrCoreTextStyle; };
+    const CoreTextStyle&    getFontData() const { return mrCoreTextStyle; }
 #else
     explicit                CommonSalLayout(FreetypeFont&);
-    const FreetypeFont&     getFontData() const { return mrFreetypeFont; };
+    const FreetypeFont*     getFreetypeFont() const { return mpFreetypeFont; }
+#if ENABLE_QT5
+    explicit                CommonSalLayout(const FontSelectPattern &rFSP,
+                                            FreetypeFont *pFreetypeFont,
+                                            Qt5Font *pFont, bool bUseQt5);
+    explicit                CommonSalLayout(Qt5Font&);
+    const Qt5Font*          getQt5Font() const { return mpQFont; }
+    bool                    useQt5() const { return mbUseQt5; }
+#endif
 #endif
 
     virtual void            InitFont() const override;
diff --git a/vcl/inc/impfontmetricdata.hxx b/vcl/inc/impfontmetricdata.hxx
index 14ad323b9b77..fd15e5765164 100644
--- a/vcl/inc/impfontmetricdata.hxx
+++ b/vcl/inc/impfontmetricdata.hxx
@@ -32,7 +32,7 @@ typedef tools::SvRef<ImplFontMetricData> ImplFontMetricDataRef;
 class OutputDevice;
 class FontSelectPattern;
 
-class ImplFontMetricData : public FontAttributes, public SvRefBase
+class VCL_DLLPUBLIC ImplFontMetricData : public FontAttributes, public SvRefBase
 {
 public:
     explicit        ImplFontMetricData( const FontSelectPattern& );
diff --git a/vcl/inc/qt5/Qt5Font.hxx b/vcl/inc/qt5/Qt5Font.hxx
new file mode 100644
index 000000000000..d8981578831a
--- /dev/null
+++ b/vcl/inc/qt5/Qt5Font.hxx
@@ -0,0 +1,43 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <vcl/dllapi.h>
+#include <QtGui/QFont>
+
+#include <fontselect.hxx>
+#include <hb-ot.h>
+
+class VCL_DLLPUBLIC Qt5Font : public QFont
+{
+    const FontSelectPattern m_aFontSelData;
+    hb_font_t* m_pHbFont;
+
+public:
+    Qt5Font( const FontSelectPattern& rFSP)
+        : m_aFontSelData( rFSP ), m_pHbFont( nullptr ) {}
+    virtual ~Qt5Font();
+
+    hb_font_t*                GetHbFont() const { return m_pHbFont; }
+    void                      SetHbFont( hb_font_t* pHbFont ) { m_pHbFont = pHbFont; }
+    const FontSelectPattern&  GetFontSelData() const { return m_aFontSelData; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
index df183dba2056..c512628862fa 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -133,7 +133,7 @@ public:
     const FontSelectPattern& GetFontSelData() const      { return maFontSelData; }
 
     void                    GetFontMetric(ImplFontMetricDataRef const &) const;
-    const unsigned char*    GetTable( const char* pName, sal_uLong* pLength );
+    const unsigned char*    GetTable( const char* pName, sal_uLong* pLength ) const;
     const FontCharMapRef    GetFontCharMap() const;
     bool                    GetFontCapabilities(vcl::FontCapabilities &) const;
 
diff --git a/vcl/qt5/Qt5Font.cxx b/vcl/qt5/Qt5Font.cxx
new file mode 100644
index 000000000000..8ad5e2b0c040
--- /dev/null
+++ b/vcl/qt5/Qt5Font.cxx
@@ -0,0 +1,26 @@
+/* -*- 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 <qt5/Qt5Font.hxx>
+
+Qt5Font::~Qt5Font()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx
index 701509b06108..347f6bb58ba5 100644
--- a/vcl/qt5/Qt5FontFace.cxx
+++ b/vcl/qt5/Qt5FontFace.cxx
@@ -65,7 +65,7 @@ sal_IntPtr Qt5FontFace::GetFontId() const
     return reinterpret_cast<sal_IntPtr>( &m_aFontId );
 }
 
-const FontCharMapRef Qt5FontFace::GetFontCharMap()
+const FontCharMapRef Qt5FontFace::GetFontCharMap() const
 {
     if( m_xCharMap.is() )
         return m_xCharMap;
@@ -88,7 +88,7 @@ const FontCharMapRef Qt5FontFace::GetFontCharMap()
     return m_xCharMap;
 }
 
-bool Qt5FontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities)
+bool Qt5FontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
 {
     // read this only once per font
     if( m_bFontCapabilitiesRead )
diff --git a/vcl/qt5/Qt5FontFace.hxx b/vcl/qt5/Qt5FontFace.hxx
index 76b8fdee99f1..7cfbdf8be702 100644
--- a/vcl/qt5/Qt5FontFace.hxx
+++ b/vcl/qt5/Qt5FontFace.hxx
@@ -44,8 +44,8 @@ public:
 
     int                      GetFontTable( const char pTagName[5], unsigned char* ) const;
 
-    const FontCharMapRef     GetFontCharMap();
-    bool                     GetFontCapabilities( vcl::FontCapabilities &rFontCapabilities );
+    const FontCharMapRef     GetFontCharMap() const;
+    bool                     GetFontCapabilities( vcl::FontCapabilities &rFontCapabilities ) const;
     bool                     HasChar( sal_uInt32 cChar ) const;
 
 protected:
@@ -53,10 +53,10 @@ protected:
                              Qt5FontFace( const FontAttributes& rFA, const QString &rFontID );
 
 private:
-    const QString            m_aFontId;
-    FontCharMapRef           m_xCharMap;
-    vcl::FontCapabilities    m_aFontCapabilities;
-    bool                     m_bFontCapabilitiesRead;
+    const QString                    m_aFontId;
+    mutable FontCharMapRef           m_xCharMap;
+    mutable vcl::FontCapabilities    m_aFontCapabilities;
+    mutable bool                     m_bFontCapabilitiesRead;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/Qt5Graphics.cxx b/vcl/qt5/Qt5Graphics.cxx
index 1d0d15677eb4..aebb486c2453 100644
--- a/vcl/qt5/Qt5Graphics.cxx
+++ b/vcl/qt5/Qt5Graphics.cxx
@@ -30,6 +30,9 @@ Qt5Graphics::Qt5Graphics( Qt5Frame *pFrame )
     : m_pFrame( pFrame )
     , m_pQImage( nullptr )
     , m_pFontCollection( nullptr )
+    , m_pFontData{ nullptr, }
+    , m_pTextStyle{ nullptr, }
+    , m_aTextColor( MAKE_SALCOLOR(0x00, 0x00, 0x00) )
 {
 }
 
@@ -37,11 +40,17 @@ Qt5Graphics::Qt5Graphics( QImage *pQImage )
     : m_pFrame( nullptr )
     , m_pQImage( pQImage )
     , m_pFontCollection( nullptr )
+    , m_pFontData{ nullptr, }
+    , m_pTextStyle{ nullptr, }
+    , m_aTextColor( MAKE_SALCOLOR(0x00, 0x00, 0x00) )
 {
 }
 
 Qt5Graphics::~Qt5Graphics()
 {
+    // release the text styles
+    for (int i = 0; i < MAX_FALLBACK; ++i)
+        delete m_pTextStyle[ i ];
 }
 
 void Qt5Graphics::PreparePainter()
diff --git a/vcl/qt5/Qt5Graphics.hxx b/vcl/qt5/Qt5Graphics.hxx
index b021134e54b7..d9f74a05b919 100644
--- a/vcl/qt5/Qt5Graphics.hxx
+++ b/vcl/qt5/Qt5Graphics.hxx
@@ -25,9 +25,10 @@
 
 #include <QtGui/QRegion>
 
+class Qt5Font;
+class Qt5FontFace;
 class Qt5Frame;
 class PhysicalFontCollection;
-class PhysicalFontFace;
 class QImage;
 class QPainter;
 
@@ -39,8 +40,11 @@ class Qt5Graphics : public SalGraphics
     QImage                       *m_pQImage;
     QRegion                       m_aClipRegion;
     std::unique_ptr< QPainter >   m_pPainter;
+
     PhysicalFontCollection       *m_pFontCollection;
-    PhysicalFontFace             *m_pFont;
+    const Qt5FontFace            *m_pFontData[ MAX_FALLBACK ];
+    Qt5Font                      *m_pTextStyle[ MAX_FALLBACK ];
+    SalColor                      m_aTextColor;
 
     void PreparePainter();
 
diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx
index fe6931c84458..0053a56c412d 100644
--- a/vcl/qt5/Qt5Graphics_Text.cxx
+++ b/vcl/qt5/Qt5Graphics_Text.cxx
@@ -19,34 +19,78 @@
 
 #include "Qt5Graphics.hxx"
 #include "Qt5FontFace.hxx"
+#include <qt5/Qt5Font.hxx>
 
 #include <vcl/fontcharmap.hxx>
 
+#include <CommonSalLayout.hxx>
 #include <PhysicalFontCollection.hxx>
 
 #include <QtGui/QFontDatabase>
+#include <QtGui/QRawFont>
 #include <QtCore/QStringList>
 
 void Qt5Graphics::SetTextColor( SalColor nSalColor )
 {
+    m_aTextColor = nSalColor;
 }
 
-void Qt5Graphics::SetFont( const FontSelectPattern*, int nFallbackLevel )
+void Qt5Graphics::SetFont( const FontSelectPattern* pReqFont, int nFallbackLevel )
 {
+    // release the text styles
+    for (int i = nFallbackLevel; i < MAX_FALLBACK; ++i)
+    {
+        if ( !m_pTextStyle[ i ] )
+            break;
+        delete m_pTextStyle[ i ];
+        m_pTextStyle[ i ] = nullptr;
+    }
+
+    if( !pReqFont )
+        // handle release-font-resources request
+        m_pFontData[ nFallbackLevel ] = nullptr;
+    else
+    {
+        m_pFontData[ nFallbackLevel ] = static_cast<const Qt5FontFace*>( pReqFont->mpFontData );
+        m_pTextStyle[ nFallbackLevel ] = new Qt5Font( *pReqFont );
+    }
 }
 
 void Qt5Graphics::GetFontMetric( ImplFontMetricDataRef &rFMD, int nFallbackLevel )
 {
+    QRawFont aRawFont( QRawFont::fromFont( *m_pTextStyle[ nFallbackLevel ] ) );
+
+    QByteArray aHheaTable = aRawFont.fontTable( "hhea" );
+    std::vector<uint8_t> rHhea(aHheaTable.data(), aHheaTable.data() + aHheaTable.size() );
+
+    QByteArray aOs2Table = aRawFont.fontTable( "OS/2" );
+    std::vector<uint8_t> rOS2(aHheaTable.data(), aHheaTable.data() + aHheaTable.size() );
+
+    rFMD->ImplCalcLineSpacing( rHhea, rOS2, aRawFont.unitsPerEm() );
+
+    rFMD->SetWidth( aRawFont.averageCharWidth() );
+
+    const QChar nKashidaCh[ 2 ] = { 0x06, 0x40 };
+    quint32 nKashidaGid = 0;
+    QPointF aPoint;
+    int nNumGlyphs;
+    if( aRawFont.glyphIndexesForChars( nKashidaCh, 1, &nKashidaGid, &nNumGlyphs )
+            && aRawFont.advancesForGlyphIndexes( &nKashidaGid, &aPoint, 1 ) )
+        rFMD->SetMinKashida( lrint(aPoint.rx()) );
 }
 
 const FontCharMapRef Qt5Graphics::GetFontCharMap() const
 {
-    return nullptr;
+    if( !m_pFontData[ 0 ] )
+        return FontCharMapRef( new FontCharMap() );
+    return m_pFontData[ 0 ]->GetFontCharMap();
 }
 
 bool Qt5Graphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
 {
-    return false;
+    if( !m_pFontData[ 0 ] )
+        return false;
+    return m_pFontData[ 0 ]->GetFontCapabilities( rFontCapabilities );
 }
 
 void Qt5Graphics::GetDevFontList( PhysicalFontCollection* pPFC )
@@ -90,7 +134,7 @@ void Qt5Graphics::FreeEmbedFontData( const void* pData, long nDataLen )
 {
 }
 
-void Qt5Graphics::GetGlyphWidths( const PhysicalFontFace*, bool bVertical,
+void Qt5Graphics::GetGlyphWidths( const PhysicalFontFace* pPFF, bool bVertical,
                                   std::vector< sal_Int32 >& rWidths,
                                   Ucs2UIntMap& rUnicodeEnc )
 {
@@ -108,6 +152,8 @@ bool Qt5Graphics::GetGlyphOutline( const GlyphItem&, basegfx::B2DPolyPolygon& )
 
 SalLayout* Qt5Graphics::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
 {
+    if( m_pTextStyle[ nFallbackLevel ] )
+        return new CommonSalLayout( *m_pTextStyle[ nFallbackLevel ] );
     return nullptr;
 }
 
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 4f896e694b59..2871b99c7ddb 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -29,6 +29,11 @@
 #include <unicode/uchar.h>
 #include <android/compatibility.hxx>
 
+#if ENABLE_QT5
+#include <qt5/Qt5Font.hxx>
+#include <QtGui/QRawFont>
+#endif
+
 static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
 {
     char pTagName[5];
@@ -62,9 +67,23 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU
         pFont->GetFontTable(pTagName, pBuffer);
     }
 #else
-    const unsigned char* pBuffer = nullptr;
-    FreetypeFont* pFont = static_cast<FreetypeFont*>(pUserData);
-    pBuffer = pFont->GetTable(pTagName, &nLength);
+    const char* pBuffer = nullptr;
+    CommonSalLayout *pLayout = static_cast<CommonSalLayout*>( pUserData );
+#if ENABLE_QT5
+    QByteArray aTable;
+    if ( pLayout->useQt5() )
+    {
+        QRawFont aRawFont( QRawFont::fromFont( *pLayout->getQt5Font() ) );
+        aTable = aRawFont.fontTable( pTagName );
+        pBuffer = reinterpret_cast<const char*>( aTable.data() );
+        nLength = aTable.size();
+    }
+    else
+#endif
+    {
+        pBuffer = reinterpret_cast<const char*>(
+            pLayout->getFreetypeFont()->GetTable(pTagName, &nLength) );
+    }
 #endif
 
     hb_blob_t* pBlob = nullptr;
@@ -73,7 +92,7 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU
         pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY,
                                pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); });
 #else
-        pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr);
+        pBlob = hb_blob_create(pBuffer, nLength, HB_MEMORY_MODE_READONLY, nullptr, nullptr);
 #endif
 
     return pBlob;
@@ -234,20 +253,62 @@ CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle)
 }
 
 #else
-CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont)
-:   mrFontSelData(rFreetypeFont.GetFontSelData())
-,   mrFreetypeFont(rFreetypeFont)
-,   mpVertGlyphs(nullptr)
+
+#if ENABLE_QT5
+CommonSalLayout::CommonSalLayout(const FontSelectPattern &rFSP,
+                                 FreetypeFont *pFreetypeFont,
+                                 Qt5Font *pQt5Font, bool bUseQt5)
+    : mrFontSelData(rFSP)
+    , mpFreetypeFont(pFreetypeFont)
+    , mbUseQt5(bUseQt5)
+    , mpQFont(pQt5Font)
+    , mpVertGlyphs(nullptr)
 {
-    mpHbFont = rFreetypeFont.GetHbFont();
+    if (mbUseQt5)
+        mpHbFont = mpQFont->GetHbFont();
+    else
+        mpHbFont = mpFreetypeFont->GetHbFont();
     if (!mpHbFont)
     {
-        hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, &rFreetypeFont, nullptr);
+        hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, this, nullptr);
 
         mpHbFont = createHbFont(pHbFace);
-        mrFreetypeFont.SetHbFont(mpHbFont);
+        if (mbUseQt5)
+            mpQFont->SetHbFont(mpHbFont);
+        else
+            mpFreetypeFont->SetHbFont(mpHbFont);
     }
 }
+
+CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont)
+    : CommonSalLayout(rFreetypeFont.GetFontSelData(),
+                      &rFreetypeFont, nullptr, false)
+{
+}
+
+CommonSalLayout::CommonSalLayout(Qt5Font& rQFont)
+    : CommonSalLayout(rQFont.GetFontSelData(),
+                      nullptr, &rQFont, true)
+{
+}
+
+#else // ! ENABLE_QT5
+
+CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont)
+    : mrFontSelData(rFreetypeFont.GetFontSelData())
+    , mpFreetypeFont(&rFreetypeFont)
+    , mpVertGlyphs(nullptr)
+{
+    mpHbFont = mpFreetypeFont->GetHbFont();
+    if (!mpHbFont)
+    {
+        hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, this, nullptr);
+        mpHbFont = createHbFont(pHbFace);
+        mpFreetypeFont->SetHbFont(mpHbFont);
+    }
+}
+
+#endif
 #endif
 
 void CommonSalLayout::InitFont() const
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
index 5b03eda92eef..d868ff701049 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -157,7 +157,7 @@ namespace
 
 void CairoTextRender::DrawTextLayout(const CommonSalLayout& rLayout)
 {
-    const FreetypeFont& rFont = rLayout.getFontData();
+    const FreetypeFont& rFont = *rLayout.getFreetypeFont();
 
     std::vector<cairo_glyph_t> cairo_glyphs;
     std::vector<int> glyph_extrarotation;
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
index 57393255bcee..5a55ee47bff3 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -973,7 +973,7 @@ bool FreetypeFont::GetGlyphOutline(const GlyphItem& rGlyph,
     return true;
 }
 
-const unsigned char* FreetypeFont::GetTable(const char* pName, sal_uLong* pLength)
+const unsigned char* FreetypeFont::GetTable(const char* pName, sal_uLong* pLength) const
 {
     return mpFontInfo->GetTable( pName, pLength );
 }


More information about the Libreoffice-commits mailing list