20 #include <config_features.h>
22 #include <osl/diagnose.h>
53 const Point& rSrcPtPixel,
const Size& rSrcSizePixel,
62 const Point& rSrcPtPixel,
const Size& rSrcSizePixel,
90 Color aCol( cCmpVal, cCmpVal, cCmpVal );
119 rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
151 aBmp.
Mirror( nMirrFlags );
161 if ( nScaleX < 1.0 || nScaleY < 1.0 )
163 aBmp.
Scale(nScaleX, nScaleY);
196 bool bClipped =
false;
235 if ( aVDev->SetOutputSizePixel( aRect.
GetSize() ) )
237 if ( aVDev->mpGraphics || aVDev->AcquireGraphics() )
239 if ( (nWidth > 0) && (nHeight > 0) )
245 aVDev->mpGraphics->CopyBits(aPosAry, *
mpGraphics, *
this, *
this);
249 OSL_ENSURE(
false,
"CopyBits with zero or negative width or height");
252 aBmp = aVDev->GetBitmap(
Point(), aVDev->GetOutputSizePixel() );
263 std::shared_ptr<SalBitmap> pSalBmp =
mpGraphics->
GetBitmap( nX, nY, nWidth, nHeight, *
this );
277 const Point& rDestPt,
const Size& rDestSize,
278 const Point& rSrcPtPixel,
const Size& rSrcSizePixel )
286 const bool bHMirr = aOutSz.
Width() < 0;
287 const bool bVMirr = aOutSz.
Height() < 0;
295 aOutPt.AdjustX( -(aOutSz.
Width() - 1) );
302 aOutPt.AdjustY( -(aOutSz.
Height() - 1) );
312 rSrcPtPixel.X(), rSrcPtPixel.Y(),
314 aRelPt.X(), aRelPt.Y(),
321 bitmap.Mirror(mirrorFlags);
322 alpha.
Mirror(mirrorFlags);
324 SalBitmap* pSalSrcBmp = bitmap.ImplGetSalBitmap().get();
334 if (
SalBitmap* pSalAlphaBmp2 = aAlphaBitmap.ImplGetSalBitmap().get())
354 if (aBmpRect.Intersection(
tools::Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty())
365 bitmap.
Mirror(mirrorFlags);
366 alpha.
Mirror(mirrorFlags);
376 struct LinearScaleContext
378 std::unique_ptr<sal_Int32[]> mpMapX;
379 std::unique_ptr<sal_Int32[]> mpMapY;
381 std::unique_ptr<sal_Int32[]> mpMapXOffset;
382 std::unique_ptr<sal_Int32[]> mpMapYOffset;
387 : mpMapX(new sal_Int32[aDstRect.GetWidth()])
388 , mpMapY(new sal_Int32[aDstRect.GetHeight()])
389 , mpMapXOffset(new sal_Int32[aDstRect.GetWidth()])
390 , mpMapYOffset(new sal_Int32[aDstRect.GetHeight()])
397 aOutSize.
Width(), nOffX, mpMapX.get(), mpMapXOffset.get());
401 aOutSize.
Height(), nOffY, mpMapY.get(), mpMapYOffset.get());
410 const double fReverseScale = (std::abs(nOutDimension) > 1) ? (nSrcDimension - 1) / double(std::abs(nOutDimension) - 1) : 0.0;
416 double fTemp = std::abs((nOffset + i) * fReverseScale);
419 pMapOffset[
i] =
static_cast<tools::Long>((fTemp - pMap[
i]) * 128.0);
431 if (pSource && pSourceAlpha && pDestination)
436 switch (nSourceFormat)
444 blendBitmap24(pDestination, pSource, pSourceAlpha, nDstWidth, nDstHeight);
464 Scanline pColorSample1, pColorSample2;
467 tools::Long nColor1Line1, nColor2Line1, nColor3Line1;
468 tools::Long nColor1Line2, nColor2Line2, nColor3Line2;
471 sal_uInt8 nColor1, nColor2, nColor3, nAlpha;
480 pLine1 = (nMapY + 1 < pSource->
Height()) ? pSource->
GetScanline(nMapY + 1) : pLine0;
484 pLineAlpha1 = (nMapY + 1 < pSourceAlpha->
Height()) ? pSourceAlpha->
GetScanline(nMapY + 1) : pLineAlpha0;
493 pColorSample1 = pLine0 + 3 * nMapX;
494 pColorSample2 = (nMapX + 1 < pSource->
Width()) ? pColorSample1 + 3 : pColorSample1;
495 nColor1Line1 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
499 nColor2Line1 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
503 nColor3Line1 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
505 pColorSample1 = pLine1 + 3 * nMapX;
506 pColorSample2 = (nMapX + 1 < pSource->
Width()) ? pColorSample1 + 3 : pColorSample1;
507 nColor1Line2 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
511 nColor2Line2 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
515 nColor3Line2 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
517 pColorSample1 = pLineAlpha0 + nMapX;
518 pColorSample2 = (nMapX + 1 < pSourceAlpha->
Width()) ? pColorSample1 + 1 : pColorSample1;
519 nAlphaLine1 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
521 pColorSample1 = pLineAlpha1 + nMapX;
522 pColorSample2 = (nMapX + 1 < pSourceAlpha->
Width()) ? pColorSample1 + 1 : pColorSample1;
523 nAlphaLine2 = (
static_cast<tools::Long>(*pColorSample1) << 7) + nMapFX * (static_cast<tools::Long>(*pColorSample2) - *pColorSample1);
525 nColor1 = (nColor1Line1 + nMapFY * ((nColor1Line2 >> 7) - (nColor1Line1 >> 7))) >> 7;
526 nColor2 = (nColor2Line1 + nMapFY * ((nColor2Line2 >> 7) - (nColor2Line1 >> 7))) >> 7;
527 nColor3 = (nColor3Line1 + nMapFY * ((nColor3Line2 >> 7) - (nColor3Line1 >> 7))) >> 7;
529 nAlpha = (nAlphaLine1 + nMapFY * ((nAlphaLine2 >> 7) - (nAlphaLine1 >> 7))) >> 7;
543 struct TradScaleContext
545 std::unique_ptr<sal_Int32[]> mpMapX;
546 std::unique_ptr<sal_Int32[]> mpMapY;
551 : mpMapX(new sal_Int32[aDstRect.GetWidth()])
552 , mpMapY(new sal_Int32[aDstRect.GetHeight()])
557 const bool bHMirr = aOutSize.
Width() < 0;
558 const bool bVMirr = aOutSize.
Height() < 0;
562 aOutSize.
Width(), nOffX, bHMirr, mpMapX.get());
566 aOutSize.
Height(), nOffY, bVMirr, mpMapY.get());
577 nMirrorOffset = (nDstLocation << 1) + nSrcDimension - 1;
581 pMap[
i] = nDstLocation + nOffset * nSrcDimension / nOutDimension;
583 pMap[
i] = nMirrorOffset - pMap[
i];
598 const bool bHMirr = aOutSize.
Width() < 0;
599 const bool bVMirr = aOutSize.
Height() < 0;
604 const bool bOldMap =
mbMap;
632 : aDstRect.
Left() - aOutPoint.X();
636 TradScaleContext aTradContext(aDstRect, aBmpRect, aOutSize, nOffX, nOffY);
642 "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
652 aBmp, pBitmapReadAccess.
get(), pAlphaReadAccess.
get(),
656 aTradContext.mpMapX.get(), aTradContext.mpMapY.get() );
660 LinearScaleContext aLinearContext(aDstRect, aBmpRect, aOutSize, nOffX, nOffY);
663 nDstWidth, nDstHeight))
670 aBmp, pBitmapReadAccess.
get(), pAlphaReadAccess.
get(),
675 aTradContext.mpMapX.get(), aTradContext.mpMapY.get() );
718 bool bIsSizeValid = !rSize.
IsEmpty();
722 Image& rNonConstImage =
const_cast<Image&
>(rImage);
724 rNonConstImage.
Draw(
this, rPos, nStyle, &rSize);
726 rNonConstImage.
Draw(
this, rPos, nStyle);
737 int c = nResAlpha ? (
static_cast<int>(nSourceAlpha)*nSourceColor + static_cast<int>(nDstAlpha)*nDestColor -
738 static_cast<int>(nDstAlpha)*nDestColor*nSourceAlpha/255 ) /
static_cast<int>(nResAlpha) : 0;
752 aSrcCol = pP->
GetColor( nMapY, nMapX );
763 nResAlpha =
static_cast<int>(nSrcAlpha) + static_cast<int>(nDstAlpha) -
static_cast<int>(nDstAlpha)*nSrcAlpha/255;
765 aDstCol.
SetRed( CalcColor( aSrcCol.
GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.
GetRed() ) );
766 aDstCol.
SetBlue( CalcColor( aSrcCol.
GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.
GetBlue() ) );
785 const sal_Int32 nOffY,
786 const sal_Int32 nDstHeight,
787 const sal_Int32 nOffX,
788 const sal_Int32 nDstWidth,
789 const sal_Int32* pMapX,
790 const sal_Int32* pMapY )
798 SAL_WARN_IF( !
mpAlphaVDev,
"vcl.gdi",
"BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
813 if (pB && pP && pA && pW && pAlphaW)
817 for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
823 Scanline pScanline = pW->GetScanline(nY);
824 Scanline pScanlineAlpha = pAlphaW->GetScanline(nY);
825 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
830 aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB.
get(), pAlphaW.
get(), nResAlpha );
835 pW->SetPixelOnData( pScanline, nX, aIndex );
837 aIndex.SetIndex( static_cast<sal_uInt8>(
nVCLRLut[ (
nVCLLut[ 255-nResAlpha ] + nD ) >> 16 ] +
840 pAlphaW->SetPixelOnData( pScanlineAlpha, nX, aIndex );
851 if (pB && pP && pA && pAlphaW)
853 for( nY = 0; nY < nDstHeight; nY++ )
856 Scanline pScanlineB = pB->GetScanline(nY);
857 Scanline pScanlineAlpha = pAlphaW->GetScanline(nY);
859 for( nX = 0; nX < nDstWidth; nX++ )
862 aDstCol = AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB.
get(), pAlphaW.
get(), nResAlpha );
864 pB->SetPixelOnData(pScanlineB, nX, pB->GetBestMatchingColor(aDstCol));
865 pAlphaW->SetPixelOnData(pScanlineAlpha, nX, pB->GetBestMatchingColor(
Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha)));
884 const sal_Int32 nOffY,
885 const sal_Int32 nDstHeight,
886 const sal_Int32 nOffX,
887 const sal_Int32 nDstWidth,
892 const sal_Int32* pMapX,
893 const sal_Int32* pMapY )
906 if( pB && pP && pA && pW )
910 for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
915 nMapY = aBmpRect.
Bottom() - nMapY;
920 Scanline pScanline = pW->GetScanline(nY);
922 for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
927 nMapX = aBmpRect.
Right() - nMapX;
933 aIndex.SetIndex( static_cast<sal_uInt8>(
nVCLRLut[ (
nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16 ] +
936 pW->SetPixelOnData( pScanline, nX, aIndex );
949 bool bFastBlend =
false;
950 if( pP && pA && pB && !bHMirr && !bVMirr )
958 if( pP && pA && pB && !bFastBlend )
964 for( nY = 0; nY < nDstHeight; nY++ )
969 nMapY = aBmpRect.
Bottom() - nMapY;
973 Scanline pBScan = pB->GetScanline( nY );
975 for( nX = 0; nX < nDstWidth; nX++ )
981 nMapX = aBmpRect.
Right() - nMapX;
983 aDstCol = pB->GetPixelFromData( pBScan, nX );
985 pB->SetPixelOnData( pBScan, nX, aDstCol );
994 for( nY = 0; nY < nDstHeight; nY++ )
1000 nMapY = aBmpRect.
Bottom() - nMapY;
1003 Scanline pBScan = pB->GetScanline(nY);
1004 for( nX = 0; nX < nDstWidth; nX++ )
1010 nMapX = aBmpRect.
Right() - nMapX;
1012 aDstCol = pB->GetPixelFromData( pBScan, nX );
1013 aDstCol.
Merge( pP->
GetColor( nMapY, nMapX ), pAScan[ nMapX ] );
1014 pB->SetPixelOnData( pBScan, nX, aDstCol );
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
tools::Long Height() const
sal_uInt8 GetPixelIndex(tools::Long nY, tools::Long nX) const
bool BlendBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, const OutputDevice &rOutDev)
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
void SetBlue(sal_uInt8 nBlue)
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool HasFastDrawTransformedBitmap() const
void setWidth(tools::Long nWidth)
virtual void ClipToPaintRegion(tools::Rectangle &rDstRect)
void Merge(const Color &rMergeColor, sal_uInt8 cTransparency)
const std::shared_ptr< SalBitmap > & ImplGetSalBitmap() const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
BmpMirrorFlags AdjustTwoRect(SalTwoRect &rTwoRect, const Size &rSizePix)
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
bool IsMapModeEnabled() const
tools::Long mnOutOffY
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
SAL_DLLPRIVATE bool is_double_buffered_window() const
void EnableMapMode(bool bEnable=true)
Size GetSizePixel() const
void Draw(OutputDevice *pOutDev, const Point &rPos, DrawImageFlags nStyle, const Size *pSize=nullptr)
constexpr tools::Long Width() const
SAL_DLLPRIVATE void DrawDeviceAlphaBitmapSlowPath(const Bitmap &rBitmap, const AlphaMask &rAlpha, tools::Rectangle aDstRect, tools::Rectangle aBmpRect, Size const &aOutSz, Point const &aOutPt)
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
SAL_DLLPRIVATE tools::Long ImplLogicXToDevicePixel(tools::Long nX) const
Convert a logical X coordinate to a device pixel's X coordinate.
Scanline GetScanline(tools::Long nY) const
virtual bool CanSubsampleBitmap() const
SAL_DLLPRIVATE void BlendBitmap(const SalTwoRect &rPosAry, const Bitmap &rBmp)
void DrawBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalBitmap, const OutputDevice &rOutDev)
virtual Bitmap GetBitmap(const Point &rSrcPt, const Size &rSize) const
const sal_uLong nVCLLut[256]
sal_uInt8 GetBlue() const
bool BlendAlphaBitmap(const SalTwoRect &rPosAry, const SalBitmap &rSalSrcBitmap, const SalBitmap &rSalMaskBitmap, const SalBitmap &rSalAlphaBitmap, const OutputDevice &rOutDev)
void DrawRect(const tools::Rectangle &rRect)
SalGraphics * mpGraphics
Graphics context to draw on.
const sal_uLong nVCLBLut[6]
bool IsRTLEnabled() const
#define DBG_ASSERT(sCon, aError)
ScanlineFormat GetScanlineFormat() const
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
BitmapColor GetColor(tools::Long nY, tools::Long nX) const
tools::Long Width() const
SAL_DLLPRIVATE tools::Long ImplLogicWidthToDevicePixel(tools::Long nWidth) const
Convert a logical width to a width in units of device pixels.
SAL_DLLPRIVATE void ImplFillOpaqueRectangle(const tools::Rectangle &rRect)
Used for alpha VDev, to set areas to opaque.
void SetRed(sal_uInt8 nRed)
bool ImplFastBitmapBlending(BitmapWriteAccess const &rDstWA, const BitmapReadAccess &rSrcRA, const BitmapReadAccess &rMskRA, const SalTwoRect &rTR)
Size GetOutputSizePixel() const
virtual sal_uInt16 GetBitCount() const
void DrawBitmap(const Point &rDestPt, const Bitmap &rBitmap)
SAL_DLLPRIVATE void DrawDeviceAlphaBitmap(const Bitmap &rBmp, const AlphaMask &rAlpha, const Point &rDestPt, const Size &rDestSize, const Point &rSrcPtPixel, const Size &rSrcSizePixel)
bool DrawAlphaBitmap(const SalTwoRect &, const SalBitmap &rSourceBitmap, const SalBitmap &rAlphaBitmap, const OutputDevice &rOutDev)
void SetIndex(sal_uInt8 cIndex)
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
const sal_uLong nVCLGLut[6]
sal_uInt8 GetGreen() const
VclPtr< VirtualDevice > mpAlphaVDev
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
std::deque< AttacherIndex_Impl > aIndex
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
bool Convert(BmpConversion eConversion)
Convert bitmap format.
constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans)
void SetGreen(sal_uInt8 nGreen)
virtual void InitClipRegion()
void setHeight(tools::Long nHeight)
tools::Long mnOutOffX
Output offset for device output in pixel (pseudo window offset within window system's frames) ...
const sal_uLong nVCLRLut[6]
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
SAL_DLLPRIVATE tools::Long ImplLogicYToDevicePixel(tools::Long nY) const
Convert a logical Y coordinate to a device pixel's Y coordinate.
const sal_uLong nVCLDitherLut[256]
bool IsDeviceOutputNecessary() const
SAL_DLLPRIVATE tools::Long ImplLogicHeightToDevicePixel(tools::Long nHeight) const
Convert a logical height to a height in units of device pixels.
bool HasFastDrawTransformedBitmap() const
Return true if DrawTransformedBitmapEx() is fast.
SAL_DLLPRIVATE Bitmap BlendBitmapWithAlpha(Bitmap &aBmp, BitmapReadAccess const *pP, BitmapReadAccess const *pA, const tools::Rectangle &aDstRect, const sal_Int32 nOffY, const sal_Int32 nDstHeight, const sal_Int32 nOffX, const sal_Int32 nDstWidth, const sal_Int32 *pMapX, const sal_Int32 *pMapY)
std::shared_ptr< SalBitmap > GetBitmap(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, const OutputDevice &rOutDev)
SAL_DLLPRIVATE void ImplSetSalBitmap(const std::shared_ptr< SalBitmap > &xImpBmp)