Rebased ref, commits from common ancestor: commit 0b1e8399df0045fe900d5558afc8590114d4b922 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Fri Nov 3 18:43:30 2017 +0100
QT5 fix build issues & cleanups 1. Linking problem on Windows due to Windows macros via <vcl/sysdata.hxx> include 2. Drop the custom MOC target for the old KF5 plugin 3. Correctly handle QT5 build without using QFont 4. ImplJobSetup is in the VL library, not the gen plugin Change-Id: Iad97b1b9b57a8c356aaa88178aff03d0c14558c7 diff --git a/vcl/CustomTarget_kf5_moc.mk b/vcl/CustomTarget_kf5_moc.mk deleted file mode 100644 index f636ef5d125c..000000000000 --- a/vcl/CustomTarget_kf5_moc.mk +++ /dev/null @@ -1,22 +0,0 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- -# -# 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/. -# - -$(eval $(call gb_CustomTarget_CustomTarget,vcl/unx/kf5)) - -$(call gb_CustomTarget_get_target,vcl/unx/kf5) : \ - $(call gb_CustomTarget_get_workdir,vcl/unx/kf5)/Kf5Timer.moc \ - $(call gb_CustomTarget_get_workdir,vcl/unx/kf5)/Kf5Widget.moc \ - -$(call gb_CustomTarget_get_workdir,vcl/unx/kf5)/%.moc : \ - $(SRCDIR)/vcl/unx/kf5/%.hxx \ - | $(call gb_CustomTarget_get_workdir,vcl/unx/kf5)/.dir - $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1) - $(MOC5) $< -o $@ - -# vim: set noet sw=4: diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx index a44fee5cfe10..a8808bac8414 100644 --- a/vcl/inc/CommonSalLayout.hxx +++ b/vcl/inc/CommonSalLayout.hxx @@ -45,13 +45,6 @@ class Qt5Font; class VCL_DLLPUBLIC CommonSalLayout : public GenericSalLayout { -#if ENABLE_QT5 - friend hb_blob_t* getFontTable(hb_face_t*, hb_tag_t, void*); - explicit CommonSalLayout(const FontSelectPattern &rFSP, - FreetypeFont *pFreetypeFont, - Qt5Font *pFont, bool bUseQt5); -#endif - hb_font_t* mpHbFont; const FontSelectPattern& mrFontSelData; css::uno::Reference<css::i18n::XBreakIterator> mxBreak; @@ -84,19 +77,23 @@ class VCL_DLLPUBLIC 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* getFreetypeFont() const { return mpFreetypeFont; }; + 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; }; + const Qt5Font* getQt5Font() const { return mpQFont; } + bool useQt5() const { return mbUseQt5; } #endif #endif diff --git a/vcl/inc/jobset.h b/vcl/inc/jobset.h index dc04e9a54bd1..5ff4c38e9a24 100644 --- a/vcl/inc/jobset.h +++ b/vcl/inc/jobset.h @@ -29,7 +29,7 @@ #define JOBSETUP_SYSTEM_UNIX 3 #define JOBSETUP_SYSTEM_MAC 4 -class VCL_PLUGIN_PUBLIC ImplJobSetup +class VCL_DLLPUBLIC ImplJobSetup { private: sal_uInt16 mnSystem; //< System - JOBSETUP_SYSTEM_xxxx diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx index a368630ebd74..1a9157ca9747 100644 --- a/vcl/inc/salgdi.hxx +++ b/vcl/inc/salgdi.hxx @@ -21,7 +21,6 @@ #define INCLUDED_VCL_INC_SALGDI_HXX #include <vcl/metric.hxx> -#include <vcl/sysdata.hxx> #include "impfontmetricdata.hxx" #include "salgdiimpl.hxx" @@ -46,6 +45,7 @@ class OpenGLContext; class OutputDevice; class FreetypeFont; class CommonSalLayout; +struct SystemGraphicsData; #if ENABLE_CAIRO_CANVAS struct SystemFontData; 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/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 936369983d14..2871b99c7ddb 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -32,11 +32,9 @@ #if ENABLE_QT5 #include <qt5/Qt5Font.hxx> #include <QtGui/QRawFont> -#else -class Qt5Font; #endif -hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) { char pTagName[5]; pTagName[0] = (char)(nTableTag >> 24); @@ -70,12 +68,12 @@ hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData } #else const char* pBuffer = nullptr; -#if ENABLE_QT5 CommonSalLayout *pLayout = static_cast<CommonSalLayout*>( pUserData ); +#if ENABLE_QT5 QByteArray aTable; - if ( pLayout->mbUseQt5 ) + if ( pLayout->useQt5() ) { - QRawFont aRawFont( QRawFont::fromFont( *pLayout->mpQFont ) ); + QRawFont aRawFont( QRawFont::fromFont( *pLayout->getQt5Font() ) ); aTable = aRawFont.fontTable( pTagName ); pBuffer = reinterpret_cast<const char*>( aTable.data() ); nLength = aTable.size(); @@ -83,9 +81,8 @@ hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData else #endif { - FreetypeFont* pFont = static_cast<FreetypeFont*>(pUserData); pBuffer = reinterpret_cast<const char*>( - pFont->GetTable(pTagName, &nLength) ); + pLayout->getFreetypeFont()->GetTable(pTagName, &nLength) ); } #endif @@ -282,27 +279,35 @@ CommonSalLayout::CommonSalLayout(const FontSelectPattern &rFSP, mpFreetypeFont->SetHbFont(mpHbFont); } } -#endif -CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) : - mrFontSelData(rFreetypeFont.GetFontSelData()) -, mpFreetypeFont(&rFreetypeFont) -, mpVertGlyphs(nullptr) +CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) + : CommonSalLayout(rFreetypeFont.GetFontSelData(), + &rFreetypeFont, nullptr, false) { - mpHbFont = rFreetypeFont.GetHbFont(); - if (!mpHbFont) - { - hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, &rFreetypeFont, nullptr); - mpHbFont = createHbFont(pHbFace); - } } -#if ENABLE_QT5 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 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 ); } commit e8526657a20b6c9c25cf885a7f6caa6bb38e3f7c Author: Thorsten Behrens <thorsten.behr...@cib.de> Date: Thu Nov 2 01:49:00 2017 +0100 QT5 fixup non-qt5 build Change-Id: Ifea73d81ba3863fd6a99453cb38303eb729f6ff4 diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 132766753174..936369983d14 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -70,8 +70,8 @@ hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData } #else const char* pBuffer = nullptr; - CommonSalLayout *pLayout = static_cast<CommonSalLayout*>( pUserData ); #if ENABLE_QT5 + CommonSalLayout *pLayout = static_cast<CommonSalLayout*>( pUserData ); QByteArray aTable; if ( pLayout->mbUseQt5 ) { @@ -83,8 +83,9 @@ hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData else #endif { + FreetypeFont* pFont = static_cast<FreetypeFont*>(pUserData); pBuffer = reinterpret_cast<const char*>( - pLayout->mpFreetypeFont->GetTable(pTagName, &nLength) ); + pFont->GetTable(pTagName, &nLength) ); } #endif @@ -256,41 +257,44 @@ CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle) #else +#if ENABLE_QT5 CommonSalLayout::CommonSalLayout(const FontSelectPattern &rFSP, FreetypeFont *pFreetypeFont, Qt5Font *pQt5Font, bool bUseQt5) : mrFontSelData(rFSP) , mpFreetypeFont(pFreetypeFont) -#if ENABLE_QT5 , mbUseQt5(bUseQt5) , mpQFont(pQt5Font) -#endif , mpVertGlyphs(nullptr) { -#if ENABLE_QT5 if (mbUseQt5) mpHbFont = mpQFont->GetHbFont(); else -#endif mpHbFont = mpFreetypeFont->GetHbFont(); if (!mpHbFont) { hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, this, nullptr); mpHbFont = createHbFont(pHbFace); -#if ENABLE_QT5 if (mbUseQt5) mpQFont->SetHbFont(mpHbFont); else -#endif mpFreetypeFont->SetHbFont(mpHbFont); } } +#endif -CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) - : CommonSalLayout(rFreetypeFont.GetFontSelData(), - &rFreetypeFont, nullptr, false) +CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) : + mrFontSelData(rFreetypeFont.GetFontSelData()) +, mpFreetypeFont(&rFreetypeFont) +, mpVertGlyphs(nullptr) { + mpHbFont = rFreetypeFont.GetHbFont(); + if (!mpHbFont) + { + hb_face_t* pHbFace = hb_face_create_for_tables(getFontTable, &rFreetypeFont, nullptr); + mpHbFont = createHbFont(pHbFace); + } } #if ENABLE_QT5 commit efb96db1095c07155e30eac270d1ddcfb4c0fec2 Author: Jan-Marek Glogowski <glo...@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: */ diff --git a/vcl/qt5/Qt5Widget.cxx b/vcl/qt5/Qt5Widget.cxx index 90ef68e9e9a7..195b5f2b341e 100644 --- a/vcl/qt5/Qt5Widget.cxx +++ b/vcl/qt5/Qt5Widget.cxx @@ -55,7 +55,6 @@ void Qt5Widget::paintEvent( QPaintEvent *pEvent ) 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 commit e391db0974d6c3a8188b883a0927bed339436fbc Author: Jan-Marek Glogowski <glo...@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 5f84bf9addfa07446bede180833c94df24233b9e Author: Jan-Marek Glogowski <glo...@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 e05161edd26f00ee8d06403f6c4f946fa14464b5 Author: Jan-Marek Glogowski <glo...@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 c512af2bc6aea89b471c20927372c8769c8f866d Author: Jan-Marek Glogowski <glo...@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 1426437be0530a8ba5749c7e76c5ce0e9053af2f Author: Jan-Marek Glogowski <glo...@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 7682a4717ae0..90ef68e9e9a7 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() @@ -82,4 +85,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 843ec5e37f290dca79f8f1245a18d67112f4427f Author: Jan-Marek Glogowski <glo...@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 173c460c26eaec9d81dc9eae6d5a73116cb3ac41 Author: Jan-Marek Glogowski <glo...@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 7b8c97984b1c0d747621235288718f675a3778f6 Author: Jan-Marek Glogowski <glo...@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 b66a7cbd8491fe436126e11975c360f47ae346ed Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Mon Oct 30 19:05:41 2017 +0100 QT5 first stab on implementing CommonSalLayout CommonSalLayout doesn't rally have an interface. It's cluttered with #ifdefs. Currently we have to move the Qt5Font into the VCL library. Someone should refactor this... Doen't render any text yet, but reports some sizes. Eventually that would cut down the public interface again. 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/CustomTarget_qt5_moc.mk b/vcl/CustomTarget_qt5_moc.mk index 8d22eb6e9288..60d5df34d405 100644 --- a/vcl/CustomTarget_qt5_moc.mk +++ b/vcl/CustomTarget_qt5_moc.mk @@ -9,12 +9,12 @@ $(eval $(call gb_CustomTarget_CustomTarget,vcl/qt5)) -$(call gb_CustomTarget_get_target,vcl/unx/qt5) : \ +$(call gb_CustomTarget_get_target,vcl/qt5) : \ $(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Instance.moc \ $(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Timer.moc \ $(call gb_CustomTarget_get_workdir,vcl/qt5)/Qt5Widget.moc \ -$(call gb_CustomTarget_get_workdir,vcl/unx/qt5)/%.moc : \ +$(call gb_CustomTarget_get_workdir,vcl/qt5)/%.moc : \ $(SRCDIR)/vcl/qt5/%.hxx \ | $(call gb_CustomTarget_get_workdir,vcl/qt5)/.dir $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),MOC,1) 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..a44fee5cfe10 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,8 +39,19 @@ #include <hb-icu.h> #include <hb-ot.h> -class CommonSalLayout : public GenericSalLayout +#if ENABLE_QT5 +class Qt5Font; +#endif + +class VCL_DLLPUBLIC CommonSalLayout : public GenericSalLayout { +#if ENABLE_QT5 + friend hb_blob_t* getFontTable(hb_face_t*, hb_tag_t, void*); + explicit CommonSalLayout(const FontSelectPattern &rFSP, + FreetypeFont *pFreetypeFont, + Qt5Font *pFont, bool bUseQt5); +#endif + hb_font_t* mpHbFont; const FontSelectPattern& mrFontSelData; css::uno::Reference<css::i18n::XBreakIterator> mxBreak; @@ -50,7 +63,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); @@ -76,7 +93,11 @@ public: 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(Qt5Font&); + const Qt5Font* getQt5Font() const { return mpQFont; }; +#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/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..132766753174 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -29,7 +29,14 @@ #include <unicode/uchar.h> #include <android/compatibility.hxx> -static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) +#if ENABLE_QT5 +#include <qt5/Qt5Font.hxx> +#include <QtGui/QRawFont> +#else +class Qt5Font; +#endif + +hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) { char pTagName[5]; pTagName[0] = (char)(nTableTag >> 24); @@ -62,9 +69,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->mbUseQt5 ) + { + QRawFont aRawFont( QRawFont::fromFont( *pLayout->mpQFont ) ); + aTable = aRawFont.fontTable( pTagName ); + pBuffer = reinterpret_cast<const char*>( aTable.data() ); + nLength = aTable.size(); + } + else +#endif + { + pBuffer = reinterpret_cast<const char*>( + pLayout->mpFreetypeFont->GetTable(pTagName, &nLength) ); + } #endif hb_blob_t* pBlob = nullptr; @@ -73,7 +94,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 +255,51 @@ CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle) } #else -CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) -: mrFontSelData(rFreetypeFont.GetFontSelData()) -, mrFreetypeFont(rFreetypeFont) -, mpVertGlyphs(nullptr) + +CommonSalLayout::CommonSalLayout(const FontSelectPattern &rFSP, + FreetypeFont *pFreetypeFont, + Qt5Font *pQt5Font, bool bUseQt5) + : mrFontSelData(rFSP) + , mpFreetypeFont(pFreetypeFont) +#if ENABLE_QT5 + , mbUseQt5(bUseQt5) + , mpQFont(pQt5Font) +#endif + , mpVertGlyphs(nullptr) { - mpHbFont = rFreetypeFont.GetHbFont(); +#if ENABLE_QT5 + if (mbUseQt5) + mpHbFont = mpQFont->GetHbFont(); + else +#endif + 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 ENABLE_QT5 + if (mbUseQt5) + mpQFont->SetHbFont(mpHbFont); + else +#endif + mpFreetypeFont->SetHbFont(mpHbFont); } } + +CommonSalLayout::CommonSalLayout(FreetypeFont& rFreetypeFont) + : CommonSalLayout(rFreetypeFont.GetFontSelData(), ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits