summaryrefslogtreecommitdiff
path: root/vcl/source/gdi
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2013-11-07 13:29:41 +0000
committerArmin Le Grand <alg@apache.org>2013-11-07 13:29:41 +0000
commite9a2d5e2889fe43565fcf453fa9db3875187d20b (patch)
tree5f9fd2bed5efa78233da130f080810e5d8d17de7 /vcl/source/gdi
parent016bb3894dcc2e3a9cfb6324f1a9f389c192426d (diff)
resync to trunk
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r--vcl/source/gdi/bitmapex.cxx304
-rw-r--r--vcl/source/gdi/bmpacc.cxx120
-rwxr-xr-xvcl/source/gdi/dibtools.cxx39
-rw-r--r--vcl/source/gdi/outdev2.cxx149
-rw-r--r--vcl/source/gdi/pngread.cxx245
-rw-r--r--vcl/source/gdi/region.cxx5
-rw-r--r--vcl/source/gdi/sallayout.cxx7
-rw-r--r--vcl/source/gdi/salmisc.cxx12
8 files changed, 626 insertions, 255 deletions
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index b44ea2e41d8f..7345cb032ad6 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -845,87 +845,6 @@ sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const
namespace
{
- void impSmoothPoint(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
- {
- double fDeltaX(rSource.getX() - nIntX);
- double fDeltaY(rSource.getY() - nIntY);
- sal_Int32 nIndX(0L);
- sal_Int32 nIndY(0L);
-
- if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
- {
- nIndX++;
- }
- else if(fDeltaX < 0.0 && nIntX >= 1L)
- {
- fDeltaX = -fDeltaX;
- nIndX--;
- }
-
- if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
- {
- nIndY++;
- }
- else if(fDeltaY < 0.0 && nIntY >= 1L)
- {
- fDeltaY = -fDeltaY;
- nIndY--;
- }
-
- if(nIndX || nIndY)
- {
- const double fColorToReal(1.0 / 255.0);
- double fR(rValue.GetRed() * fColorToReal);
- double fG(rValue.GetGreen() * fColorToReal);
- double fB(rValue.GetBlue() * fColorToReal);
- double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
-
- if(nIndX)
- {
- const double fMulA(fDeltaX * fColorToReal);
- double fMulB(1.0 - fDeltaX);
- const BitmapColor aTopPartner(rRead.GetColor(nIntY, nIntX + nIndX));
-
- fR = (fR * fMulB) + (aTopPartner.GetRed() * fMulA);
- fG = (fG * fMulB) + (aTopPartner.GetGreen() * fMulA);
- fB = (fB * fMulB) + (aTopPartner.GetBlue() * fMulA);
-
- if(nIndY)
- {
- fMulB *= fColorToReal;
- const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
- const BitmapColor aBottomPartner(rRead.GetColor(nIntY + nIndY, nIntX + nIndX));
-
- fRBottom = (aBottom.GetRed() * fMulB) + (aBottomPartner.GetRed() * fMulA);
- fGBottom = (aBottom.GetGreen() * fMulB) + (aBottomPartner.GetGreen() * fMulA);
- fBBottom = (aBottom.GetBlue() * fMulB) + (aBottomPartner.GetBlue() * fMulA);
- }
- }
-
- if(nIndY)
- {
- if(!nIndX)
- {
- const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
-
- fRBottom = aBottom.GetRed() * fColorToReal;
- fGBottom = aBottom.GetGreen() * fColorToReal;
- fBBottom = aBottom.GetBlue() * fColorToReal;
- }
-
- const double fMulB(1.0 - fDeltaY);
-
- fR = (fR * fMulB) + (fRBottom * fDeltaY);
- fG = (fG * fMulB) + (fGBottom * fDeltaY);
- fB = (fB * fMulB) + (fBBottom * fDeltaY);
- }
-
- rValue.SetRed((sal_uInt8)(fR * 255.0));
- rValue.SetGreen((sal_uInt8)(fG * 255.0));
- rValue.SetBlue((sal_uInt8)(fB * 255.0));
- }
- }
-
Bitmap impTransformBitmap(
const Bitmap& rSource,
const Size aDestinationSize,
@@ -937,54 +856,41 @@ namespace
if(pWrite)
{
- const Size aContentSizePixel(rSource.GetSizePixel());
+ //const Size aContentSizePixel(rSource.GetSizePixel());
BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
if(pRead)
{
const Size aDestinationSizePixel(aDestination.GetSizePixel());
- bool bWorkWithIndex(rSource.GetBitCount() <= 8);
- BitmapColor aOutside(BitmapColor(0xff, 0xff, 0xff));
+ const BitmapColor aOutside(BitmapColor(0xff, 0xff, 0xff));
for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
{
for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
{
const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
- const sal_Int32 nIntX(basegfx::fround(aSourceCoor.getX()));
- if(nIntX >= 0L && nIntX < aContentSizePixel.getWidth())
+ if(bSmooth)
{
- const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY()));
-
- if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight())
- {
- // inside pixel
- BitmapColor aValue;
-
- if(bWorkWithIndex)
- {
- aValue = pRead->GetPaletteColor(pRead->GetPixelIndex(nIntY, nIntX));
- }
- else
- {
- aValue = pRead->GetPixel(nIntY, nIntX);
- }
-
- if(bSmooth)
- {
- impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead);
- }
-
- pWrite->SetPixel(y, x, aValue);
- continue;
- }
+ pWrite->SetPixel(
+ y,
+ x,
+ pRead->GetInterpolatedColorWithFallback(
+ aSourceCoor.getY(),
+ aSourceCoor.getX(),
+ aOutside));
}
-
- // here are outside pixels. Complete mask
- if(bWorkWithIndex)
+ else
{
- pWrite->SetPixel(y, x, aOutside);
+ // this version does the correct <= 0.0 checks, so no need
+ // to do the static_cast< sal_Int32 > self and make an error
+ pWrite->SetPixel(
+ y,
+ x,
+ pRead->GetColorWithFallback(
+ aSourceCoor.getY(),
+ aSourceCoor.getX(),
+ aOutside));
}
}
}
@@ -1000,25 +906,26 @@ namespace
return aDestination;
}
} // end of anonymous namespace
+
BitmapEx BitmapEx::TransformBitmapEx(
double fWidth,
double fHeight,
- const basegfx::B2DHomMatrix& rTransformation) const
+ const basegfx::B2DHomMatrix& rTransformation,
+ bool bSmooth) const
{
if(fWidth <= 1 || fHeight <= 1)
return BitmapEx();
// force destination to 24 bit, we want to smooth output
const Size aDestinationSize(basegfx::fround(fWidth), basegfx::fround(fHeight));
- static bool bDoSmoothAtAll(true);
- const Bitmap aDestination(impTransformBitmap(GetBitmap(), aDestinationSize, rTransformation, bDoSmoothAtAll));
+ const Bitmap aDestination(impTransformBitmap(GetBitmap(), aDestinationSize, rTransformation, bSmooth));
// create mask
if(IsTransparent())
{
if(IsAlpha())
{
- const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bDoSmoothAtAll));
+ const Bitmap aAlpha(impTransformBitmap(GetAlpha().GetBitmap(), aDestinationSize, rTransformation, bSmooth));
return BitmapEx(aDestination, AlphaMask(aAlpha));
}
else
@@ -1035,7 +942,9 @@ BitmapEx BitmapEx::TransformBitmapEx(
BitmapEx BitmapEx::getTransformed(
const basegfx::B2DHomMatrix& rTransformation,
- double fMaximumArea) const
+ const basegfx::B2DRange& rVisibleRange,
+ double fMaximumArea,
+ bool bSmooth) const
{
BitmapEx aRetval;
@@ -1048,20 +957,31 @@ BitmapEx BitmapEx::getTransformed(
if(!nSourceWidth || !nSourceHeight)
return aRetval;
- // Get dest range
+ // Get aOutlineRange
basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
+
aOutlineRange.transform(rTransformation);
- // get target size
- double fWidth(aOutlineRange.getWidth());
- double fHeight(aOutlineRange.getHeight());
+ // create visible range from it by moving from relative to absolute
+ basegfx::B2DRange aVisibleRange(rVisibleRange);
+
+ aVisibleRange.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aOutlineRange.getRange(),
+ aOutlineRange.getMinimum()));
+
+ // get target size (which is visible range's size)
+ double fWidth(aVisibleRange.getWidth());
+ double fHeight(aVisibleRange.getHeight());
if(fWidth < 1.0 || fHeight < 1.0)
+ {
return aRetval;
+ }
// test if discrete size (pixel) maybe too big and limit it
const double fArea(fWidth * fHeight);
- const bool bNeedToReduce(fArea > fMaximumArea);
+ const bool bNeedToReduce(basegfx::fTools::more(fArea, fMaximumArea));
double fReduceFactor(1.0);
if(bNeedToReduce)
@@ -1082,8 +1002,10 @@ BitmapEx BitmapEx::getTransformed(
// aOutlineRange
aTransform = rTransformation * aTransform;
- // substract top-left of aOutlineRange
- aTransform.translate(-aOutlineRange.getMinX(), -aOutlineRange.getMinY());
+ // substract top-left of absolute VisibleRange
+ aTransform.translate(
+ -aVisibleRange.getMinX(),
+ -aVisibleRange.getMinY());
// scale to target pixels (if needed)
if(bNeedToReduce)
@@ -1095,7 +1017,7 @@ BitmapEx BitmapEx::getTransformed(
aTransform.invert();
// create bitmap using source, destination and linear back-transformation
- aRetval = TransformBitmapEx(fWidth, fHeight, aTransform);
+ aRetval = TransformBitmapEx(fWidth, fHeight, aTransform, bSmooth);
return aRetval;
}
@@ -1109,58 +1031,110 @@ BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorMod
for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
{
- const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
+ const basegfx::BColorModifierSharedPtr& rModifier = rBColorModifierStack.getBColorModifier(--a);
+ const basegfx::BColorModifier_replace* pReplace = dynamic_cast< const basegfx::BColorModifier_replace* >(rModifier.get());
- switch(rModifier.getMode())
+ if(pReplace)
{
- case basegfx::BCOLORMODIFYMODE_REPLACE :
+ // complete replace
+ if(IsTransparent())
{
- // complete replace
- if(IsTransparent())
+ // clear bitmap with dest color
+ if(aChangedBitmap.GetBitCount() <= 8)
{
- // clear bitmap with dest color
- if(aChangedBitmap.GetBitCount() <= 8)
- {
- // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
- // erase color is determined and used -> this may be different from what is
- // wanted here. Better create a new bitmap with the needed color explicitely
- BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
- OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
+ // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
+ // erase color is determined and used -> this may be different from what is
+ // wanted here. Better create a new bitmap with the needed color explicitely
+ BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
+ OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
- if(pReadAccess)
- {
- BitmapPalette aNewPalette(pReadAccess->GetPalette());
- aNewPalette[0] = BitmapColor(Color(rModifier.getBColor()));
- aChangedBitmap = Bitmap(
- aChangedBitmap.GetSizePixel(),
- aChangedBitmap.GetBitCount(),
- &aNewPalette);
- delete pReadAccess;
- }
- }
- else
+ if(pReadAccess)
{
- aChangedBitmap.Erase(Color(rModifier.getBColor()));
+ BitmapPalette aNewPalette(pReadAccess->GetPalette());
+ aNewPalette[0] = BitmapColor(Color(pReplace->getBColor()));
+ aChangedBitmap = Bitmap(
+ aChangedBitmap.GetSizePixel(),
+ aChangedBitmap.GetBitCount(),
+ &aNewPalette);
+ delete pReadAccess;
}
}
else
{
- // erase bitmap, caller will know to paint direct
- aChangedBitmap.SetEmpty();
+ aChangedBitmap.Erase(Color(pReplace->getBColor()));
}
-
- bDone = true;
- break;
+ }
+ else
+ {
+ // erase bitmap, caller will know to paint direct
+ aChangedBitmap.SetEmpty();
}
- default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
+ bDone = true;
+ }
+ else
+ {
+ BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
+
+ if(pContent)
{
- BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
+ const double fConvertColor(1.0 / 255.0);
+
+ if(pContent->HasPalette())
+ {
+ const sal_uInt16 nCount(pContent->GetPaletteEntryCount());
+
+ for(sal_uInt16 a(0); a < nCount; a++)
+ {
+ const BitmapColor& rCol = pContent->GetPaletteColor(a);
+ const basegfx::BColor aBSource(
+ rCol.GetRed() * fConvertColor,
+ rCol.GetGreen() * fConvertColor,
+ rCol.GetBlue() * fConvertColor);
+ const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
+ pContent->SetPaletteColor(a, BitmapColor(Color(aBDest)));
+ }
+ }
+ else if(BMP_FORMAT_24BIT_TC_BGR == pContent->GetScanlineFormat())
+ {
+ for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+ {
+ Scanline pScan = pContent->GetScanline(y);
- if(pContent)
+ for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
+ {
+ const basegfx::BColor aBSource(
+ *(pScan + 2)* fConvertColor,
+ *(pScan + 1) * fConvertColor,
+ *pScan * fConvertColor);
+ const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
+ }
+ }
+ }
+ else if(BMP_FORMAT_24BIT_TC_RGB == pContent->GetScanlineFormat())
{
- const double fConvertColor(1.0 / 255.0);
+ for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+ {
+ Scanline pScan = pContent->GetScanline(y);
+ for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
+ {
+ const basegfx::BColor aBSource(
+ *pScan * fConvertColor,
+ *(pScan + 1) * fConvertColor,
+ *(pScan + 2) * fConvertColor);
+ const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 255.0);
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() * 255.0);
+ *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 255.0);
+ }
+ }
+ }
+ else
+ {
for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
{
for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
@@ -1170,16 +1144,14 @@ BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorMod
(double)aBMCol.GetRed() * fConvertColor,
(double)aBMCol.GetGreen() * fConvertColor,
(double)aBMCol.GetBlue() * fConvertColor);
- const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
+ const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
}
}
-
- delete pContent;
}
- break;
+ delete pContent;
}
}
}
diff --git a/vcl/source/gdi/bmpacc.cxx b/vcl/source/gdi/bmpacc.cxx
index ae41737b1667..9e2ab2df9f91 100644
--- a/vcl/source/gdi/bmpacc.cxx
+++ b/vcl/source/gdi/bmpacc.cxx
@@ -324,6 +324,126 @@ sal_uInt16 BitmapReadAccess::GetBestPaletteIndex( const BitmapColor& rBitmapColo
return( HasPalette() ? mpBuffer->maPalette.GetBestIndex( rBitmapColor ) : 0 );
}
+BitmapColor BitmapReadAccess::GetInterpolatedColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
+{
+ // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
+ // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
+ if(mpBuffer && fX >= 0.0 && fY >= 0.0)
+ {
+ const sal_Int32 nX(static_cast< sal_Int32 >(fX));
+ const sal_Int32 nY(static_cast< sal_Int32 >(fY));
+
+ if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
+ {
+ // get base-return value from inside pixel
+ BitmapColor aRetval(GetColor(nY, nX));
+
+ // calculate deltas and indices for neighbour accesses
+ sal_Int16 nDeltaX((fX - (nX + 0.5)) * 255.0); // [-255 .. 255]
+ sal_Int16 nDeltaY((fY - (nY + 0.5)) * 255.0); // [-255 .. 255]
+ sal_Int16 nIndX(0);
+ sal_Int16 nIndY(0);
+
+ if(nDeltaX > 0)
+ {
+ nIndX = nX + 1;
+ }
+ else
+ {
+ nIndX = nX - 1;
+ nDeltaX = -nDeltaX;
+ }
+
+ if(nDeltaY > 0)
+ {
+ nIndY = nY + 1;
+ }
+ else
+ {
+ nIndY = nY - 1;
+ nDeltaY = -nDeltaY;
+ }
+
+ // get right/left neighbour
+ BitmapColor aXCol(rFallback);
+
+ if(nDeltaX && nIndX >= 0 && nIndX < mpBuffer->mnWidth)
+ {
+ aXCol = GetColor(nY, nIndX);
+ }
+
+ // get top/bottom neighbour
+ BitmapColor aYCol(rFallback);
+
+ if(nDeltaY && nIndY >= 0 && nIndY < mpBuffer->mnHeight)
+ {
+ aYCol = GetColor(nIndY, nX);
+ }
+
+ // get one of four edge neighbours
+ BitmapColor aXYCol(rFallback);
+
+ if(nDeltaX && nDeltaY && nIndX >=0 && nIndY >= 0 && nIndX < mpBuffer->mnWidth && nIndY < mpBuffer->mnHeight)
+ {
+ aXYCol = GetColor(nIndY, nIndX);
+ }
+
+ // merge return value with right/left neighbour
+ if(aXCol != aRetval)
+ {
+ aRetval.Merge(aXCol, 255 - nDeltaX);
+ }
+
+ // merge top/bottom neighbour with edge
+ if(aYCol != aXYCol)
+ {
+ aYCol.Merge(aXYCol, 255 - nDeltaX);
+ }
+
+ // merge return value with already merged top/bottom neighbour
+ if(aRetval != aYCol)
+ {
+ aRetval.Merge(aYCol, 255 - nDeltaY);
+ }
+
+ return aRetval;
+ }
+ }
+
+ return rFallback;
+}
+
+BitmapColor BitmapReadAccess::GetColorWithFallback( double fY, double fX, const BitmapColor& rFallback ) const
+{
+ // ask directly doubles >= 0.0 here to avoid rounded values of 0 at small negative
+ // double values, e.g. static_cast< sal_Int32 >(-0.25) is 0, not -1, but *has* to be outside (!)
+ if(mpBuffer && fX >= 0.0 && fY >= 0.0)
+ {
+ const sal_Int32 nX(static_cast< sal_Int32 >(fX));
+ const sal_Int32 nY(static_cast< sal_Int32 >(fY));
+
+ if(nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
+ {
+ return GetColor(nY, nX);
+ }
+ }
+
+ return rFallback;
+}
+
+BitmapColor BitmapReadAccess::GetColorWithFallback( long nY, long nX, const BitmapColor& rFallback ) const
+{
+ if(mpBuffer)
+ {
+ if(nX >= 0 && nY >= 0 && nX < mpBuffer->mnWidth && nY < mpBuffer->mnHeight)
+ {
+ return GetColor(nY, nX);
+ }
+ }
+
+ return rFallback;
+}
+
// ---------------------
// - BitmapWriteAccess -
// ---------------------
diff --git a/vcl/source/gdi/dibtools.cxx b/vcl/source/gdi/dibtools.cxx
index 8e2c0e5970b2..bdfce54454aa 100755
--- a/vcl/source/gdi/dibtools.cxx
+++ b/vcl/source/gdi/dibtools.cxx
@@ -388,12 +388,12 @@ void ImplDecodeRLE( sal_uInt8* pBuffer, DIBV5Header& rHeader, BitmapWriteAccess&
while ( !bEndDecoding && ( nY >= 0L ) );
}
-bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown)
+bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& rAcc, BitmapWriteAccess* pAccAlpha, bool bTopDown, bool& rAlphaUsed)
{
const sal_uLong nAlignedWidth = AlignedWidth4Bytes(rHeader.nWidth * rHeader.nBitCount);
- sal_uInt32 nRMask(0);
- sal_uInt32 nGMask(0);
- sal_uInt32 nBMask(0);
+ sal_uInt32 nRMask(( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL);
+ sal_uInt32 nGMask(( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL);
+ sal_uInt32 nBMask(( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL);
bool bNative(false);
bool bTCMask(!pAccAlpha && ((16 == rHeader.nBitCount) || (32 == rHeader.nBitCount)));
bool bRLE((RLE_8 == rHeader.nCompression && 8 == rHeader.nBitCount) || (RLE_4 == rHeader.nCompression && 4 == rHeader.nBitCount));
@@ -430,21 +430,12 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
else
{
// Read color mask
- if(bTCMask)
+ if(bTCMask && BITFIELDS == rHeader.nCompression)
{
- if(BITFIELDS == rHeader.nCompression)
- {
- rIStm.SeekRel( -12L );
- rIStm >> nRMask;
- rIStm >> nGMask;
- rIStm >> nBMask;
- }
- else
- {
- nRMask = ( rHeader.nBitCount == 16 ) ? 0x00007c00UL : 0x00ff0000UL;
- nGMask = ( rHeader.nBitCount == 16 ) ? 0x000003e0UL : 0x0000ff00UL;
- nBMask = ( rHeader.nBitCount == 16 ) ? 0x0000001fUL : 0x000000ffUL;
- }
+ rIStm.SeekRel( -12L );
+ rIStm >> nRMask;
+ rIStm >> nGMask;
+ rIStm >> nBMask;
}
if(bRLE)
@@ -601,6 +592,7 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
aMask.GetColorAndAlphaFor32Bit( aColor, aAlpha, (sal_uInt8*) pTmp32++ );
rAcc.SetPixel( nY, nX, aColor );
pAccAlpha->SetPixelIndex(nY, nX, sal_uInt8(0xff) - aAlpha);
+ rAlphaUsed |= bool(0xff != aAlpha);
}
}
}
@@ -725,6 +717,8 @@ bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLon
}
// read bits
+ bool bAlphaUsed(false);
+
if(!pIStm->GetError())
{
if(nOffset)
@@ -732,7 +726,7 @@ bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLon
pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
}
- bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown);
+ bRet = ImplReadDIBBits(*pIStm, aHeader, *pAcc, pAccAlpha, bTopDown, bAlphaUsed);
if(bRet && aHeader.nXPelsPerMeter && aHeader.nYPelsPerMeter)
{
@@ -758,6 +752,11 @@ bool ImplReadDIBBody( SvStream& rIStm, Bitmap& rBmp, Bitmap* pBmpAlpha, sal_uLon
if(bAlphaPossible)
{
aNewBmpAlpha.ReleaseAccess(pAccAlpha);
+
+ if(!bAlphaUsed)
+ {
+ bAlphaPossible = false;
+ }
}
if(bRet)
@@ -1240,7 +1239,7 @@ bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess&
if(pAccAlpha) // only write DIBV5 when asked to do so
{
aHeader.nV5CSType = 0x57696E20; // LCS_WINDOWS_COLOR_SPACE
- aHeader.nV5Intent = 0x00000008; // LCS_GM_ABS_COLORIMETRIC
+ aHeader.nV5Intent = 0x00000004; // LCS_GM_IMAGES
rOStm << aHeader.nV5RedMask;
rOStm << aHeader.nV5GreenMask;
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx
index 46f10a8a3534..f13620ad49df 100644
--- a/vcl/source/gdi/outdev2.cxx
+++ b/vcl/source/gdi/outdev2.cxx
@@ -43,6 +43,7 @@
#include <window.h>
#include <outdata.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#define BAND_MAX_SIZE 512000
@@ -818,8 +819,9 @@ void OutputDevice::DrawTransformedBitmapEx(
const bool bSheared(!basegfx::fTools::equalZero(fShearX));
const bool bMirroredX(basegfx::fTools::less(aScale.getX(), 0.0));
const bool bMirroredY(basegfx::fTools::less(aScale.getY(), 0.0));
+ static bool bForceToOwnTransformer(false);
- if(!bRotated && !bSheared && !bMirroredX && !bMirroredY)
+ if(!bForceToOwnTransformer && !bRotated && !bSheared && !bMirroredX && !bMirroredY)
{
// with no rotation, shear or mirroring it can be mapped to DrawBitmapEx
// do *not* execute the mirroring here, it's done in the fallback
@@ -840,7 +842,7 @@ void OutputDevice::DrawTransformedBitmapEx(
const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile && !bPrinter);
- if(bTryDirectPaint)
+ if(!bForceToOwnTransformer && bTryDirectPaint)
{
// try to paint directly
const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0));
@@ -873,7 +875,7 @@ void OutputDevice::DrawTransformedBitmapEx(
if(!bDone)
{
// take the fallback when no rotate and shear, but mirror (else we would have done this above)
- if(!bRotated && !bSheared)
+ if(!bForceToOwnTransformer && !bRotated && !bSheared)
{
// with no rotation or shear it can be mapped to DrawBitmapEx
// do *not* execute the mirroring here, it's done in the fallback
@@ -886,14 +888,139 @@ void OutputDevice::DrawTransformedBitmapEx(
// fallback; create transformed bitmap the hard way (back-transform
// the pixels) and paint
- basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
- const double fMaximumArea(bMetafile ? 800000.0 : 200000.0);
- const BitmapEx aTransformed(rBitmapEx.getTransformed(aFullTransform, fMaximumArea));
- aTargetRange.transform(rTransformation);
- const Point aDestPt(basegfx::fround(aTargetRange.getMinX()), basegfx::fround(aTargetRange.getMinY()));
- const Size aDestSize(basegfx::fround(aTargetRange.getWidth()), basegfx::fround(aTargetRange.getHeight()));
-
- DrawBitmapEx(aDestPt, aDestSize, aTransformed);
+ basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0);
+
+ // limit maximum area to something looking good for non-pixel-based targets (metafile, printer)
+ // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area
+ // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
+ // to avoid crashes/ressource problems (ca. 1500x3000 here)
+ const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
+ const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
+ const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea);
+ double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled)));
+
+ if(!bMetafile && !bPrinter)
+ {
+ // limit TargetRange to existing pixels (if pixel device)
+ // first get discrete range of object
+ basegfx::B2DRange aFullPixelRange(aVisibleRange);
+
+ aFullPixelRange.transform(aFullTransform);
+
+ if(basegfx::fTools::equalZero(aFullPixelRange.getWidth()) || basegfx::fTools::equalZero(aFullPixelRange.getHeight()))
+ {
+ // object is outside of visible area
+ return;
+ }
+
+ // now get discrete target pixels; start with OutDev pixel size and evtl.
+ // intersect with active clipping area
+ basegfx::B2DRange aOutPixel(
+ 0.0,
+ 0.0,
+ GetOutputSizePixel().Width(),
+ GetOutputSizePixel().Height());
+
+ if(IsClipRegion())
+ {
+ const Rectangle aRegionRectangle(GetActiveClipRegion().GetBoundRect());
+
+ aOutPixel.intersect( // caution! Range from rectangle, one too much (!)
+ basegfx::B2DRange(
+ aRegionRectangle.Left(),
+ aRegionRectangle.Top(),
+ aRegionRectangle.Right() + 1,
+ aRegionRectangle.Bottom() + 1));
+ }
+
+ if(aOutPixel.isEmpty())
+ {
+ // no active output area
+ return;
+ }
+
+ // if aFullPixelRange is not completely inside of aOutPixel,
+ // reduction of target pixels is possible
+ basegfx::B2DRange aVisiblePixelRange(aFullPixelRange);
+
+ if(!aOutPixel.isInside(aFullPixelRange))
+ {
+ aVisiblePixelRange.intersect(aOutPixel);
+
+ if(aVisiblePixelRange.isEmpty())
+ {
+ // nothing in visible part, reduces to nothing
+ return;
+ }
+
+ // aVisiblePixelRange contains the reduced output area in
+ // discrete coordinates. To make it useful everywhere, make it relative to
+ // the object range
+ basegfx::B2DHomMatrix aMakeVisibleRangeRelative;
+
+ aVisibleRange = aVisiblePixelRange;
+ aMakeVisibleRangeRelative.translate(
+ -aFullPixelRange.getMinX(),
+ -aFullPixelRange.getMinY());
+ aMakeVisibleRangeRelative.scale(
+ 1.0 / aFullPixelRange.getWidth(),
+ 1.0 / aFullPixelRange.getHeight());
+ aVisibleRange.transform(aMakeVisibleRangeRelative);
+ }
+
+ // for pixel devices, do *not* limit size, else OutputDevice::ImplDrawAlpha
+ // will create another, badly scaled bitmap to do the job. Nonetheless, do a
+ // maximum clipping of something big (1600x1280x2). Add 1.0 to avoid rounding
+ // errors in rough estimations
+ const double fNewMaxArea(aVisiblePixelRange.getWidth() * aVisiblePixelRange.getHeight());
+
+ fMaximumArea = std::min(4096000.0, fNewMaxArea + 1.0);
+ }
+
+ if(!aVisibleRange.isEmpty())
+ {
+ static bool bDoSmoothAtAll(true);
+ BitmapEx aTransformed(rBitmapEx);
+
+ // #122923# when the result needs an alpha channel due to being rotated or sheared
+ // and thus uncovering areas, add these channels so that the own transformer (used
+ // in getTransformed) also creates a transformed alpha channel
+ if(!aTransformed.IsTransparent() && (bSheared || bRotated))
+ {
+ // parts will be uncovered, extend aTransformed with a mask bitmap
+ const Bitmap aContent(aTransformed.GetBitmap());
+#if defined(MACOSX)
+ AlphaMask aMaskBmp(aContent.GetSizePixel());
+ aMaskBmp.Erase(0);
+#else
+ Bitmap aMaskBmp(aContent.GetSizePixel(), 1);
+ aMaskBmp.Erase(Color(COL_BLACK)); // #122758# Initialize to non-transparent
+#endif
+ aTransformed = BitmapEx(aContent, aMaskBmp);
+ }
+
+ aTransformed = aTransformed.getTransformed(
+ aFullTransform,
+ aVisibleRange,
+ fMaximumArea,
+ bDoSmoothAtAll);
+ basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
+
+ // get logic object target range
+ aTargetRange.transform(rTransformation);
+
+ // get from unified/relative VisibleRange to logoc one
+ aVisibleRange.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aTargetRange.getRange(),
+ aTargetRange.getMinimum()));
+
+ // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose
+ const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
+ const Size aDestSize(basegfx::fround(aVisibleRange.getWidth()), basegfx::fround(aVisibleRange.getHeight()));
+
+ DrawBitmapEx(aDestPt, aDestSize, aTransformed);
+ }
}
}
diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx
index 3e798b5ea601..97531772c80b 100644
--- a/vcl/source/gdi/pngread.cxx
+++ b/vcl/source/gdi/pngread.cxx
@@ -151,6 +151,15 @@ private:
sal_Bool mbpHYs; // sal_True if pysical size of pixel available
sal_Bool mbIgnoreGammaChunk;
+#ifdef DBG_UTIL
+ // do some checks in debug mode
+ sal_uInt32 mnAllocSizeScanline;
+ sal_uInt32 mnAllocSizeScanlineAlpha;
+#endif
+ // the temporary Scanline (and alpha) for direct scanline copy to Bitmap
+ sal_uInt8* mpScanline;
+ sal_uInt8* mpScanlineAlpha;
+
bool ReadNextChunk();
void ReadRemainingChunks();
void SkipRemainingChunks();
@@ -204,7 +213,13 @@ PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream )
mbIDAT( sal_False ),
mbGamma ( sal_False ),
mbpHYs ( sal_False ),
- mbIgnoreGammaChunk ( sal_False )
+ mbIgnoreGammaChunk ( sal_False ),
+#ifdef DBG_UTIL
+ mnAllocSizeScanline(0),
+ mnAllocSizeScanlineAlpha(0),
+#endif
+ mpScanline(0),
+ mpScanlineAlpha(0)
{
// prepare the PNG data stream
mnOrigStreamMode = mrPNGStream.GetNumberFormatInt();
@@ -250,6 +265,9 @@ PNGReaderImpl::~PNGReaderImpl()
delete[] mpInflateInBuf;
delete[] mpScanPrior;
delete mpZCodec;
+
+ delete[] mpScanline;
+ delete[] mpScanlineAlpha;
}
// ------------------------------------------------------------------------
@@ -1358,42 +1376,125 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
else // no palette => truecolor
{
- if( mbAlphaChannel ) // has RGB + alpha
- { // BMP_FORMAT_32BIT_TC_RGBA
+ // #122985# Added fast-lane implementations using CopyScanline with direct supported mem formats
+ static bool bCkeckDirectScanline(true);
+
+ if( mbAlphaChannel )
+ {
+ // has RGB + alpha
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
- if ( mpColorTable != mpDefaultColorTable )
+ // BMP_FORMAT_32BIT_TC_RGBA
+ // only use DirectScanline when we have no preview shifting stuff and accesses to content and alpha
+ const bool bDoDirectScanline(
+ bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc && mpMaskAcc);
+ const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
+
+ if(bDoDirectScanline)
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 1 ] ],
- mpColorTable[ pTmp[ 2 ] ] ), pTmp[ 3 ] );
+ // allocate scanlines on demand, reused for next line
+ if(!mpScanline)
+ {
+#ifdef DBG_UTIL
+ mnAllocSizeScanline = maOrigSize.Width() * 3;
+#endif
+ mpScanline = new sal_uInt8[maOrigSize.Width() * 3];
+ }
+
+ if(!mpScanlineAlpha)
+ {
+#ifdef DBG_UTIL
+ mnAllocSizeScanlineAlpha = maOrigSize.Width();
+#endif
+ mpScanlineAlpha = new sal_uInt8[maOrigSize.Width()];
+ }
+ }
+
+ if(bDoDirectScanline)
+ {
+ OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
+ OSL_ENSURE(mpScanlineAlpha, "No ScanlineAlpha allocated (!)");
+#ifdef DBG_UTIL
+ OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
+ OSL_ENSURE(mnAllocSizeScanlineAlpha >= maOrigSize.Width(), "Allocated ScanlineAlpha too small (!)");
+#endif
+ sal_uInt8* pScanline(mpScanline);
+ sal_uInt8* pScanlineAlpha(mpScanlineAlpha);
+
+ for(sal_Int32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 4)
+ {
+ // prepare content line as BGR by reordering when copying
+ // do not forget to invert alpha (source is alpha, target is opacity)
+ if(bCustomColorTable)
+ {
+ *pScanline++ = mpColorTable[pTmp[2]];
+ *pScanline++ = mpColorTable[pTmp[1]];
+ *pScanline++ = mpColorTable[pTmp[0]];
+ *pScanlineAlpha++ = ~pTmp[3];
+ }
+ else
+ {
+ *pScanline++ = pTmp[2];
+ *pScanline++ = pTmp[1];
+ *pScanline++ = pTmp[0];
+ *pScanlineAlpha++ = ~pTmp[3];
+ }
+ }
+
+ // copy scanlines directly to bitmaps for content and alpha; use the formats which
+ // are able to copy directly to BitmapBuffer
+ mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3);
+ mpMaskAcc->CopyScanline(nY, mpScanlineAlpha, BMP_FORMAT_8BIT_PAL, maOrigSize.Width());
}
else
{
-// if ( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
-// {
-// int nLineBytes = 4 * maOrigSize.Width();
-// mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_32BIT_TC_RGBA, nLineBytes );
-// pTmp += nLineBytes;
-// }
-// else
+ for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ), pTmp[3] );
+ if(bCustomColorTable)
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 1 ] ],
+ mpColorTable[ pTmp[ 2 ] ]),
+ pTmp[ 3 ]);
+ }
+ else
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ pTmp[0],
+ pTmp[1],
+ pTmp[2]),
+ pTmp[3]);
+ }
}
}
}
else
- { // BMP_FORMAT_64BIT_TC_RGBA
+ {
+ // BMP_FORMAT_64BIT_TC_RGBA
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 8 )
- ImplSetAlphaPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 2 ] ],
- mpColorTable[ pTmp[ 4 ] ] ), pTmp[6] );
+ {
+ ImplSetAlphaPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 2 ] ],
+ mpColorTable[ pTmp[ 4 ] ]),
+ pTmp[6]);
+ }
}
}
else if( mbTransparent ) // has RGB + transparency
- { // BMP_FORMAT_24BIT_TC_RGB
+ {
+ // BMP_FORMAT_24BIT_TC_RGB
+ // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
@@ -1402,7 +1503,7 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
sal_uInt8 nGreen = pTmp[ 1 ];
sal_uInt8 nBlue = pTmp[ 2 ];
sal_Bool bTransparent = ( ( nRed == mnTransRed )
- && ( nGreen == mnTransGreen )
+ && ( nGreen == mnTransGreen )
&& ( nBlue == mnTransBlue ) );
ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
@@ -1411,7 +1512,8 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
}
else
- { // BMP_FORMAT_48BIT_TC_RGB
+ {
+ // BMP_FORMAT_48BIT_TC_RGB
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
{
sal_uInt8 nRed = pTmp[ 0 ];
@@ -1428,37 +1530,94 @@ void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
}
}
else // has RGB but neither alpha nor transparency
- { // BMP_FORMAT_24BIT_TC_RGB
+ {
+ // BMP_FORMAT_24BIT_TC_RGB
+ // only use DirectScanline when we have no preview shifting stuff and access to content
+ const bool bDoDirectScanline(
+ bCkeckDirectScanline && !nXStart && 1 == nXAdd && !mnPreviewShift && mpAcc);
+ const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
+
+ if(bDoDirectScanline && !mpScanline)
+ {
+ // allocate scanlines on demand, reused for next line
+#ifdef DBG_UTIL
+ mnAllocSizeScanline = maOrigSize.Width() * 3;
+#endif
+ mpScanline = new sal_uInt8[maOrigSize.Width() * 3];
+ }
+
if ( mnPngDepth == 8 ) // maybe the source has 16 bit per sample
{
- if ( mpColorTable != mpDefaultColorTable )
+ if(bDoDirectScanline)
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
- ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 1 ] ],
- mpColorTable[ pTmp[ 2 ] ] ) );
+ OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
+#ifdef DBG_UTIL
+ OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
+#endif
+ sal_uInt8* pScanline(mpScanline);
+
+ for(sal_Int32 nX(0); nX < maOrigSize.Width(); nX++, pTmp += 3)
+ {
+ // prepare content line as BGR by reordering when copying
+ if(bCustomColorTable)
+ {
+ *pScanline++ = mpColorTable[pTmp[2]];
+ *pScanline++ = mpColorTable[pTmp[1]];
+ *pScanline++ = mpColorTable[pTmp[0]];
+ }
+ else
+ {
+ *pScanline++ = pTmp[2];
+ *pScanline++ = pTmp[1];
+ *pScanline++ = pTmp[0];
+ }
+ }
+
+ // copy scanline directly to bitmap for content; use the format which is able to
+ // copy directly to BitmapBuffer
+ mpAcc->CopyScanline(nY, mpScanline, BMP_FORMAT_24BIT_TC_BGR, maOrigSize.Width() * 3);
}
else
{
- if( nXAdd == 1 && mnPreviewShift == 0 ) // copy raw line data if possible
- {
- int nLineBytes = maOrigSize.Width() * 3;
- mpAcc->CopyScanline( nY, pTmp, BMP_FORMAT_24BIT_TC_RGB, nLineBytes );
- pTmp += nLineBytes;
- }
- else
+ for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
{
- for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
- ImplSetPixel( nY, nX, BitmapColor( pTmp[0], pTmp[1], pTmp[2] ) );
+ if(bCustomColorTable)
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 1 ] ],
+ mpColorTable[ pTmp[ 2 ] ]));
+ }
+ else
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ pTmp[0],
+ pTmp[1],
+ pTmp[2]));
+ }
}
}
}
else
- { // BMP_FORMAT_48BIT_TC_RGB
+ {
+ // BMP_FORMAT_48BIT_TC_RGB
+ // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
for ( sal_Int32 nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
- ImplSetPixel( nY, nX, BitmapColor( mpColorTable[ pTmp[ 0 ] ],
- mpColorTable[ pTmp[ 2 ] ],
- mpColorTable[ pTmp[ 4 ] ] ) );
+ {
+ ImplSetPixel(
+ nY,
+ nX,
+ BitmapColor(
+ mpColorTable[ pTmp[ 0 ] ],
+ mpColorTable[ pTmp[ 2 ] ],
+ mpColorTable[ pTmp[ 4 ] ]));
+ }
}
}
}
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
index 55bb30a332c7..05e191f9a3b5 100644
--- a/vcl/source/gdi/region.cxx
+++ b/vcl/source/gdi/region.cxx
@@ -1274,9 +1274,10 @@ Rectangle Region::GetBoundRect() const
}
else
{
+ // #122149# corrected rounding, no need for ceil() and floor() here
return Rectangle(
- static_cast<sal_Int32>(floor(aRange.getMinX())), static_cast<sal_Int32>(floor(aRange.getMinY())),
- static_cast<sal_Int32>(ceil(aRange.getMaxX())), static_cast<sal_Int32>(ceil(aRange.getMaxY())));
+ basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()),
+ basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY()));
}
}
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index b858517a708b..18fef6e76fe9 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -1869,12 +1869,7 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
for( n = 0; n < nLevel; ++n )
maFallbackRuns[n].ResetPos();
// get the next codepoint index that needs fallback
- // and limit it to the minindex..endindex bounds
int nActiveCharPos = nCharPos[0];
- if( nActiveCharPos < mnMinCharPos)
- nActiveCharPos = mnMinCharPos;
- else if( nActiveCharPos >= rArgs.mnEndCharPos )
- nActiveCharPos = rArgs.mnEndCharPos - 1;
// get the end index of the active run
int nLastRunEndChar = (vRtl[nActiveCharPos - mnMinCharPos])?
rArgs.mnEndCharPos : rArgs.mnMinCharPos - 1;
@@ -2083,8 +2078,6 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
}
}
}
-// if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
-// maFallbackRuns[i].NextRun();
}
mpLayouts[0]->Simplify( true );
diff --git a/vcl/source/gdi/salmisc.cxx b/vcl/source/gdi/salmisc.cxx
index 817aa90e13da..7b93189c5d45 100644
--- a/vcl/source/gdi/salmisc.cxx
+++ b/vcl/source/gdi/salmisc.cxx
@@ -429,12 +429,12 @@ BitmapBuffer* StretchAndConvert(
}
// horizontal mapping table
- if( nDstDX != nSrcDX )
+ if( (nDstDX != nSrcDX) && (nDstDX != 0) )
{
- const double fFactorX = ( nDstDX > 1 ) ? (double) ( nSrcDX - 1 ) / ( nDstDX - 1 ) : 0.0;
+ const double fFactorX = (double)nSrcDX / nDstDX;
for( i = 0L; i < nDstDX; i++ )
- pMapX[ i ] = nSrcX + FRound( i * fFactorX );
+ pMapX[ i ] = nSrcX + static_cast<int>( i * fFactorX );
}
else
{
@@ -443,12 +443,12 @@ BitmapBuffer* StretchAndConvert(
}
// vertical mapping table
- if( nDstDY != nSrcDY )
+ if( (nDstDY != nSrcDY) && (nDstDY != 0) )
{
- const double fFactorY = ( nDstDY > 1 ) ? (double) ( nSrcDY - 1 ) / ( nDstDY - 1 ) : 0.0;
+ const double fFactorY = (double)nSrcDY / nDstDY;
for( i = 0L; i < nDstDY; i++ )
- pMapY[ i ] = nSrcY + FRound( i * fFactorY );
+ pMapY[ i ] = nSrcY + static_cast<int>( i * fFactorY );
}
else
{