diff options
author | Armin Le Grand <alg@apache.org> | 2013-11-07 13:29:41 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2013-11-07 13:29:41 +0000 |
commit | e9a2d5e2889fe43565fcf453fa9db3875187d20b (patch) | |
tree | 5f9fd2bed5efa78233da130f080810e5d8d17de7 /vcl/source/gdi | |
parent | 016bb3894dcc2e3a9cfb6324f1a9f389c192426d (diff) |
resync to trunk
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r-- | vcl/source/gdi/bitmapex.cxx | 304 | ||||
-rw-r--r-- | vcl/source/gdi/bmpacc.cxx | 120 | ||||
-rwxr-xr-x | vcl/source/gdi/dibtools.cxx | 39 | ||||
-rw-r--r-- | vcl/source/gdi/outdev2.cxx | 149 | ||||
-rw-r--r-- | vcl/source/gdi/pngread.cxx | 245 | ||||
-rw-r--r-- | vcl/source/gdi/region.cxx | 5 | ||||
-rw-r--r-- | vcl/source/gdi/sallayout.cxx | 7 | ||||
-rw-r--r-- | vcl/source/gdi/salmisc.cxx | 12 |
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 { |