Revert "ScanlineDirection is unnecessary"
This reverts commita525438eb6
Author: Noel Grandin <noelgrandin@collabora.co.uk> Date: Wed Jan 22 09:50:43 2025 +0200 fix GDI and Quartz backends and commit828a0dcdf6
Author: Noel Grandin <noel.grandin@collabora.co.uk> Date: Thu Jan 16 08:23:19 2025 +0200 ScanlineDirection is unnecessary because macOS uses bottom-up coordinate system, and I could not find a way to make the bitmaps stored top-down. Change-Id: Idc05b7473eca5fae0e33d634117de810146da3b5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180603 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -4066,6 +4066,8 @@ include/vcl/salnativewidgets.hxx:198
|
||||
enum ControlPart BackgroundDialog
|
||||
include/vcl/salnativewidgets.hxx:237
|
||||
enum ButtonValue DontKnow
|
||||
include/vcl/Scanline.hxx:48
|
||||
enum ScanlineDirection BottomUp
|
||||
include/vcl/sysdata.hxx:54
|
||||
enum SystemEnvData::Toolkit Qt
|
||||
include/vcl/syswin.hxx:50
|
||||
|
@@ -40,6 +40,7 @@ struct VCL_DLLPUBLIC BitmapBuffer
|
||||
BitmapPalette maPalette;
|
||||
sal_uInt8* mpBits;
|
||||
ScanlineFormat meFormat = ScanlineFormat::NONE;
|
||||
ScanlineDirection meDirection = ScanlineDirection::BottomUp;
|
||||
ColorMask maColorMask;
|
||||
sal_uInt16 mnBitCount;
|
||||
};
|
||||
|
@@ -48,6 +48,15 @@ public:
|
||||
|
||||
tools::Long Height() const { return mpBuffer ? mpBuffer->mnHeight : 0L; }
|
||||
|
||||
bool IsTopDown() const
|
||||
{
|
||||
assert(mpBuffer && "Access is not valid!");
|
||||
|
||||
return mpBuffer && mpBuffer->meDirection == ScanlineDirection::TopDown;
|
||||
}
|
||||
|
||||
bool IsBottomUp() const { return !IsTopDown(); }
|
||||
|
||||
ScanlineFormat GetScanlineFormat() const
|
||||
{
|
||||
assert(mpBuffer && "Access is not valid!");
|
||||
|
@@ -49,7 +49,11 @@ public:
|
||||
assert(mpBuffer && "Access is not valid!");
|
||||
assert(nY < mpBuffer->mnHeight && "y-coordinate out of range!");
|
||||
|
||||
return mpBuffer->mpBits + (nY * mpBuffer->mnScanlineSize);
|
||||
if (mpBuffer->meDirection == ScanlineDirection::TopDown)
|
||||
{
|
||||
return mpBuffer->mpBits + (nY * mpBuffer->mnScanlineSize);
|
||||
}
|
||||
return mpBuffer->mpBits + ((mpBuffer->mnHeight - 1 - nY) * mpBuffer->mnScanlineSize);
|
||||
}
|
||||
|
||||
BitmapColor GetPixelFromData(const sal_uInt8* pData, tools::Long nX) const
|
||||
|
@@ -47,4 +47,10 @@ enum class ScanlineFormat : sal_uInt8
|
||||
N32BitTcMask,
|
||||
};
|
||||
|
||||
enum class ScanlineDirection : sal_uInt8
|
||||
{
|
||||
BottomUp,
|
||||
TopDown
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
@@ -40,7 +40,8 @@ BitmapHelper::BitmapHelper(const SalBitmap& rSourceBitmap, const bool bForceARGB
|
||||
const SalTwoRect aTwoRect
|
||||
= { 0, 0, pSrc->mnWidth, pSrc->mnHeight, 0, 0, pSrc->mnWidth, pSrc->mnHeight };
|
||||
std::optional<BitmapBuffer> pTmp
|
||||
= (pSrc->meFormat == SVP_24BIT_FORMAT)
|
||||
= (pSrc->meFormat == SVP_24BIT_FORMAT
|
||||
&& pSrc->meDirection == ScanlineDirection::TopDown)
|
||||
? FastConvert24BitRgbTo32BitCairo(pSrc)
|
||||
: StretchAndConvert(*pSrc, aTwoRect, SVP_CAIRO_FORMAT);
|
||||
aTmpBmp.Create(std::move(pTmp));
|
||||
|
@@ -1979,6 +1979,7 @@ std::optional<BitmapBuffer> FastConvert24BitRgbTo32BitCairo(const BitmapBuffer*
|
||||
const tools::Long nHeight = pSrc->mnHeight;
|
||||
std::optional<BitmapBuffer> pDst(std::in_place);
|
||||
pDst->meFormat = ScanlineFormat::N32BitTcArgb;
|
||||
pDst->meDirection = ScanlineDirection::TopDown;
|
||||
pDst->mnWidth = nWidth;
|
||||
pDst->mnHeight = nHeight;
|
||||
pDst->mnBitCount = 32;
|
||||
|
@@ -70,6 +70,7 @@ static std::optional<BitmapBuffer> ImplCreateDIB(
|
||||
if (ePixelFormat <= vcl::PixelFormat::N8_BPP)
|
||||
nColors = vcl::numberOfColors(ePixelFormat);
|
||||
|
||||
pDIB->meDirection = ScanlineDirection::TopDown;
|
||||
pDIB->mnWidth = rSize.Width();
|
||||
pDIB->mnHeight = rSize.Height();
|
||||
tools::Long nScanlineBase;
|
||||
|
@@ -120,6 +120,7 @@ BitmapBuffer* QtBitmap::AcquireBuffer(BitmapAccessMode /*nMode*/)
|
||||
pBuffer->mnBitCount = getFormatBits(m_pImage->format());
|
||||
pBuffer->mpBits = m_pImage->bits();
|
||||
pBuffer->mnScanlineSize = m_pImage->bytesPerLine();
|
||||
pBuffer->meDirection = ScanlineDirection::TopDown;
|
||||
|
||||
switch (pBuffer->mnBitCount)
|
||||
{
|
||||
|
@@ -312,6 +312,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode)
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
buffer->meDirection = ScanlineDirection::TopDown;
|
||||
// Refcount all read/write accesses, to catch problems with existing accesses while
|
||||
// a bitmap changes, and also to detect when we can free mBuffer if wanted.
|
||||
// Write mode implies also reading. It would be probably a good idea to count even
|
||||
@@ -1146,6 +1147,7 @@ void SkiaSalBitmap::PerformErase()
|
||||
if (!ImplFastEraseBitmap(*bitmapBuffer, fastColor))
|
||||
{
|
||||
FncSetPixel setPixel = BitmapReadAccess::SetPixelFunction(bitmapBuffer->meFormat);
|
||||
assert(bitmapBuffer->meDirection == ScanlineDirection::TopDown);
|
||||
// Set first scanline, copy to others.
|
||||
Scanline scanline = bitmapBuffer->mpBits;
|
||||
for (tools::Long x = 0; x < bitmapBuffer->mnWidth; ++x)
|
||||
|
@@ -268,7 +268,13 @@ static bool ImplCopyImage( BitmapBuffer& rDstBuffer, const BitmapBuffer& rSrcBuf
|
||||
const PIXBYTE* pRawSrc = rSrcBuffer.mpBits;
|
||||
PIXBYTE* pRawDst = rDstBuffer.mpBits;
|
||||
|
||||
if( nSrcLinestep == nDstLinestep )
|
||||
// source and destination don't match upside down
|
||||
if (rSrcBuffer.meDirection != rDstBuffer.meDirection)
|
||||
{
|
||||
pRawDst += (rSrcBuffer.mnHeight - 1) * nDstLinestep;
|
||||
nDstLinestep = -rDstBuffer.mnScanlineSize;
|
||||
}
|
||||
else if( nSrcLinestep == nDstLinestep )
|
||||
{
|
||||
memcpy( pRawDst, pRawSrc, rSrcBuffer.mnHeight * nDstLinestep );
|
||||
return true;
|
||||
@@ -302,6 +308,13 @@ static bool ImplConvertToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
|
||||
|
||||
TrueColorPixelPtr<DSTFMT> aDstLine; aDstLine.SetRawPtr( rDstBuffer.mpBits );
|
||||
|
||||
// source and destination don't match upside down
|
||||
if (rSrcBuffer.meDirection != rDstBuffer.meDirection)
|
||||
{
|
||||
aDstLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nDstLinestep );
|
||||
nDstLinestep = -nDstLinestep;
|
||||
}
|
||||
|
||||
for( int y = rSrcBuffer.mnHeight; --y >= 0; )
|
||||
{
|
||||
ImplConvertLine( aDstLine, rSrcLine, rSrcBuffer.mnWidth );
|
||||
@@ -366,6 +379,7 @@ bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
|
||||
return false;
|
||||
// vertical mirroring
|
||||
if( rTR.mnDestHeight < 0 )
|
||||
// TODO: rDst.meDirection != ScanlineDirection::TopDown;
|
||||
return false;
|
||||
|
||||
// offsetted conversion is not implemented yet
|
||||
@@ -449,7 +463,10 @@ bool ImplFastBitmapConversion( BitmapBuffer& rDst, const BitmapBuffer& rSrc,
|
||||
|
||||
static inline ConstScanline ImplGetScanline( const BitmapBuffer& rBuf, tools::Long nY )
|
||||
{
|
||||
return rBuf.mpBits + nY * rBuf.mnScanlineSize;
|
||||
if (rBuf.meDirection == ScanlineDirection::TopDown)
|
||||
return rBuf.mpBits + nY * rBuf.mnScanlineSize;
|
||||
else
|
||||
return rBuf.mpBits + (rBuf.mnHeight - 1 - nY) * rBuf.mnScanlineSize;
|
||||
}
|
||||
|
||||
static inline Scanline ImplGetScanline( BitmapBuffer& rBuf, tools::Long nY )
|
||||
@@ -567,6 +584,20 @@ static bool ImplBlendToBitmap( TrueColorPixelPtr<SRCFMT>& rSrcLine,
|
||||
if( rMskBuffer.mnHeight == 1 )
|
||||
nMskLinestep = 0;
|
||||
|
||||
// source and mask don't match: upside down
|
||||
if (rSrcBuffer.meDirection != rMskBuffer.meDirection)
|
||||
{
|
||||
aMskLine.AddByteOffset( (rSrcBuffer.mnHeight - 1) * nMskLinestep );
|
||||
nMskLinestep = -nMskLinestep;
|
||||
}
|
||||
|
||||
// source and destination don't match: upside down
|
||||
if (rSrcBuffer.meDirection != rDstBuffer.meDirection)
|
||||
{
|
||||
aDstLine.AddByteOffset( (rDstBuffer.mnHeight - 1) * nDstLinestep );
|
||||
nDstLinestep = -nDstLinestep;
|
||||
}
|
||||
|
||||
assert(rDstBuffer.mnHeight <= rSrcBuffer.mnHeight && "not sure about that?");
|
||||
for (int y = rDstBuffer.mnHeight; --y >= 0;)
|
||||
{
|
||||
@@ -669,6 +700,7 @@ bool ImplFastBitmapBlending( BitmapWriteAccess const & rDstWA,
|
||||
return false;
|
||||
// vertical mirroring
|
||||
if( rTR.mnDestHeight < 0 )
|
||||
// TODO: rDst.meDirection != ScanlineDirection::TopDown;
|
||||
return false;
|
||||
|
||||
// offsetted blending is not implemented yet
|
||||
|
@@ -499,7 +499,7 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
|
||||
{
|
||||
// we can't trust arbitrary-sourced index based formats to have correct indexes, so we exclude the pal formats
|
||||
// from raw read and force checking their colormap indexes
|
||||
bNative = bTopDown && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth );
|
||||
bNative = ( ( rAcc.IsBottomUp() != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1246,8 +1246,13 @@ bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess const & rAcc, sal_uLong
|
||||
|
||||
rImageSize = rOStm.Tell();
|
||||
|
||||
for( tools::Long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0; nY-- )
|
||||
rOStm.WriteBytes( rAcc.GetScanline(nY), nScanlineSize );
|
||||
if( rAcc.IsBottomUp() )
|
||||
rOStm.WriteBytes(rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize());
|
||||
else
|
||||
{
|
||||
for( tools::Long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0; nY-- )
|
||||
rOStm.WriteBytes( rAcc.GetScanline(nY), nScanlineSize );
|
||||
}
|
||||
}
|
||||
else if((RLE_4 == nCompression) || (RLE_8 == nCompression))
|
||||
{
|
||||
@@ -1266,60 +1271,88 @@ bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess const & rAcc, sal_uLong
|
||||
// (other cases are not written below)
|
||||
const auto ePixelFormat(convertToBPP(rAcc.GetBitCount()));
|
||||
const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * sal_Int32(ePixelFormat)));
|
||||
bool bNative(false);
|
||||
|
||||
switch(rAcc.GetScanlineFormat())
|
||||
{
|
||||
case ScanlineFormat::N1BitMsbPal:
|
||||
case ScanlineFormat::N8BitPal:
|
||||
case ScanlineFormat::N24BitTcBgr:
|
||||
{
|
||||
if(rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth))
|
||||
{
|
||||
bNative = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rImageSize = rOStm.Tell();
|
||||
|
||||
const tools::Long nWidth(rAcc.Width());
|
||||
const tools::Long nHeight(rAcc.Height());
|
||||
std::vector<sal_uInt8> aBuf(nAlignedWidth);
|
||||
switch(ePixelFormat)
|
||||
if(bNative)
|
||||
{
|
||||
case vcl::PixelFormat::N8_BPP:
|
||||
rOStm.WriteBytes(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height());
|
||||
}
|
||||
else
|
||||
{
|
||||
const tools::Long nWidth(rAcc.Width());
|
||||
const tools::Long nHeight(rAcc.Height());
|
||||
std::vector<sal_uInt8> aBuf(nAlignedWidth);
|
||||
switch(ePixelFormat)
|
||||
{
|
||||
for( tools::Long nY = nHeight - 1; nY >= 0; nY-- )
|
||||
case vcl::PixelFormat::N8_BPP:
|
||||
{
|
||||
sal_uInt8* pTmp = aBuf.data();
|
||||
Scanline pScanline = rAcc.GetScanline( nY );
|
||||
|
||||
for( tools::Long nX = 0; nX < nWidth; nX++ )
|
||||
*pTmp++ = rAcc.GetIndexFromData( pScanline, nX );
|
||||
|
||||
rOStm.WriteBytes(aBuf.data(), nAlignedWidth);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case vcl::PixelFormat::N24_BPP:
|
||||
{
|
||||
//valgrind, zero out the trailing unused alignment bytes
|
||||
size_t nUnusedBytes = nAlignedWidth - nWidth * 3;
|
||||
memset(aBuf.data() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes);
|
||||
}
|
||||
[[fallthrough]];
|
||||
// #i59239# fallback to 24 bit format, if bitcount is non-default
|
||||
default:
|
||||
{
|
||||
BitmapColor aPixelColor;
|
||||
|
||||
for( tools::Long nY = nHeight - 1; nY >= 0; nY-- )
|
||||
{
|
||||
sal_uInt8* pTmp = aBuf.data();
|
||||
|
||||
for( tools::Long nX = 0; nX < nWidth; nX++ )
|
||||
for( tools::Long nY = nHeight - 1; nY >= 0; nY-- )
|
||||
{
|
||||
// when alpha is used, this may be non-24bit main bitmap, so use GetColor
|
||||
// instead of GetPixel to ensure RGB value
|
||||
aPixelColor = rAcc.GetColor( nY, nX );
|
||||
sal_uInt8* pTmp = aBuf.data();
|
||||
Scanline pScanline = rAcc.GetScanline( nY );
|
||||
|
||||
*pTmp++ = aPixelColor.GetBlue();
|
||||
*pTmp++ = aPixelColor.GetGreen();
|
||||
*pTmp++ = aPixelColor.GetRed();
|
||||
for( tools::Long nX = 0; nX < nWidth; nX++ )
|
||||
*pTmp++ = rAcc.GetIndexFromData( pScanline, nX );
|
||||
|
||||
rOStm.WriteBytes(aBuf.data(), nAlignedWidth);
|
||||
}
|
||||
|
||||
rOStm.WriteBytes(aBuf.data(), nAlignedWidth);
|
||||
}
|
||||
break;
|
||||
|
||||
case vcl::PixelFormat::N24_BPP:
|
||||
{
|
||||
//valgrind, zero out the trailing unused alignment bytes
|
||||
size_t nUnusedBytes = nAlignedWidth - nWidth * 3;
|
||||
memset(aBuf.data() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes);
|
||||
}
|
||||
[[fallthrough]];
|
||||
// #i59239# fallback to 24 bit format, if bitcount is non-default
|
||||
default:
|
||||
{
|
||||
BitmapColor aPixelColor;
|
||||
|
||||
for( tools::Long nY = nHeight - 1; nY >= 0; nY-- )
|
||||
{
|
||||
sal_uInt8* pTmp = aBuf.data();
|
||||
|
||||
for( tools::Long nX = 0; nX < nWidth; nX++ )
|
||||
{
|
||||
// when alpha is used, this may be non-24bit main bitmap, so use GetColor
|
||||
// instead of GetPixel to ensure RGB value
|
||||
aPixelColor = rAcc.GetColor( nY, nX );
|
||||
|
||||
*pTmp++ = aPixelColor.GetBlue();
|
||||
*pTmp++ = aPixelColor.GetGreen();
|
||||
*pTmp++ = aPixelColor.GetRed();
|
||||
}
|
||||
|
||||
rOStm.WriteBytes(aBuf.data(), nAlignedWidth);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -62,11 +62,19 @@ void SalBitmap::updateChecksum() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pBuf->mnScanlineSize == lineBitsCount / 8 )
|
||||
nCrc = rtl_crc32(nCrc, pBuf->mpBits, pBuf->mnScanlineSize * pBuf->mnHeight);
|
||||
else // Do not include padding with undefined content in the checksum.
|
||||
for( tools::Long y = 0; y < pBuf->mnHeight; ++y )
|
||||
if (pBuf->meDirection == ScanlineDirection::TopDown)
|
||||
{
|
||||
if( pBuf->mnScanlineSize == lineBitsCount / 8 )
|
||||
nCrc = rtl_crc32(nCrc, pBuf->mpBits, pBuf->mnScanlineSize * pBuf->mnHeight);
|
||||
else // Do not include padding with undefined content in the checksum.
|
||||
for( tools::Long y = 0; y < pBuf->mnHeight; ++y )
|
||||
nCrc = scanlineChecksum(nCrc, pBuf->mpBits + y * pBuf->mnScanlineSize, lineBitsCount, extraBitsMask);
|
||||
}
|
||||
else // Compute checksum in the order of scanlines, to make it consistent between different bitmap implementations.
|
||||
{
|
||||
for( tools::Long y = pBuf->mnHeight - 1; y >= 0; --y )
|
||||
nCrc = scanlineChecksum(nCrc, pBuf->mpBits + y * pBuf->mnScanlineSize, lineBitsCount, extraBitsMask);
|
||||
}
|
||||
pThis->ReleaseBuffer(pBuf, BitmapAccessMode::Read);
|
||||
pThis->mnChecksum = nCrc;
|
||||
pThis->mbChecksumValid = true;
|
||||
|
@@ -215,7 +215,23 @@ static bool readWebp(SvStream& stream, Graphic& graphic)
|
||||
switch (pixelMode)
|
||||
{
|
||||
case PixelMode::DirectRead:
|
||||
{
|
||||
// Adjust for IsBottomUp() if necessary.
|
||||
if (access->IsBottomUp())
|
||||
{
|
||||
std::vector<char> tmp;
|
||||
const sal_uInt32 lineSize = access->GetScanlineSize();
|
||||
tmp.resize(lineSize);
|
||||
for (tools::Long y = 0; y < access->Height() / 2; ++y)
|
||||
{
|
||||
tools::Long otherY = access->Height() - 1 - y;
|
||||
memcpy(tmp.data(), access->GetScanline(y), lineSize);
|
||||
memcpy(access->GetScanline(y), access->GetScanline(otherY), lineSize);
|
||||
memcpy(access->GetScanline(otherY), tmp.data(), lineSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelMode::Split:
|
||||
{
|
||||
// Split to normal and alpha bitmaps.
|
||||
|
@@ -99,7 +99,7 @@ static bool writeWebp(SvStream& rStream, const BitmapEx& bitmapEx, bool lossless
|
||||
BitmapScopedReadAccess access(bitmap);
|
||||
BitmapScopedReadAccess accessAlpha(bitmapAlpha);
|
||||
bool dataDone = false;
|
||||
if (bitmapAlpha.IsEmpty())
|
||||
if (!access->IsBottomUp() && bitmapAlpha.IsEmpty())
|
||||
{
|
||||
// Try to directly copy the bitmap data.
|
||||
switch (access->GetScanlineFormat())
|
||||
|
@@ -235,6 +235,7 @@ std::optional<BitmapBuffer> StretchAndConvert(
|
||||
std::optional<BitmapBuffer> pDstBuffer(std::in_place);
|
||||
|
||||
|
||||
pDstBuffer->meDirection = rSrcBuffer.meDirection;
|
||||
// set function for getting pixels
|
||||
pFncGetPixel = BitmapReadAccess::GetPixelFunction(rSrcBuffer.meFormat);
|
||||
if( !pFncGetPixel )
|
||||
@@ -378,15 +379,33 @@ std::optional<BitmapBuffer> StretchAndConvert(
|
||||
}
|
||||
|
||||
// source scanline buffer
|
||||
Scanline pTmpScan = rSrcBuffer.mpBits;
|
||||
tools::Long nOffset = rSrcBuffer.mnScanlineSize;
|
||||
Scanline pTmpScan;
|
||||
tools::Long nOffset;
|
||||
if (rSrcBuffer.meDirection == ScanlineDirection::TopDown)
|
||||
{
|
||||
pTmpScan = rSrcBuffer.mpBits;
|
||||
nOffset = rSrcBuffer.mnScanlineSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTmpScan = rSrcBuffer.mpBits + ( rSrcBuffer.mnHeight - 1 ) * rSrcBuffer.mnScanlineSize;
|
||||
nOffset = -rSrcBuffer.mnScanlineSize;
|
||||
}
|
||||
|
||||
for (tools::Long i = 0; i < rSrcBuffer.mnHeight; i++, pTmpScan += nOffset)
|
||||
pSrcScan[ i ] = pTmpScan;
|
||||
|
||||
// destination scanline buffer
|
||||
pTmpScan = pDstBuffer->mpBits;
|
||||
nOffset = pDstBuffer->mnScanlineSize;
|
||||
if (pDstBuffer->meDirection == ScanlineDirection::TopDown)
|
||||
{
|
||||
pTmpScan = pDstBuffer->mpBits;
|
||||
nOffset = pDstBuffer->mnScanlineSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTmpScan = pDstBuffer->mpBits + ( pDstBuffer->mnHeight - 1 ) * pDstBuffer->mnScanlineSize;
|
||||
nOffset = -pDstBuffer->mnScanlineSize;
|
||||
}
|
||||
|
||||
for (tools::Long i = 0; i < pDstBuffer->mnHeight; i++, pTmpScan += nOffset)
|
||||
pDstScan[ i ] = pTmpScan;
|
||||
|
@@ -399,6 +399,11 @@ uno::Sequence< sal_Int8 > SAL_CALL VclCanvasBitmap::getData( rendering::IntegerB
|
||||
bitmapLayout.ScanLineStride= aRequestedBytes.getOpenWidth();
|
||||
|
||||
sal_Int32 nScanlineStride=bitmapLayout.ScanLineStride;
|
||||
if (m_pBmpAcc->IsBottomUp())
|
||||
{
|
||||
pOutBuf += bitmapLayout.ScanLineStride*(aRequestedBytes.getOpenHeight()-1);
|
||||
nScanlineStride *= -1;
|
||||
}
|
||||
|
||||
if( !m_aBmpEx.IsAlpha() )
|
||||
{
|
||||
|
@@ -561,8 +561,12 @@ BitmapEx OpenGLHelper::ConvertBufferToBitmapEx(const sal_uInt8* const pBuffer, t
|
||||
BitmapScopedWriteAccess pAlphaWriteAccess( aAlpha );
|
||||
#ifdef _WIN32
|
||||
assert(pWriteAccess->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr);
|
||||
assert(pWriteAccess->IsTopDown());
|
||||
assert(pAlphaWriteAccess->IsTopDown());
|
||||
#else
|
||||
assert(pWriteAccess->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb);
|
||||
assert(!pWriteAccess->IsTopDown());
|
||||
assert(!pAlphaWriteAccess->IsTopDown());
|
||||
#endif
|
||||
assert(pAlphaWriteAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal);
|
||||
|
||||
|
@@ -538,11 +538,10 @@ void ImplDrawBitmap( HDC hDC, const SalTwoRect& rPosAry, const WinSalBitmap& rSa
|
||||
WinSalBitmap::ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGBQUAD );
|
||||
const int nOldStretchMode = SetStretchBltMode( hDC, STRETCH_DELETESCANS );
|
||||
|
||||
int nHeight = -pBI->bmiHeader.biHeight; // height is negative for top-down bitmap
|
||||
StretchDIBits( hDC,
|
||||
static_cast<int>(rPosAry.mnDestX), static_cast<int>(rPosAry.mnDestY),
|
||||
static_cast<int>(rPosAry.mnDestWidth), static_cast<int>(rPosAry.mnDestHeight),
|
||||
static_cast<int>(rPosAry.mnSrcX), static_cast<int>(nHeight - rPosAry.mnSrcHeight - rPosAry.mnSrcY),
|
||||
static_cast<int>(rPosAry.mnSrcX), static_cast<int>(pBI->bmiHeader.biHeight - rPosAry.mnSrcHeight - rPosAry.mnSrcY),
|
||||
static_cast<int>(rPosAry.mnSrcWidth), static_cast<int>(rPosAry.mnSrcHeight),
|
||||
pBits, pBI, DIB_RGB_COLORS, nDrawMode );
|
||||
|
||||
|
@@ -251,6 +251,7 @@ std::shared_ptr<Gdiplus::Bitmap> WinSalBitmap::ImplCreateGdiPlusBitmap()
|
||||
{
|
||||
sal_uInt8* pSrcRGB(pRGB->mpBits);
|
||||
const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
|
||||
const bool bTopDown(pRGB->meDirection == ScanlineDirection::TopDown);
|
||||
const Gdiplus::Rect aAllRect(0, 0, nW, nH);
|
||||
Gdiplus::BitmapData aGdiPlusBitmapData;
|
||||
pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &aGdiPlusBitmapData);
|
||||
@@ -258,7 +259,8 @@ std::shared_ptr<Gdiplus::Bitmap> WinSalBitmap::ImplCreateGdiPlusBitmap()
|
||||
// copy data to Gdiplus::Bitmap; format is BGR here in both cases, so memcpy is possible
|
||||
for(sal_uInt32 y(0); y < nH; y++)
|
||||
{
|
||||
sal_uInt8* targetPixels = static_cast<sal_uInt8*>(aGdiPlusBitmapData.Scan0) + (y * aGdiPlusBitmapData.Stride);
|
||||
const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
|
||||
sal_uInt8* targetPixels = static_cast<sal_uInt8*>(aGdiPlusBitmapData.Scan0) + (nYInsert * aGdiPlusBitmapData.Stride);
|
||||
|
||||
memcpy(targetPixels, pSrcRGB, nW * 3);
|
||||
pSrcRGB += nW * 3 + nExtraRGB;
|
||||
@@ -368,6 +370,7 @@ std::shared_ptr<Gdiplus::Bitmap> WinSalBitmap::ImplCreateGdiPlusBitmap(const Win
|
||||
sal_uInt8* pSrcA(pA->mpBits);
|
||||
const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
|
||||
const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
|
||||
const bool bTopDown(pRGB->meDirection == ScanlineDirection::TopDown);
|
||||
const Gdiplus::Rect aAllRect(0, 0, nW, nH);
|
||||
Gdiplus::BitmapData aGdiPlusBitmapData;
|
||||
pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData);
|
||||
@@ -376,7 +379,8 @@ std::shared_ptr<Gdiplus::Bitmap> WinSalBitmap::ImplCreateGdiPlusBitmap(const Win
|
||||
// A from alpha, so inner loop is needed (who invented BitmapEx..?)
|
||||
for(sal_uInt32 y(0); y < nH; y++)
|
||||
{
|
||||
sal_uInt8* targetPixels = static_cast<sal_uInt8*>(aGdiPlusBitmapData.Scan0) + (y * aGdiPlusBitmapData.Stride);
|
||||
const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
|
||||
sal_uInt8* targetPixels = static_cast<sal_uInt8*>(aGdiPlusBitmapData.Scan0) + (nYInsert * aGdiPlusBitmapData.Stride);
|
||||
|
||||
for(sal_uInt32 x(0); x < nW; x++)
|
||||
{
|
||||
@@ -517,11 +521,10 @@ bool WinSalBitmap::Create( const SalBitmap& rSSalBmp, SalGraphics* pSGraphics )
|
||||
|
||||
if( pBI->bmiHeader.biBitCount == 1 )
|
||||
{
|
||||
int nHeight = -pBI->bmiHeader.biHeight; // height is negative for top-down bitmap
|
||||
hNewDDB = CreateBitmap( pBI->bmiHeader.biWidth, nHeight, 1, 1, nullptr );
|
||||
hNewDDB = CreateBitmap( pBI->bmiHeader.biWidth, pBI->bmiHeader.biHeight, 1, 1, nullptr );
|
||||
|
||||
if( hNewDDB )
|
||||
SetDIBits( hDC, hNewDDB, 0, nHeight, pBits, pBI, DIB_RGB_COLORS );
|
||||
SetDIBits( hDC, hNewDDB, 0, pBI->bmiHeader.biHeight, pBits, pBI, DIB_RGB_COLORS );
|
||||
}
|
||||
else
|
||||
hNewDDB = CreateDIBitmap( hDC, &pBI->bmiHeader, CBM_INIT, pBits, pBI, DIB_RGB_COLORS );
|
||||
@@ -688,7 +691,7 @@ HGLOBAL WinSalBitmap::ImplCreateDIB(const Size& rSize, vcl::PixelFormat ePixelFo
|
||||
|
||||
pBIH->biSize = sizeof( BITMAPINFOHEADER );
|
||||
pBIH->biWidth = rSize.Width();
|
||||
pBIH->biHeight = -rSize.Height(); // negative for top-down bitmap
|
||||
pBIH->biHeight = rSize.Height();
|
||||
pBIH->biPlanes = 1;
|
||||
pBIH->biBitCount = nBits;
|
||||
pBIH->biCompression = BI_RGB;
|
||||
|
@@ -116,10 +116,14 @@ void convertToWinSalBitmap(SalBitmap& rSalBitmap, WinSalBitmap& rWinSalBitmap)
|
||||
rWinSalBitmap.Create(rSalBitmap.GetSize(), vcl::bitDepthToPixelFormat(rSalBitmap.GetBitCount()), aBitmapPalette);
|
||||
BitmapBuffer* pWrite = rWinSalBitmap.AcquireBuffer(BitmapAccessMode::Write);
|
||||
|
||||
// convert to bottom-up data
|
||||
sal_uInt8* pSource = pRead->mpBits + pRead->mnScanlineSize * (pRead->mnHeight - 1);
|
||||
sal_uInt8* pSource(pRead->mpBits);
|
||||
sal_uInt8* pDestination(pWrite->mpBits);
|
||||
tools::Long readRowChange = -pRead->mnScanlineSize;
|
||||
tools::Long readRowChange = pRead->mnScanlineSize;
|
||||
if (pRead->meDirection == ScanlineDirection::TopDown)
|
||||
{
|
||||
pSource += pRead->mnScanlineSize * (pRead->mnHeight - 1);
|
||||
readRowChange = -readRowChange;
|
||||
}
|
||||
|
||||
std::unique_ptr<ColorScanlineConverter> pConverter;
|
||||
|
||||
|
@@ -33,8 +33,6 @@
|
||||
|
||||
HBITMAP WinSalVirtualDevice::ImplCreateVirDevBitmap(HDC hDC, tools::Long nDX, tools::Long nDY, sal_uInt16 nBitCount, void **ppData)
|
||||
{
|
||||
assert(nDX >= 0);
|
||||
assert(nDY >= 0);
|
||||
HBITMAP hBitmap;
|
||||
|
||||
if ( nBitCount == 1 )
|
||||
@@ -54,7 +52,7 @@ HBITMAP WinSalVirtualDevice::ImplCreateVirDevBitmap(HDC hDC, tools::Long nDX, to
|
||||
BITMAPINFO aBitmapInfo;
|
||||
aBitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
|
||||
aBitmapInfo.bmiHeader.biWidth = nDX;
|
||||
aBitmapInfo.bmiHeader.biHeight = -nDY; // negative for top-down
|
||||
aBitmapInfo.bmiHeader.biHeight = nDY;
|
||||
aBitmapInfo.bmiHeader.biPlanes = 1;
|
||||
aBitmapInfo.bmiHeader.biBitCount = nBitCount;
|
||||
aBitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
Reference in New Issue
Block a user