/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_drawinglayer.hxx" #include #include #include #include ////////////////////////////////////////////////////////////////////////////// // support for rendering Bitmap and BitmapEx contents namespace drawinglayer { 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)); } } void impSmoothIndex(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 fVal(rValue.GetIndex() * fColorToReal); double fValBottom(0.0); if(nIndX) { const double fMulA(fDeltaX * fColorToReal); double fMulB(1.0 - fDeltaX); const BitmapColor aTopPartner(rRead.GetPixel(nIntY, nIntX + nIndX)); fVal = (fVal * fMulB) + (aTopPartner.GetIndex() * fMulA); if(nIndY) { fMulB *= fColorToReal; const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX)); const BitmapColor aBottomPartner(rRead.GetPixel(nIntY + nIndY, nIntX + nIndX)); fValBottom = (aBottom.GetIndex() * fMulB) + (aBottomPartner.GetIndex() * fMulA); } } if(nIndY) { if(!nIndX) { const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX)); fValBottom = aBottom.GetIndex() * fColorToReal; } const double fMulB(1.0 - fDeltaY); fVal = (fVal * fMulB) + (fValBottom * fDeltaY); } rValue.SetIndex((sal_uInt8)(fVal * 255.0)); } } void impTransformBitmap(const Bitmap& rSource, Bitmap& rDestination, const basegfx::B2DHomMatrix& rTransform, bool bSmooth) { BitmapWriteAccess* pWrite = rDestination.AcquireWriteAccess(); if(pWrite) { const Size aContentSizePixel(rSource.GetSizePixel()); BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess(); if(pRead) { const Size aDestinationSizePixel(rDestination.GetSizePixel()); bool bWorkWithIndex(rDestination.GetBitCount() <= 8); BitmapColor aOutside(pRead->GetBestMatchingColor(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()) { const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY())); if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight()) { if(bWorkWithIndex) { BitmapColor aValue(pRead->GetPixel(nIntY, nIntX)); if(bSmooth) { impSmoothIndex(aValue, aSourceCoor, nIntX, nIntY, *pRead); } pWrite->SetPixel(y, x, aValue); } else { BitmapColor aValue(pRead->GetColor(nIntY, nIntX)); if(bSmooth) { impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead); } pWrite->SetPixel(y, x, aValue.IsIndex() ? aValue : pWrite->GetBestMatchingColor(aValue)); } continue; } } // here are outside pixels. Complete mask if(bWorkWithIndex) { pWrite->SetPixel(y, x, aOutside); } } } delete pRead; } delete pWrite; } } Bitmap impCreateEmptyBitmapWithPattern(const Bitmap& rSource, const Size& aTargetSizePixel) { Bitmap aRetval; BitmapReadAccess* pReadAccess = (const_cast< Bitmap& >(rSource)).AcquireReadAccess(); if(pReadAccess) { if(rSource.GetBitCount() <= 8) { BitmapPalette aPalette(pReadAccess->GetPalette()); aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount(), &aPalette); } else { aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount()); } delete pReadAccess; } return aRetval; } } // end of anonymous namespace } // end of namespace drawinglayer namespace drawinglayer { BitmapEx impTransformBitmapEx( const BitmapEx& rSource, const Rectangle& rCroppedRectPixel, const basegfx::B2DHomMatrix& rTransform) { // force destination to 24 bit, we want to smooth output const Size aDestinationSize(rCroppedRectPixel.GetSize()); Bitmap aDestination(impCreateEmptyBitmapWithPattern(rSource.GetBitmap(), aDestinationSize)); static bool bDoSmoothAtAll(true); impTransformBitmap(rSource.GetBitmap(), aDestination, rTransform, bDoSmoothAtAll); // create mask if(rSource.IsTransparent()) { if(rSource.IsAlpha()) { Bitmap aAlpha(impCreateEmptyBitmapWithPattern(rSource.GetAlpha().GetBitmap(), aDestinationSize)); impTransformBitmap(rSource.GetAlpha().GetBitmap(), aAlpha, rTransform, bDoSmoothAtAll); return BitmapEx(aDestination, AlphaMask(aAlpha)); } else { Bitmap aMask(impCreateEmptyBitmapWithPattern(rSource.GetMask(), aDestinationSize)); impTransformBitmap(rSource.GetMask(), aMask, rTransform, false); return BitmapEx(aDestination, aMask); } } return BitmapEx(aDestination); } BitmapEx impModifyBitmapEx( const basegfx::BColorModifierStack& rBColorModifierStack, const BitmapEx& rSource) { Bitmap aChangedBitmap(rSource.GetBitmap()); bool bDone(false); for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; ) { const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a); switch(rModifier.getMode()) { case basegfx::BCOLORMODIFYMODE_REPLACE : { // complete replace if(rSource.IsTransparent()) { // 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 ?!?"); if(pReadAccess) { BitmapPalette aNewPalette(pReadAccess->GetPalette()); aNewPalette[0] = BitmapColor(Color(rModifier.getBColor())); aChangedBitmap = Bitmap( aChangedBitmap.GetSizePixel(), aChangedBitmap.GetBitCount(), &aNewPalette); delete pReadAccess; } } else { aChangedBitmap.Erase(Color(rModifier.getBColor())); } } else { // erase bitmap, caller will know to paint direct aChangedBitmap.SetEmpty(); } bDone = true; break; } default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE { BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess(); if(pContent) { const double fConvertColor(1.0 / 255.0); for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++) { for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++) { const BitmapColor aBMCol(pContent->GetColor(y, x)); const basegfx::BColor aBSource( (double)aBMCol.GetRed() * fConvertColor, (double)aBMCol.GetGreen() * fConvertColor, (double)aBMCol.GetBlue() * fConvertColor); const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource)); pContent->SetPixel(y, x, BitmapColor(Color(aBDest))); } } delete pContent; } break; } } } if(aChangedBitmap.IsEmpty()) { return BitmapEx(); } else { if(rSource.IsTransparent()) { if(rSource.IsAlpha()) { return BitmapEx(aChangedBitmap, rSource.GetAlpha()); } else { return BitmapEx(aChangedBitmap, rSource.GetMask()); } } else { return BitmapEx(aChangedBitmap); } } } } // end of namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// // eof