basctl/source/basicide/baside2b.cxx | 1 include/vcl/salgtype.hxx | 15 +++ sfx2/source/appl/appdispatchprovider.cxx | 5 + vcl/inc/fontselect.hxx | 2 vcl/inc/qt5/Qt5Bitmap.hxx | 2 vcl/inc/qt5/Qt5FontFace.hxx | 1 vcl/inc/qt5/Qt5Graphics.hxx | 2 vcl/inc/qt5/Qt5Tools.hxx | 2 vcl/qt5/Qt5Bitmap.cxx | 80 +++++++++++++++++--- vcl/qt5/Qt5Font.cxx | 53 +++++++++++++ vcl/qt5/Qt5FontFace.cxx | 64 ++++++++++++++-- vcl/qt5/Qt5Graphics_GDI.cxx | 124 +++++++++++++++++++++---------- vcl/qt5/Qt5Graphics_Text.cxx | 67 ++++++++++++++++ vcl/qt5/Qt5Instance.cxx | 7 + vcl/source/font/fontcache.cxx | 2 15 files changed, 364 insertions(+), 63 deletions(-)
New commits: commit 9a5b1d50806706328404060806bf3ee936b4baaf Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:24:28 2018 +0200 Qt5 use fontconfig for font substitution This just shoves all known fonts from the PrintFontManager into the QFontDatabase. Can be disabled using SAL_VCL_QT5_NO_FONTCONFIG. It already feels slow - don't know. Running "./bin/run vcldemo --show text" you can see it has some pro and cons, regarding the output. Qts' diacrits look definitly nicer then the "substitutions". This brings the font support kind of on par with the other backends. And since sensible font substitition is not at all implemented in Qt, we have to rely on some platform ssolution anyway. And this needs a sensible, platform agnostic interface, so we can reuse the code easier. Change-Id: I4e9d8ee98fc479a7c4bbe4c968116e0a102ebb7a diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index a9f9175e6d48..c45b678d88a5 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -248,9 +248,31 @@ void Qt5Graphics::drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry) aPainter.update(aPolygon.boundingRect()); } -void Qt5Graphics::drawPolyPolygon(sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/, - PCONSTSALPOINT* /*pPtAry*/) +void Qt5Graphics::drawPolyPolygon(sal_uInt32 nPolyCount, const sal_uInt32* pPoints, + PCONSTSALPOINT* ppPtAry) { + // ignore invisible polygons + if (SALCOLOR_NONE == m_aFillColor && SALCOLOR_NONE == m_aLineColor) + return; + + QPainterPath aPath; + for (sal_uInt32 nPoly = 0; nPoly < nPolyCount; nPoly++) + { + const sal_uInt32 nPoints = pPoints[nPoly]; + if (nPoints > 1) + { + const SalPoint* pPtAry = ppPtAry[nPoly]; + aPath.moveTo(pPtAry->mnX, pPtAry->mnY); + pPtAry++; + for (sal_uInt32 nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++) + aPath.lineTo(pPtAry->mnX, pPtAry->mnY); + aPath.closeSubpath(); + } + } + + Qt5Painter aPainter(*this, true); + aPainter.drawPath(aPath); + aPainter.update(aPath.boundingRect()); } bool Qt5Graphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency) diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx index 282432214589..92e9a416d74a 100644 --- a/vcl/qt5/Qt5Graphics_Text.cxx +++ b/vcl/qt5/Qt5Graphics_Text.cxx @@ -23,6 +23,8 @@ #include <Qt5Painter.hxx> #include <vcl/fontcharmap.hxx> +#include <unx/geninst.h> +#include <unx/fontmanager.hxx> #include <sallayout.hxx> #include <PhysicalFontCollection.hxx> @@ -89,11 +91,33 @@ bool Qt5Graphics::GetFontCapabilities(vcl::FontCapabilities& rFontCapabilities) void Qt5Graphics::GetDevFontList(PhysicalFontCollection* pPFC) { + static const bool bUseFontconfig = (nullptr == getenv("SAL_VCL_QT5_NO_FONTCONFIG")); + m_pFontCollection = pPFC; if (pPFC->Count()) return; QFontDatabase aFDB; + + if (bUseFontconfig) + { + ::std::vector<psp::fontID> aList; + psp::FastPrintFontInfo aInfo; + + psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); + rMgr.getFontList(aList); + for (auto const& elem : aList) + { + if (!rMgr.getFontFastInfo(elem, aInfo)) + continue; + QString aFilename = toQString( + OStringToOUString(rMgr.getFontFileSysPath(aInfo.m_nID), RTL_TEXTENCODING_UTF8)); + aFDB.addApplicationFont(aFilename); + } + + SalGenericInstance::RegisterFontSubstitutors(pPFC); + } + for (auto& family : aFDB.families()) for (auto& style : aFDB.styles(family)) { diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx index 40c737446c65..6ea2610e03f7 100644 --- a/vcl/qt5/Qt5Instance.cxx +++ b/vcl/qt5/Qt5Instance.cxx @@ -283,7 +283,7 @@ VCLPLUG_QT5_PUBLIC SalInstance* create_SalInstance() QApplication::setQuitOnLastWindowClosed(false); - const bool bUseCairo = (nullptr != getenv("SAL_VCL_QT5_USE_CAIRO")); + static const bool bUseCairo = (nullptr != getenv("SAL_VCL_QT5_USE_CAIRO")); Qt5Instance* pInstance = new Qt5Instance(new SalYieldMutex(), bUseCairo); // initialize SalData commit 670117dd9659910fe2cbde92356b12ef1ceb8399 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:15:50 2018 +0200 Qt5 multiple small fixes * just assert palettes, which are larger then the bitmap support; smaller then maximum palettes are ok * 1bit images are encoded by the most significant bit (N1BitMsbPal) => adapt the alpha mask decoding * drawLine update height and width need an additional pixel * drawn objects can be filled *and* have an outline * show cairo usage in about dialog Change-Id: I301708386feb3cc1c86b27f47f0e76594a1e7357 diff --git a/vcl/qt5/Qt5Bitmap.cxx b/vcl/qt5/Qt5Bitmap.cxx index 824bfc28b89a..adc46651fe41 100644 --- a/vcl/qt5/Qt5Bitmap.cxx +++ b/vcl/qt5/Qt5Bitmap.cxx @@ -38,11 +38,11 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale && "Unsupported BitCount!"); if (nBitCount == 1) - assert(2 == rPal.GetEntryCount()); + assert(2 >= rPal.GetEntryCount()); if (nBitCount == 4) - assert(16 == rPal.GetEntryCount()); + assert(16 >= rPal.GetEntryCount()); if (nBitCount == 8) - assert(256 == rPal.GetEntryCount()); + assert(256 >= rPal.GetEntryCount()); if (nBitCount == 4) { @@ -230,7 +230,7 @@ BitmapBuffer* Qt5Bitmap::AcquireBuffer(BitmapAccessMode /*nMode*/) switch (pBuffer->mnBitCount) { case 1: - pBuffer->mnFormat = ScanlineFormat::N1BitLsbPal | ScanlineFormat::TopDown; + pBuffer->mnFormat = ScanlineFormat::N1BitMsbPal | ScanlineFormat::TopDown; pBuffer->maPalette = m_aPalette; break; case 4: diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index 146849007035..a9f9175e6d48 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -196,7 +196,7 @@ void Qt5Graphics::drawLine(long nX1, long nY1, long nX2, long nY2) nY1 = nY2; nY2 = tmp; } - aPainter.update(nX1, nY1, nX2 - nX1, nY2 - nY1); + aPainter.update(nX1, nY1, nX2 - nX1 + 1, nY2 - nY1 + 1); } void Qt5Graphics::drawRect(long nX, long nY, long nWidth, long nHeight) @@ -207,7 +207,7 @@ void Qt5Graphics::drawRect(long nX, long nY, long nWidth, long nHeight) Qt5Painter aPainter(*this, true); if (SALCOLOR_NONE != m_aFillColor) aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush()); - else + if (SALCOLOR_NONE != m_aLineColor) aPainter.drawRect(nX, nY, nWidth, nHeight); aPainter.update(nX, nY, nWidth, nHeight); } @@ -527,7 +527,7 @@ static bool getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlph { if (x && !(x % 8)) ++alpha_line; - if (0 == (*alpha_line & (1 << (x % 8)))) + if (0 != (*alpha_line & (1 << (7 - x % 8)))) image_line[3] = 0; } } @@ -584,7 +584,7 @@ bool Qt5Graphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, Qt5Painter aPainter(*this, true, nTransparency); if (SALCOLOR_NONE != m_aFillColor) aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush()); - else + if (SALCOLOR_NONE != m_aLineColor) aPainter.drawRect(nX, nY, nWidth, nHeight); aPainter.update(nX, nY, nWidth, nHeight); return true; diff --git a/vcl/qt5/Qt5Instance.cxx b/vcl/qt5/Qt5Instance.cxx index ef618e18fa7f..40c737446c65 100644 --- a/vcl/qt5/Qt5Instance.cxx +++ b/vcl/qt5/Qt5Instance.cxx @@ -50,7 +50,10 @@ Qt5Instance::Qt5Instance(SalYieldMutex* pMutex, bool bUseCairo) { ImplSVData* pSVData = ImplGetSVData(); delete pSVData->maAppData.mpToolkitName; - pSVData->maAppData.mpToolkitName = new OUString("qt5"); + if (bUseCairo) + pSVData->maAppData.mpToolkitName = new OUString("qt5+cairo"); + else + pSVData->maAppData.mpToolkitName = new OUString("qt5"); m_postUserEventId = QEvent::registerEventType(); commit bd39726fe67cad9eb133daf4a8ab8c2b19dddfe1 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:10:27 2018 +0200 Qt5 implement invert for blinking cursor The different modes are quite probably not correctly implemented, as multiple backends disagree here. Change-Id: I08fc3096487ca95f4905ae9f0e4b5d3897fca483 diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index 08c620c11796..146849007035 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -444,9 +444,30 @@ std::shared_ptr<SalBitmap> Qt5Graphics::getBitmap(long nX, long nY, long nWidth, Color Qt5Graphics::getPixel(long nX, long nY) { return m_pQImage->pixel(nX, nY); } -void Qt5Graphics::invert(long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, - SalInvert /*nFlags*/) +void Qt5Graphics::invert(long nX, long nY, long nWidth, long nHeight, SalInvert nFlags) { + Qt5Painter aPainter(*this); + if (SalInvert::N50 & nFlags) + { + aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination); + aPainter.setBrush(Qt::DiagCrossPattern); + aPainter.fillRect(nX, nY, nWidth, nHeight, aPainter.brush()); + } + else + { + if (SalInvert::TrackFrame & nFlags) + { + aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination); + aPainter.setPen(Qt::DashLine); + aPainter.drawRect(nX, nY, nWidth, nHeight); + } + else + { + aPainter.setCompositionMode(QPainter::RasterOp_SourceXorDestination); + aPainter.fillRect(nX, nY, nWidth, nHeight, Qt::white); + } + } + aPainter.update(nX, nY, nWidth, nHeight); } void Qt5Graphics::invert(sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/, SalInvert /*nFlags*/) commit 30bf6b73178a6cf793cddb9c646560808f5faba7 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:06:54 2018 +0200 Qt5 implement scaled image draws If the source and target rects don't match, LO expect the image to be scaled. Change-Id: I337acfa56600eba92c10aed7a70749ad08c03e90 diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx index 0e9de46818a6..b1ba6ce85d98 100644 --- a/vcl/inc/qt5/Qt5Graphics.hxx +++ b/vcl/inc/qt5/Qt5Graphics.hxx @@ -53,6 +53,8 @@ class Qt5Graphics : public SalGraphics Qt5Graphics(Qt5Frame* pFrame, QImage* pQImage); + void drawScaledImage(const SalTwoRect& rPosAry, const QImage& rImage); + public: Qt5Graphics(Qt5Frame* pFrame) : Qt5Graphics(pFrame, nullptr) diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index 971b85f705fe..08c620c11796 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -356,6 +356,15 @@ bool Qt5Graphics::drawPolyLine(const basegfx::B2DPolygon& rPolyLine, double fTra bool Qt5Graphics::drawGradient(const tools::PolyPolygon&, const Gradient&) { return false; } +void Qt5Graphics::drawScaledImage(const SalTwoRect& rPosAry, const QImage& rImage) +{ + Qt5Painter aPainter(*this); + QRect aSrcRect(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); + QRect aDestRect(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight); + aPainter.drawImage(aDestRect, rImage, aSrcRect); + aPainter.update(aDestRect); +} + void Qt5Graphics::copyArea(long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, bool /*bWindowInvalidate*/) { @@ -372,25 +381,21 @@ void Qt5Graphics::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics) || rPosAry.mnDestHeight <= 0) return; - assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth); - assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight); - - QImage aImage, *pImage = &aImage; + QImage aImage, *pImage; + SalTwoRect aPosAry = rPosAry; if (!pSrcGraphics || this == pSrcGraphics) { - if (rPosAry.mnDestX == rPosAry.mnSrcX && rPosAry.mnDestY == rPosAry.mnSrcY) - return; + pImage = static_cast<Qt5Graphics*>(this)->m_pQImage; aImage = pImage->copy(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); + pImage = &aImage; + aPosAry.mnSrcX = 0; + aPosAry.mnSrcY = 0; } else pImage = static_cast<Qt5Graphics*>(pSrcGraphics)->m_pQImage; - 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); + drawScaledImage(aPosAry, *pImage); } void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) @@ -399,10 +404,6 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBit || rPosAry.mnDestHeight <= 0) return; - assert(rPosAry.mnSrcWidth == rPosAry.mnDestWidth); - assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight); - - Qt5Painter aPainter(*this); Qt5Bitmap aRGBABitmap; if (rSalBitmap.GetBitCount() == 4) aRGBABitmap.Create(rSalBitmap, 32); @@ -411,10 +412,7 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBit : aRGBABitmap.GetQImage(); assert(pImage); - 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); + drawScaledImage(rPosAry, *pImage); } void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& /*rSalBitmap*/, @@ -523,12 +521,7 @@ bool Qt5Graphics::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rS QImage aImage; if (!getAlphaImage(rSourceBitmap, rAlphaBitmap, aImage)) return false; - - Qt5Painter aPainter(*this); - aPainter.drawImage( - QPoint(rPosAry.mnDestX, rPosAry.mnDestY), aImage, - QRect(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight)); - aPainter.update(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight); + drawScaledImage(rPosAry, aImage); return true; } commit ef46981023becba0f34a235a3571028dd0ea8838 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 17:45:14 2018 +0200 Qt5 implement 4bit => 32bit bitmap conversion Some of the PNG icons are 4bit palette based PNG images. This implements the conversation function for the most common 4bit case, so we don't rely on some generic handling. All other non-4bit conversions can be handled by Qt. Change-Id: I4ddd744fb7166fc3a6992b6be6c250c2adb99ca5 diff --git a/vcl/inc/qt5/Qt5Bitmap.hxx b/vcl/inc/qt5/Qt5Bitmap.hxx index 6ecdebed5ca1..c89038a28fb7 100644 --- a/vcl/inc/qt5/Qt5Bitmap.hxx +++ b/vcl/inc/qt5/Qt5Bitmap.hxx @@ -31,7 +31,7 @@ class VCL_DLLPUBLIC Qt5Bitmap : public SalBitmap BitmapPalette m_aPalette; // for 4bit support - std::unique_ptr<sal_uInt8> m_pBuffer; + std::unique_ptr<sal_uInt8[]> m_pBuffer; Size m_aSize; sal_uInt32 m_nScanline; diff --git a/vcl/qt5/Qt5Bitmap.cxx b/vcl/qt5/Qt5Bitmap.cxx index ff44143a16f2..824bfc28b89a 100644 --- a/vcl/qt5/Qt5Bitmap.cxx +++ b/vcl/qt5/Qt5Bitmap.cxx @@ -48,8 +48,17 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale { m_pImage.reset(); m_aSize = rSize; - m_nScanline = rSize.Width() / 2 + (rSize.Width() % 2) ? 0 : 1; - m_pBuffer.reset(new sal_uInt8[m_nScanline * rSize.Height()]); + bool bFail = o3tl::checked_multiply<sal_uInt32>(rSize.Width(), nBitCount, m_nScanline); + if (bFail) + { + SAL_WARN("vcl.gdi", "checked multiply failed"); + return false; + } + m_nScanline = AlignedWidth4Bytes(m_nScanline); + sal_uInt8* pBuffer = nullptr; + if (0 != m_nScanline && 0 != rSize.Height()) + pBuffer = new sal_uInt8[m_nScanline * rSize.Height()]; + m_pBuffer.reset(pBuffer); } else { @@ -59,7 +68,7 @@ bool Qt5Bitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPale m_aPalette = rPal; auto count = rPal.GetEntryCount(); - if (nBitCount != 4 && count) + if (nBitCount != 4 && count && m_pImage.get()) { QVector<QRgb> aColorTable(count); for (unsigned i = 0; i < count; ++i) @@ -81,8 +90,14 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp) { m_aSize = pBitmap->m_aSize; m_nScanline = pBitmap->m_nScanline; - m_pBuffer.reset(new sal_uInt8[m_nScanline * m_aSize.Height()]); - memcpy(m_pBuffer.get(), pBitmap->m_pBuffer.get(), m_nScanline); + sal_uInt8* pBuffer = nullptr; + if (0 != m_nScanline && 0 != m_aSize.Height()) + { + sal_uInt32 nSize = m_nScanline * m_aSize.Height(); + pBuffer = new sal_uInt8[nSize]; + memcpy(pBuffer, pBitmap->m_pBuffer.get(), nSize); + } + m_pBuffer.reset(pBuffer); m_pImage.reset(); } m_aPalette = pBitmap->m_aPalette; @@ -107,9 +122,52 @@ bool Qt5Bitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) const Qt5Bitmap* pBitmap = static_cast<const Qt5Bitmap*>(&rSalBmp); if (pBitmap->m_pBuffer.get()) - return false; + { + if (nNewBitCount != 32) + return false; + + // convert 4bit indexed palette to 32bit ARGB + m_pImage.reset(new QImage(pBitmap->m_aSize.Width(), pBitmap->m_aSize.Height(), + getBitFormat(nNewBitCount))); + m_pImage->fill(0); + + // prepare a whole palette + const BitmapPalette& rPal = pBitmap->m_aPalette; + QVector<QRgb> colorTable(16); + int i = 0, maxEntry = pBitmap->m_aPalette.GetEntryCount(); + assert(maxEntry <= 16 && maxEntry >= 0); + for (; i < maxEntry; ++i) + colorTable[i] = qRgb(rPal[i].GetRed(), rPal[i].GetGreen(), rPal[i].GetBlue()); + for (; i < 16; ++i) + colorTable[i] = qRgb(0, 0, 0); - m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount)))); + sal_uInt32* image_data = reinterpret_cast<sal_uInt32*>(m_pImage->bits()); + sal_uInt8* buffer_data_pos = pBitmap->m_pBuffer.get(); + sal_uInt32 nWidth = pBitmap->m_aSize.Height() / 2; + bool isOdd(0 != pBitmap->m_aSize.Height() % 2); + + for (sal_uInt32 h = 0; h < pBitmap->m_aSize.Height(); ++h) + { + sal_uInt8* buffer_data = buffer_data_pos; + buffer_data_pos += pBitmap->m_nScanline; + for (sal_uInt32 w = 0; w < nWidth; ++w) + { + *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4)); + ++image_data; + *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data & 0xF)); + ++image_data; + ++buffer_data; + } + if (isOdd) + { + *image_data = reinterpret_cast<sal_uInt32>(colorTable.at(*buffer_data >> 4)); + ++image_data; + } + } + } + else + m_pImage.reset(new QImage(pBitmap->m_pImage->convertToFormat(getBitFormat(nNewBitCount)))); + m_pBuffer.reset(); return true; } diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx index b58f18e4b59b..971b85f705fe 100644 --- a/vcl/qt5/Qt5Graphics_GDI.cxx +++ b/vcl/qt5/Qt5Graphics_GDI.cxx @@ -403,8 +403,12 @@ void Qt5Graphics::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBit assert(rPosAry.mnSrcHeight == rPosAry.mnDestHeight); Qt5Painter aPainter(*this); - - const QImage* pImage = static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage(); + Qt5Bitmap aRGBABitmap; + if (rSalBitmap.GetBitCount() == 4) + aRGBABitmap.Create(rSalBitmap, 32); + const QImage* pImage = (rSalBitmap.GetBitCount() != 4) + ? static_cast<const Qt5Bitmap*>(&rSalBitmap)->GetQImage() + : aRGBABitmap.GetQImage(); assert(pImage); aPainter.drawImage( @@ -475,7 +479,12 @@ static bool getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlph return false; } - const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage(); + Qt5Bitmap aRGBABitmap; + if (rSourceBitmap.GetBitCount() == 4) + aRGBABitmap.Create(rSourceBitmap, 32); + const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4) + ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage() + : aRGBABitmap.GetQImage(); const QImage* pAlpha = static_cast<const Qt5Bitmap*>(&rAlphaBitmap)->GetQImage(); rAlphaImage = pBitmap->convertToFormat(Qt5_DefaultFormat32); @@ -532,7 +541,12 @@ bool Qt5Graphics::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const ba return false; else { - const QImage* pBitmap = static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage(); + Qt5Bitmap aRGBABitmap; + if (rSourceBitmap.GetBitCount() == 4) + aRGBABitmap.Create(rSourceBitmap, 32); + const QImage* pBitmap = (rSourceBitmap.GetBitCount() != 4) + ? static_cast<const Qt5Bitmap*>(&rSourceBitmap)->GetQImage() + : aRGBABitmap.GetQImage(); aImage = pBitmap->convertToFormat(Qt5_DefaultFormat32); } commit ebd1d973eac7ef6f330634a2d2a8ca1bf3c6720e Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:38:07 2018 +0200 Qt5 flesh out font handling Fills some more FontAttributes based on the QFont. Also implements initial font rotation support. Something is still strage with the vertical font in Writers vertical ruler. Text looks correct in vertical text boxes FWIW. The toRectangle bug is embarrassing; I was wondering for quite some time, which glyphs had strange size rects :-) While at it, move the Qt5Font header to vcl/inc/qt5. Change-Id: I67fa400486981035be6f98c5ab56e82d69c42065 diff --git a/vcl/qt5/Qt5Font.hxx b/vcl/inc/qt5/Qt5Font.hxx similarity index 100% rename from vcl/qt5/Qt5Font.hxx rename to vcl/inc/qt5/Qt5Font.hxx diff --git a/vcl/inc/qt5/Qt5FontFace.hxx b/vcl/inc/qt5/Qt5FontFace.hxx index 3c94f46777e1..c653b4be6f6e 100644 --- a/vcl/inc/qt5/Qt5FontFace.hxx +++ b/vcl/inc/qt5/Qt5FontFace.hxx @@ -37,6 +37,7 @@ public: virtual ~Qt5FontFace() override; static Qt5FontFace* fromQFont(const QFont& rFont); + static void fillAttributesFromQFont(const QFont& rFont, FontAttributes& rFA); sal_IntPtr GetFontId() const override; diff --git a/vcl/inc/qt5/Qt5Tools.hxx b/vcl/inc/qt5/Qt5Tools.hxx index f075468ca3d3..c919b401e191 100644 --- a/vcl/inc/qt5/Qt5Tools.hxx +++ b/vcl/inc/qt5/Qt5Tools.hxx @@ -49,7 +49,7 @@ inline QRect toQRect(const tools::Rectangle& rRect) inline tools::Rectangle toRectangle(const QRect& rRect) { - return tools::Rectangle(rRect.left(), rRect.top(), rRect.width(), rRect.height()); + return tools::Rectangle(rRect.left(), rRect.top(), rRect.right(), rRect.bottom()); } inline QSize toQSize(const Size& rSize) { return QSize(rSize.Width(), rSize.Height()); } diff --git a/vcl/qt5/Qt5Font.cxx b/vcl/qt5/Qt5Font.cxx index 0164c3b13cd4..dc393dd1cae8 100644 --- a/vcl/qt5/Qt5Font.cxx +++ b/vcl/qt5/Qt5Font.cxx @@ -17,14 +17,65 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include "Qt5Font.hxx" +#include <Qt5Font.hxx> +#include <Qt5Tools.hxx> #include <QtGui/QFont> #include <QtGui/QRawFont> +static QFont::Weight GetQFontWeight(FontWeight eWeight) +{ + switch (eWeight) + { + case WEIGHT_THIN: + return QFont::Thin; + case WEIGHT_ULTRALIGHT: + return QFont::ExtraLight; + case WEIGHT_LIGHT: + return QFont::Light; + case FontWeight_FORCE_EQUAL_SIZE: + assert(false && "FontWeight_FORCE_EQUAL_SIZE not implementable for QFont"); + case WEIGHT_SEMILIGHT: + case WEIGHT_DONTKNOW: + case WEIGHT_NORMAL: + return QFont::Normal; + case WEIGHT_MEDIUM: + return QFont::Medium; + case WEIGHT_SEMIBOLD: + return QFont::DemiBold; + case WEIGHT_BOLD: + return QFont::Bold; + case WEIGHT_ULTRABOLD: + return QFont::ExtraBold; + case WEIGHT_BLACK: + return QFont::Black; + } + + // so we would get enum not handled warning + return QFont::Normal; +} + Qt5Font::Qt5Font(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP) : LogicalFontInstance(rPFF, rFSP) { + setFamily(toQString(rPFF.GetFamilyName())); + setWeight(GetQFontWeight(rPFF.GetWeight())); + setPixelSize(rFSP.mnHeight); + switch (rFSP.GetItalic()) + { + case ITALIC_DONTKNOW: + case FontItalic_FORCE_EQUAL_SIZE: + break; + case ITALIC_NONE: + setStyle(Style::StyleNormal); + break; + case ITALIC_OBLIQUE: + setStyle(Style::StyleOblique); + break; + case ITALIC_NORMAL: + setStyle(Style::StyleItalic); + break; + } } Qt5Font::~Qt5Font() {} diff --git a/vcl/qt5/Qt5FontFace.cxx b/vcl/qt5/Qt5FontFace.cxx index 043a9b6e798b..10f79aa559bd 100644 --- a/vcl/qt5/Qt5FontFace.cxx +++ b/vcl/qt5/Qt5FontFace.cxx @@ -18,7 +18,7 @@ */ #include <Qt5FontFace.hxx> -#include "Qt5Font.hxx" +#include <Qt5Font.hxx> #include <Qt5Tools.hxx> #include <sft.hxx> @@ -41,13 +41,67 @@ Qt5FontFace::Qt5FontFace(const Qt5FontFace& rSrc) m_xCharMap = rSrc.m_xCharMap; } +void Qt5FontFace::fillAttributesFromQFont(const QFont& rFont, FontAttributes& rFA) +{ + QFontInfo aFontInfo(rFont); + + rFA.SetFamilyName(toOUString(aFontInfo.family())); + if (IsStarSymbol(toOUString(aFontInfo.family()))) + rFA.SetSymbolFlag(true); + rFA.SetStyleName(toOUString(aFontInfo.styleName())); + rFA.SetPitch(aFontInfo.fixedPitch() ? PITCH_FIXED : PITCH_VARIABLE); + + FontWeight eWeight = WEIGHT_DONTKNOW; + switch (aFontInfo.weight()) + { + case QFont::Thin: + eWeight = WEIGHT_THIN; + break; + case QFont::ExtraLight: + eWeight = WEIGHT_ULTRALIGHT; + break; + case QFont::Light: + eWeight = WEIGHT_LIGHT; + break; + case QFont::Normal: + eWeight = WEIGHT_NORMAL; + break; + case QFont::Medium: + eWeight = WEIGHT_MEDIUM; + break; + case QFont::DemiBold: + eWeight = WEIGHT_SEMIBOLD; + break; + case QFont::Bold: + eWeight = WEIGHT_BOLD; + break; + case QFont::ExtraBold: + eWeight = WEIGHT_ULTRABOLD; + break; + case QFont::Black: + eWeight = WEIGHT_BLACK; + break; + } + rFA.SetWeight(eWeight); + + switch (aFontInfo.style()) + { + case QFont::StyleNormal: + rFA.SetItalic(ITALIC_NONE); + break; + case QFont::StyleItalic: + rFA.SetItalic(ITALIC_NORMAL); + break; + case QFont::StyleOblique: + rFA.SetItalic(ITALIC_OBLIQUE); + break; + } +} + Qt5FontFace* Qt5FontFace::fromQFont(const QFont& rFont) { FontAttributes aFA; - aFA.SetFamilyName(toOUString(rFont.family())); - aFA.SetStyleName(toOUString(rFont.styleName())); - aFA.SetItalic(rFont.italic() ? ITALIC_NORMAL : ITALIC_NONE); - + fillAttributesFromQFont(rFont, aFA); return new Qt5FontFace(aFA, rFont.toString()); } diff --git a/vcl/qt5/Qt5Graphics_Text.cxx b/vcl/qt5/Qt5Graphics_Text.cxx index cb7bef853ba8..282432214589 100644 --- a/vcl/qt5/Qt5Graphics_Text.cxx +++ b/vcl/qt5/Qt5Graphics_Text.cxx @@ -19,7 +19,7 @@ #include <Qt5Graphics.hxx> #include <Qt5FontFace.hxx> -#include "Qt5Font.hxx" +#include <Qt5Font.hxx> #include <Qt5Painter.hxx> #include <vcl/fontcharmap.hxx> @@ -56,6 +56,7 @@ void Qt5Graphics::SetFont(const FontSelectPattern* pReqFont, int nFallbackLevel) void Qt5Graphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel) { QRawFont aRawFont(QRawFont::fromFont(*m_pTextStyle[nFallbackLevel])); + Qt5FontFace::fillAttributesFromQFont(*m_pTextStyle[nFallbackLevel], *rFMD); QByteArray aHheaTable = aRawFont.fontTable("hhea"); std::vector<uint8_t> rHhea(aHheaTable.data(), aHheaTable.data() + aHheaTable.size()); @@ -65,6 +66,7 @@ void Qt5Graphics::GetFontMetric(ImplFontMetricDataRef& rFMD, int nFallbackLevel) rFMD->ImplCalcLineSpacing(rHhea, rOS2, aRawFont.unitsPerEm()); + rFMD->SetSlant(0); rFMD->SetWidth(aRawFont.averageCharWidth()); rFMD->SetMinKashida(m_pTextStyle[nFallbackLevel]->GetKashidaWidth()); @@ -146,10 +148,21 @@ bool Qt5Graphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& r bool Qt5Graphics::GetGlyphOutline(const GlyphItem&, basegfx::B2DPolyPolygon&) { return false; } +class Qt5CommonSalLayout : public GenericSalLayout +{ +public: + Qt5CommonSalLayout(LogicalFontInstance& rLFI) + : GenericSalLayout(rLFI) + { + } + + void SetOrientation(int nOrientation) { mnOrientation = nOrientation; } +}; + std::unique_ptr<SalLayout> Qt5Graphics::GetTextLayout(ImplLayoutArgs&, int nFallbackLevel) { if (m_pTextStyle[nFallbackLevel]) - return std::unique_ptr<SalLayout>(new GenericSalLayout(*m_pTextStyle[nFallbackLevel])); + return std::unique_ptr<SalLayout>(new Qt5CommonSalLayout(*m_pTextStyle[nFallbackLevel])); return std::unique_ptr<SalLayout>(); } @@ -162,6 +175,14 @@ void Qt5Graphics::DrawTextLayout(const GenericSalLayout& rLayout) QVector<quint32> glyphIndexes; QVector<QPointF> positions; + // prevent glyph rotation inside the SalLayout + // probably better to add a parameter to GetNextGlyphs? + Qt5CommonSalLayout* pQt5Layout + = static_cast<Qt5CommonSalLayout*>(const_cast<GenericSalLayout*>(&rLayout)); + int nOrientation = rLayout.GetOrientation(); + if (nOrientation) + pQt5Layout->SetOrientation(0); + Point aPos; const GlyphItem* pGlyph; int nStart = 0; @@ -171,6 +192,9 @@ void Qt5Graphics::DrawTextLayout(const GenericSalLayout& rLayout) positions.push_back(QPointF(aPos.X(), aPos.Y())); } + if (nOrientation) + pQt5Layout->SetOrientation(nOrientation); + QGlyphRun aGlyphRun; aGlyphRun.setPositions(positions); aGlyphRun.setGlyphIndexes(glyphIndexes); @@ -179,6 +203,21 @@ void Qt5Graphics::DrawTextLayout(const GenericSalLayout& rLayout) Qt5Painter aPainter(*this); QColor aColor = toQColor(m_aTextColor); aPainter.setPen(aColor); + + if (nOrientation) + { + // make text position the center of the rotation + // then rotate and move back + QRect window = aPainter.window(); + window.moveTo(-positions[0].x(), -positions[0].y()); + aPainter.setWindow(window); + + QTransform p; + p.rotate(-static_cast<qreal>(nOrientation) / 10.0); + p.translate(-positions[0].x(), -positions[0].y()); + aPainter.setTransform(p); + } + aPainter.drawGlyphRun(QPointF(), aGlyphRun); } commit d4125bd04bd58972594510bf6ab5614693e25833 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:30:34 2018 +0200 Add ostream::operator<< for SalTwoRect Change-Id: I4466ebb154acd8046927db6b945b04c85095b87e diff --git a/include/vcl/salgtype.hxx b/include/vcl/salgtype.hxx index 0e37300f3dbd..d920ede00dac 100644 --- a/include/vcl/salgtype.hxx +++ b/include/vcl/salgtype.hxx @@ -23,6 +23,8 @@ #include <sal/types.h> #include <o3tl/typed_flags_set.hxx> #include <tools/color.hxx> +#include <tools/gen.hxx> +#include <ostream> enum class DeviceFormat { NONE = -1, @@ -63,6 +65,19 @@ struct SalTwoRect } }; +template <typename charT, typename traits> +inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream, + const SalTwoRect& rPosAry) +{ + tools::Rectangle aSrcRect(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcX + rPosAry.mnSrcWidth, + rPosAry.mnSrcY + rPosAry.mnSrcHeight); + tools::Rectangle aDestRect(rPosAry.mnDestX, rPosAry.mnDestY, + rPosAry.mnDestX + rPosAry.mnDestWidth, + rPosAry.mnDestY + rPosAry.mnDestHeight); + stream << aSrcRect << " => " << aDestRect; + return stream; +} + enum class SalROPColor { N0, N1, Invert }; commit e2320955b32595df09c9c4412ccec56a0b273df7 Author: Jan-Marek Glogowski <[email protected]> Date: Thu Jul 5 18:37:35 2018 +0200 Some cleanup and comments Change-Id: Ic1dda9b0e5d7896703b65d0d43be340196bcb871 diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx index 6b97f30409e7..ae2fb1086d7f 100644 --- a/basctl/source/basicide/baside2b.cxx +++ b/basctl/source/basicide/baside2b.cxx @@ -963,6 +963,7 @@ void EditorWindow::CreateEditEngine() ImplSetFont(); aSyntaxIdle.SetInvokeHandler( LINK( this, EditorWindow, SyntaxTimerHdl ) ); + aSyntaxIdle.SetDebugName( "basctl EditorWindow aSyntaxIdle" ); bool bWasDoSyntaxHighlight = bDoSyntaxHighlight; bDoSyntaxHighlight = false; // too slow for large texts... diff --git a/sfx2/source/appl/appdispatchprovider.cxx b/sfx2/source/appl/appdispatchprovider.cxx index a13cb5312bf6..d13a9009ee0e 100644 --- a/sfx2/source/appl/appdispatchprovider.cxx +++ b/sfx2/source/appl/appdispatchprovider.cxx @@ -129,7 +129,10 @@ Reference < XDispatch > SAL_CALL SfxAppDispatchProvider::queryDispatch( bool bMasterCommand( false ); Reference < XDispatch > xDisp; const SfxSlot* pSlot = nullptr; - SfxDispatcher* pAppDisp = SfxGetpApp()->GetAppDispatcher_Impl(); + SfxApplication* pApp = SfxGetpApp(); + if ( !pApp ) + return xDisp; + SfxDispatcher* pAppDisp = pApp->GetAppDispatcher_Impl(); if ( aURL.Protocol == "slot:" || aURL.Protocol == "commandId:" ) { nId = static_cast<sal_uInt16>(aURL.Path.toInt32()); diff --git a/vcl/inc/fontselect.hxx b/vcl/inc/fontselect.hxx index efb88ad74ae1..fd453a0d5f54 100644 --- a/vcl/inc/fontselect.hxx +++ b/vcl/inc/fontselect.hxx @@ -59,7 +59,7 @@ public: int mnWidth; // width of font in pixel units int mnHeight; // height of font in pixel units float mfExactHeight; // requested height (in pixels with subpixel details) - int mnOrientation; // text orientation in 3600 system + int mnOrientation; // text orientation in 1/10 degree (0-3600) LanguageType meLanguage; // text language bool mbVertical; // vertical mode of requested font bool mbNonAntialiased; // true if antialiasing is disabled diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx index a58d9b6931f2..333bc8415c08 100644 --- a/vcl/source/font/fontcache.cxx +++ b/vcl/source/font/fontcache.cxx @@ -48,7 +48,7 @@ bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const Fo return false; // check font face attributes - if( (rA.GetWeight() != rB.GetWeight()) + if( (rA.GetWeight() != rB.GetWeight()) || (rA.GetItalic() != rB.GetItalic()) // || (rA.meFamily != rB.meFamily) // TODO: remove this mostly obsolete member || (rA.GetPitch() != rB.GetPitch()) ) _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
