diff options
-rw-r--r-- | vcl/inc/qt5/Qt5Bitmap.hxx | 2 | ||||
-rw-r--r-- | vcl/qt5/Qt5Bitmap.cxx | 72 | ||||
-rw-r--r-- | vcl/qt5/Qt5Graphics_GDI.cxx | 22 |
3 files changed, 84 insertions, 12 deletions
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); } |