summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/outdev2.cxx
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2014-04-13 12:03:07 +1000
committerChris Sherlock <chris.sherlock79@gmail.com>2014-04-16 07:33:49 +1000
commit13fec19b913f24723ac2373bf282e0854a6d7267 (patch)
treeeb03c2eff8a61366c77e53d2629c568a6ac48a06 /vcl/source/gdi/outdev2.cxx
parent1f742c520d0cca536d1e8f59a435b014577b7b4c (diff)
Move OutputDevice source files to vcl/source/gdi/outdev
I will be splitting out these files into OutputDevice functionality Change-Id: If04c104a49a4a0dfc53a36cb84f8f4178e9f52c8
Diffstat (limited to 'vcl/source/gdi/outdev2.cxx')
-rw-r--r--vcl/source/gdi/outdev2.cxx2228
1 files changed, 0 insertions, 2228 deletions
diff --git a/vcl/source/gdi/outdev2.cxx b/vcl/source/gdi/outdev2.cxx
deleted file mode 100644
index daf4e2c5ac8b..000000000000
--- a/vcl/source/gdi/outdev2.cxx
+++ /dev/null
@@ -1,2228 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <tools/debug.hxx>
-#include <vcl/bitmap.hxx>
-#include <vcl/bitmapex.hxx>
-#include <vcl/window.hxx>
-#include <vcl/metaact.hxx>
-#include <vcl/gdimtf.hxx>
-#include <vcl/virdev.hxx>
-#include <vcl/bmpacc.hxx>
-#include <vcl/outdev.hxx>
-#include <vcl/image.hxx>
-#include <bmpfast.hxx>
-#include <salbmp.hxx>
-#include <salgdi.hxx>
-#include <impbmp.hxx>
-#include <sallayout.hxx>
-#include <image.h>
-#include <outdev.h>
-#include <window.h>
-#include <outdata.hxx>
-#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <basegfx/matrix/b2dhommatrixtools.hxx>
-#include <boost/scoped_array.hpp>
-
-#define OUTDEV_INIT() \
-{ \
- if ( !IsDeviceOutputNecessary() ) \
- return; \
- \
- if ( !mpGraphics ) \
- if ( !ImplGetGraphics() ) \
- return; \
- \
- if ( mbInitClipRegion ) \
- ImplInitClipRegion(); \
- \
- if ( mbOutputClipped ) \
- return; \
-}
-
-extern const sal_uLong nVCLRLut[ 6 ];
-extern const sal_uLong nVCLGLut[ 6 ];
-extern const sal_uLong nVCLBLut[ 6 ];
-extern const sal_uLong nVCLDitherLut[ 256 ];
-extern const sal_uLong nVCLLut[ 256 ];
-
-sal_uLong ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix )
-{
- sal_uLong nMirrFlags = 0;
-
- if ( rTwoRect.mnDestWidth < 0 )
- {
- rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth;
- rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth;
- rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1;
- nMirrFlags |= BMP_MIRROR_HORZ;
- }
-
- if ( rTwoRect.mnDestHeight < 0 )
- {
- rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight;
- rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight;
- rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1;
- nMirrFlags |= BMP_MIRROR_VERT;
- }
-
- if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) ||
- ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) ||
- ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) ||
- ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) )
- {
- const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
- Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
- Rectangle aCropRect( aSourceRect );
-
- aCropRect.Intersection( Rectangle( Point(), rSizePix ) );
-
- if( aCropRect.IsEmpty() )
- rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
- else
- {
- const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
- const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
-
- const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
- const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
- const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
- const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
-
- rTwoRect.mnSrcX = aCropRect.Left();
- rTwoRect.mnSrcY = aCropRect.Top();
- rTwoRect.mnSrcWidth = aCropRect.GetWidth();
- rTwoRect.mnSrcHeight = aCropRect.GetHeight();
- rTwoRect.mnDestX = nDstX1;
- rTwoRect.mnDestY = nDstY1;
- rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
- rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
- }
- }
-
- return nMirrFlags;
-}
-
-void ImplAdjustTwoRect( SalTwoRect& rTwoRect, const Rectangle& rValidSrcRect )
-{
- if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) ||
- ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) ||
- ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) ||
- ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) )
- {
- const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ),
- Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) );
- Rectangle aCropRect( aSourceRect );
-
- aCropRect.Intersection( rValidSrcRect );
-
- if( aCropRect.IsEmpty() )
- rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0;
- else
- {
- const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0;
- const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0;
-
- const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) );
- const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) );
- const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) );
- const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) );
-
- rTwoRect.mnSrcX = aCropRect.Left();
- rTwoRect.mnSrcY = aCropRect.Top();
- rTwoRect.mnSrcWidth = aCropRect.GetWidth();
- rTwoRect.mnSrcHeight = aCropRect.GetHeight();
- rTwoRect.mnDestX = nDstX1;
- rTwoRect.mnDestY = nDstY1;
- rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1;
- rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1;
- }
- }
-}
-
-void OutputDevice::ImplDrawOutDevDirect( const OutputDevice* pSrcDev, SalTwoRect& rPosAry )
-{
- SalGraphics* pGraphics2;
-
- if ( this == pSrcDev )
- pGraphics2 = NULL;
- else
- {
- if ( (GetOutDevType() != pSrcDev->GetOutDevType()) ||
- (GetOutDevType() != OUTDEV_WINDOW) )
- {
- if ( !pSrcDev->mpGraphics )
- {
- if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
- return;
- }
- pGraphics2 = pSrcDev->mpGraphics;
- }
- else
- {
- if ( ((Window*)this)->mpWindowImpl->mpFrameWindow == ((Window*)pSrcDev)->mpWindowImpl->mpFrameWindow )
- pGraphics2 = NULL;
- else
- {
- if ( !pSrcDev->mpGraphics )
- {
- if ( !((OutputDevice*)pSrcDev)->ImplGetGraphics() )
- return;
- }
- pGraphics2 = pSrcDev->mpGraphics;
-
- if ( !mpGraphics )
- {
- if ( !ImplGetGraphics() )
- return;
- }
- DBG_ASSERT( mpGraphics && pSrcDev->mpGraphics,
- "OutputDevice::DrawOutDev(): We need more than one Graphics" );
- }
- }
- }
-
- // #102532# Offset only has to be pseudo window offset
- const Rectangle aSrcOutRect( Point( pSrcDev->mnOutOffX, pSrcDev->mnOutOffY ),
- Size( pSrcDev->mnOutWidth, pSrcDev->mnOutHeight ) );
-
- ImplAdjustTwoRect( rPosAry, aSrcOutRect );
-
- if ( rPosAry.mnSrcWidth && rPosAry.mnSrcHeight && rPosAry.mnDestWidth && rPosAry.mnDestHeight )
- {
- // --- RTL --- if this is no window, but pSrcDev is a window
- // mirroring may be required
- // because only windows have a SalGraphicsLayout
- // mirroring is performed here
- if( (GetOutDevType() != OUTDEV_WINDOW) && pGraphics2 && (pGraphics2->GetLayout() & SAL_LAYOUT_BIDI_RTL) )
- {
- SalTwoRect aPosAry2 = rPosAry;
- pGraphics2->mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcDev );
- mpGraphics->CopyBits( aPosAry2, pGraphics2, this, pSrcDev );
- }
- else
- mpGraphics->CopyBits( rPosAry, pGraphics2, this, pSrcDev );
- }
-}
-
-void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPt, const Size& rSrcSize )
-{
- if( ImplIsRecordLayout() )
- return;
-
- if ( ROP_INVERT == meRasterOp )
- {
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- return;
- }
-
- if ( mpMetaFile )
- {
- const Bitmap aBmp( GetBitmap( rSrcPt, rSrcSize ) );
- mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
- }
-
- OUTDEV_INIT();
-
- SalTwoRect aPosAry;
- aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
- aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
- aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
- aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
-
- const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
- Size( mnOutWidth, mnOutHeight ) );
-
- ImplAdjustTwoRect( aPosAry, aSrcOutRect );
-
- if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- mpGraphics->CopyBits( aPosAry, NULL, this, NULL );
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawOutDev( rDestPt, rDestSize, rSrcPt, rSrcSize );
-}
-
-void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPt, const Size& rSrcSize,
- const OutputDevice& rOutDev )
-{
- if ( ImplIsRecordLayout() )
- return;
-
- if ( ROP_INVERT == meRasterOp )
- {
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- return;
- }
-
- if ( mpMetaFile )
- {
- const Bitmap aBmp( rOutDev.GetBitmap( rSrcPt, rSrcSize ) );
- mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
- }
-
- OUTDEV_INIT();
-
- SalTwoRect aPosAry;
- aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
- aPosAry.mnSrcY = rOutDev.ImplLogicYToDevicePixel( rSrcPt.Y() );
- aPosAry.mnSrcWidth = rOutDev.ImplLogicWidthToDevicePixel( rSrcSize.Width() );
- aPosAry.mnSrcHeight = rOutDev.ImplLogicHeightToDevicePixel( rSrcSize.Height() );
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- if( mpAlphaVDev )
- {
- if( rOutDev.mpAlphaVDev )
- {
- // alpha-blend source over destination
- DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
- }
- else
- {
- ImplDrawOutDevDirect( &rOutDev, aPosAry );
-
- // #i32109#: make destination rectangle opaque - source has no alpha
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
- }
- }
- else
- {
- if( rOutDev.mpAlphaVDev )
- {
- // alpha-blend source over destination
- DrawBitmapEx( rDestPt, rDestSize, rOutDev.GetBitmapEx(rSrcPt, rSrcSize) );
- }
- else
- {
- // no alpha at all, neither in source nor destination device
- ImplDrawOutDevDirect( &rOutDev, aPosAry );
- }
- }
-}
-
-void OutputDevice::CopyArea( const Point& rDestPt,
- const Point& rSrcPt, const Size& rSrcSize,
- sal_uInt16 nFlags )
-{
- if ( ImplIsRecordLayout() )
- return;
-
- RasterOp eOldRop = GetRasterOp();
- SetRasterOp( ROP_OVERPAINT );
-
- OUTDEV_INIT();
-
- SalTwoRect aPosAry;
- aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
- aPosAry.mnSrcHeight = ImplLogicHeightToDevicePixel( rSrcSize.Height() );
-
- if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight )
- {
- aPosAry.mnSrcX = ImplLogicXToDevicePixel( rSrcPt.X() );
- aPosAry.mnSrcY = ImplLogicYToDevicePixel( rSrcPt.Y() );
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
- aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
-
- const Rectangle aSrcOutRect( Point( mnOutOffX, mnOutOffY ),
- Size( mnOutWidth, mnOutHeight ) );
-
- ImplAdjustTwoRect( aPosAry, aSrcOutRect );
-
- CopyAreaFinal ( aPosAry, nFlags );
- }
-
- SetRasterOp( eOldRop );
-
- if( mpAlphaVDev )
- mpAlphaVDev->CopyArea( rDestPt, rSrcPt, rSrcSize, nFlags );
-}
-
-void OutputDevice::CopyAreaFinal( SalTwoRect& aPosAry, sal_uInt32 /*nFlags*/)
-{
- if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
- return;
-
- aPosAry.mnDestWidth = aPosAry.mnSrcWidth;
- aPosAry.mnDestHeight = aPosAry.mnSrcHeight;
- mpGraphics->CopyBits(aPosAry, NULL, this, NULL);
-}
-
-void OutputDevice::ImplDrawFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
- const OutputDevice& rOutDev, const Region& rRegion )
-{
-
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- bool bOldMap = mbMap;
- RasterOp eOldROP = GetRasterOp();
- mpMetaFile = NULL;
- mbMap = false;
- SetRasterOp( ROP_OVERPAINT );
-
- if ( !IsDeviceOutputNecessary() )
- return;
-
- if ( !mpGraphics )
- {
- if ( !ImplGetGraphics() )
- return;
- }
-
- // ClipRegion zuruecksetzen
- if ( rRegion.IsNull() )
- mpGraphics->ResetClipRegion();
- else
- ImplSelectClipRegion( rRegion );
-
- SalTwoRect aPosAry;
- aPosAry.mnSrcX = rDevPt.X();
- aPosAry.mnSrcY = rDevPt.Y();
- aPosAry.mnSrcWidth = rDevSize.Width();
- aPosAry.mnSrcHeight = rDevSize.Height();
- aPosAry.mnDestX = rPt.X();
- aPosAry.mnDestY = rPt.Y();
- aPosAry.mnDestWidth = rDevSize.Width();
- aPosAry.mnDestHeight = rDevSize.Height();
- ImplDrawOutDevDirect( &rOutDev, aPosAry );
-
- // Ensure that ClipRegion is recalculated and set
- mbInitClipRegion = true;
-
- SetRasterOp( eOldROP );
- mbMap = bOldMap;
- mpMetaFile = pOldMetaFile;
-}
-
-void OutputDevice::ImplGetFrameDev( const Point& rPt, const Point& rDevPt, const Size& rDevSize,
- OutputDevice& rDev )
-{
-
- bool bOldMap = mbMap;
- mbMap = false;
- rDev.DrawOutDev( rDevPt, rDevSize, rPt, rDevSize, *this );
- mbMap = bOldMap;
-}
-
-void OutputDevice::DrawBitmap( const Point& rDestPt, const Bitmap& rBitmap )
-{
- if( ImplIsRecordLayout() )
- return;
-
- const Size aSizePix( rBitmap.GetSizePixel() );
- ImplDrawBitmap( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, META_BMP_ACTION );
-
- if( mpAlphaVDev )
- {
- // #i32109#: Make bitmap area opaque
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, PixelToLogic( aSizePix )) );
- }
-}
-
-void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize, const Bitmap& rBitmap )
-{
- if( ImplIsRecordLayout() )
- return;
-
- ImplDrawBitmap( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, META_BMPSCALE_ACTION );
-
- if( mpAlphaVDev )
- {
- // #i32109#: Make bitmap area opaque
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
- }
-}
-
-void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- const Bitmap& rBitmap )
-{
- if( ImplIsRecordLayout() )
- return;
-
- ImplDrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmap, META_BMPSCALEPART_ACTION );
-
- if( mpAlphaVDev )
- {
- // #i32109#: Make bitmap area opaque
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
- }
-}
-
-void OutputDevice::ImplDrawBitmap( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- const Bitmap& rBitmap, const sal_uLong nAction )
-{
-
- if ( ( mnDrawMode & DRAWMODE_NOBITMAP ) )
- {
- return;
- }
- if ( ROP_INVERT == meRasterOp )
- {
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- return;
- }
-
- Bitmap aBmp( rBitmap );
-
- if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
- DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
- {
- if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
- {
- sal_uInt8 cCmpVal;
-
- if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
- cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
- else
- cCmpVal = 255;
-
- Color aCol( cCmpVal, cCmpVal, cCmpVal );
- Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
- SetLineColor( aCol );
- SetFillColor( aCol );
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- Pop();
- return;
- }
- else if( !!aBmp )
- {
- if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
- aBmp.Convert( BMP_CONVERSION_8BIT_GREYS );
-
- if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
- aBmp.Convert( BMP_CONVERSION_GHOSTED );
- }
- }
-
- if ( mpMetaFile )
- {
- switch( nAction )
- {
- case( META_BMP_ACTION ):
- mpMetaFile->AddAction( new MetaBmpAction( rDestPt, aBmp ) );
- break;
-
- case( META_BMPSCALE_ACTION ):
- mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
- break;
-
- case( META_BMPSCALEPART_ACTION ):
- mpMetaFile->AddAction( new MetaBmpScalePartAction(
- rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmp ) );
- break;
- }
- }
-
- OUTDEV_INIT();
-
- if( !aBmp.IsEmpty() )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = rSrcPtPixel.X();
- aPosAry.mnSrcY = rSrcPtPixel.Y();
- aPosAry.mnSrcWidth = rSrcSizePixel.Width();
- aPosAry.mnSrcHeight = rSrcSizePixel.Height();
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
- const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, aBmp.GetSizePixel() );
-
- if ( nMirrFlags )
- aBmp.Mirror( nMirrFlags );
-
- if ( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
- if ( nAction == META_BMPSCALE_ACTION )
- ScaleBitmap (aBmp, aPosAry);
-
- mpGraphics->DrawBitmap( aPosAry, *aBmp.ImplGetImpBitmap()->ImplGetSalBitmap(), this );
- }
- }
- }
-}
-
-void OutputDevice::ScaleBitmap (Bitmap &rBmp, SalTwoRect &rPosAry)
-{
- const double nScaleX = rPosAry.mnDestWidth / static_cast<double>( rPosAry.mnSrcWidth );
- const double nScaleY = rPosAry.mnDestHeight / static_cast<double>( rPosAry.mnSrcHeight );
-
- // If subsampling, use Bitmap::Scale for subsampling for better quality.
- if ( nScaleX < 1.0 || nScaleY < 1.0 )
- {
- rBmp.Scale ( nScaleX, nScaleY );
- rPosAry.mnSrcWidth = rPosAry.mnDestWidth;
- rPosAry.mnSrcHeight = rPosAry.mnDestHeight;
- }
-}
-
-void OutputDevice::DrawBitmapEx( const Point& rDestPt,
- const BitmapEx& rBitmapEx )
-{
- if( ImplIsRecordLayout() )
- return;
-
- if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
- {
- DrawBitmap( rDestPt, rBitmapEx.GetBitmap() );
- }
- else
- {
- const Size aSizePix( rBitmapEx.GetSizePixel() );
- ImplDrawBitmapEx( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmapEx, META_BMPEX_ACTION );
- }
-}
-
-void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
- const BitmapEx& rBitmapEx )
-{
- if( ImplIsRecordLayout() )
- return;
-
- if ( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
- {
- DrawBitmap( rDestPt, rDestSize, rBitmapEx.GetBitmap() );
- }
- else
- {
- ImplDrawBitmapEx( rDestPt, rDestSize, Point(), rBitmapEx.GetSizePixel(), rBitmapEx, META_BMPEXSCALE_ACTION );
- }
-}
-
-void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- const BitmapEx& rBitmapEx )
-{
- if( ImplIsRecordLayout() )
- return;
-
- if( TRANSPARENT_NONE == rBitmapEx.GetTransparentType() )
- {
- DrawBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx.GetBitmap() );
- }
- else
- {
- ImplDrawBitmapEx( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, rBitmapEx, META_BMPEXSCALEPART_ACTION );
- }
-}
-
-bool OutputDevice::DrawTransformBitmapExDirect(
- const basegfx::B2DHomMatrix& aFullTransform,
- const BitmapEx& rBitmapEx)
-{
- bool bDone = false;
-
- // try to paint directly
- const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0));
- const basegfx::B2DPoint aTopX(aFullTransform * basegfx::B2DPoint(1.0, 0.0));
- const basegfx::B2DPoint aTopY(aFullTransform * basegfx::B2DPoint(0.0, 1.0));
- SalBitmap* pSalSrcBmp = rBitmapEx.GetBitmap().ImplGetImpBitmap()->ImplGetSalBitmap();
- SalBitmap* pSalAlphaBmp = 0;
-
- if(rBitmapEx.IsTransparent())
- {
- if(rBitmapEx.IsAlpha())
- {
- pSalAlphaBmp = rBitmapEx.GetAlpha().ImplGetImpBitmap()->ImplGetSalBitmap();
- }
- else
- {
- pSalAlphaBmp = rBitmapEx.GetMask().ImplGetImpBitmap()->ImplGetSalBitmap();
- }
- }
-
- bDone = mpGraphics->DrawTransformedBitmap(
- aNull,
- aTopX,
- aTopY,
- *pSalSrcBmp,
- pSalAlphaBmp,
- this);
-
- return bDone;
-};
-
-bool OutputDevice::TransformReduceBitmapExTargetRange(
- const basegfx::B2DHomMatrix& aFullTransform,
- basegfx::B2DRange &aVisibleRange,
- double &fMaximumArea)
-{
- // 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 false;
- }
-
- // 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 false;
- }
-
- // 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 false;
- }
-
- // 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);
-
- return true;
-}
-
-void OutputDevice::DrawTransformedBitmapEx(
- const basegfx::B2DHomMatrix& rTransformation,
- const BitmapEx& rBitmapEx)
-{
- if( ImplIsRecordLayout() )
- return;
-
- if(rBitmapEx.IsEmpty())
- return;
-
- if ( mnDrawMode & DRAWMODE_NOBITMAP )
- return;
-
- // decompose matrix to check rotation and shear
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
- const bool bRotated(!basegfx::fTools::equalZero(fRotate));
- 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(!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
- // #i124580# the correct DestSize needs to be calculated based on MaxXY values
- const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
- const Size aDestSize(
- basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
- basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
-
- DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
- return;
- }
-
- // we have rotation,shear or mirror, check if some crazy mode needs the
- // created transformed bitmap
- const bool bInvert(ROP_INVERT == meRasterOp);
- const bool bBitmapChangedColor(mnDrawMode & (DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP | DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP));
- const bool bMetafile(mpMetaFile);
- bool bDone(false);
- const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
- const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile );
-
- if(!bForceToOwnTransformer && bTryDirectPaint)
- {
- bDone = DrawTransformBitmapExDirect(aFullTransform, rBitmapEx);
- }
-
- if(!bDone)
- {
- // take the fallback when no rotate and shear, but mirror (else we would have done this above)
- 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
- // #i124580# the correct DestSize needs to be calculated based on MaxXY values
- const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
- const Size aDestSize(
- basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
- basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
-
- DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
- return;
- }
-
- // fallback; create transformed bitmap the hard way (back-transform
- // the pixels) and paint
- 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)
- {
- if ( !TransformReduceBitmapExTargetRange( aFullTransform, aVisibleRange, fMaximumArea ) )
- return;
- }
-
- 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) || defined(IOS)
- 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
- // #i124580# the correct DestSize needs to be calculated based on MaxXY values
- const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
- const Size aDestSize(
- basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(),
- basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y());
-
- DrawBitmapEx(aDestPt, aDestSize, aTransformed);
- }
- }
-}
-
-void OutputDevice::ImplDrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- const BitmapEx& rBitmapEx, const sal_uLong nAction )
-{
- OSL_ENSURE(TRANSPARENT_NONE != rBitmapEx.GetTransparentType(), "ImplDrawBitmapEx not needed, no transparency in BitmapEx (!)");
-
- if ( mnDrawMode & DRAWMODE_NOBITMAP )
- return;
-
- if ( ROP_INVERT == meRasterOp )
- {
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- return;
- }
-
- BitmapEx aBmpEx( rBitmapEx );
-
- if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP |
- DRAWMODE_GRAYBITMAP | DRAWMODE_GHOSTEDBITMAP ) )
- {
- if ( mnDrawMode & ( DRAWMODE_BLACKBITMAP | DRAWMODE_WHITEBITMAP ) )
- {
- Bitmap aColorBmp( aBmpEx.GetSizePixel(), ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 4 : 1 );
- sal_uInt8 cCmpVal;
-
- if ( mnDrawMode & DRAWMODE_BLACKBITMAP )
- cCmpVal = ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP ) ? 0x80 : 0;
- else
- cCmpVal = 255;
-
- aColorBmp.Erase( Color( cCmpVal, cCmpVal, cCmpVal ) );
-
- if( aBmpEx.IsAlpha() )
- {
- // Create one-bit mask out of alpha channel, by
- // thresholding it at alpha=0.5. As
- // DRAWMODE_BLACK/WHITEBITMAP requires monochrome
- // output, having alpha-induced grey levels is not
- // acceptable.
- Bitmap aMask( aBmpEx.GetAlpha().GetBitmap() );
- aMask.MakeMono( 129 );
- aBmpEx = BitmapEx( aColorBmp, aMask );
- }
- else
- {
- aBmpEx = BitmapEx( aColorBmp, aBmpEx.GetMask() );
- }
- }
- else if( !!aBmpEx )
- {
- if ( mnDrawMode & DRAWMODE_GRAYBITMAP )
- aBmpEx.Convert( BMP_CONVERSION_8BIT_GREYS );
-
- if ( mnDrawMode & DRAWMODE_GHOSTEDBITMAP )
- aBmpEx.Convert( BMP_CONVERSION_GHOSTED );
- }
- }
-
- if ( mpMetaFile )
- {
- switch( nAction )
- {
- case( META_BMPEX_ACTION ):
- mpMetaFile->AddAction( new MetaBmpExAction( rDestPt, aBmpEx ) );
- break;
-
- case( META_BMPEXSCALE_ACTION ):
- mpMetaFile->AddAction( new MetaBmpExScaleAction( rDestPt, rDestSize, aBmpEx ) );
- break;
-
- case( META_BMPEXSCALEPART_ACTION ):
- mpMetaFile->AddAction( new MetaBmpExScalePartAction( rDestPt, rDestSize,
- rSrcPtPixel, rSrcSizePixel, aBmpEx ) );
- break;
- }
- }
-
- OUTDEV_INIT();
-
- DrawDeviceBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmpEx );
-}
-
-void OutputDevice::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- BitmapEx& rBmpEx )
-{
- if(rBmpEx.IsAlpha())
- {
- Size aDestSizePixel(LogicToPixel(rDestSize));
-
- BitmapEx aScaledBitmapEx(rBmpEx);
- Point aSrcPtPixel(rSrcPtPixel);
- Size aSrcSizePixel(rSrcSizePixel);
-
- // we have beautiful scaling algorithms, let's use them
- if (aDestSizePixel != rSrcSizePixel && rSrcSizePixel.Width() != 0 && rSrcSizePixel.Height() != 0)
- {
- double fScaleX = double(aDestSizePixel.Width()) / rSrcSizePixel.Width();
- double fScaleY = double(aDestSizePixel.Height()) / rSrcSizePixel.Height();
-
- aScaledBitmapEx.Scale(fScaleX, fScaleY);
-
- aSrcSizePixel = aDestSizePixel;
- aSrcPtPixel.X() = rSrcPtPixel.X() * fScaleX;
- aSrcPtPixel.Y() = rSrcPtPixel.Y() * fScaleY;
- }
- ImplDrawAlpha(aScaledBitmapEx.GetBitmap(), aScaledBitmapEx.GetAlpha(), rDestPt, rDestSize, aSrcPtPixel, aSrcSizePixel);
- return;
- }
-
- if( !( !rBmpEx ) )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = rSrcPtPixel.X();
- aPosAry.mnSrcY = rSrcPtPixel.Y();
- aPosAry.mnSrcWidth = rSrcSizePixel.Width();
- aPosAry.mnSrcHeight = rSrcSizePixel.Height();
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, rBmpEx.GetSizePixel() );
-
- if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
-
- if( nMirrFlags )
- rBmpEx.Mirror( nMirrFlags );
-
- const SalBitmap* pSalSrcBmp = rBmpEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
- const ImpBitmap* pMaskBmp = rBmpEx.ImplGetMaskImpBitmap();
-
- if ( pMaskBmp )
- {
- SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap();
- bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp);
-
- if(bTryDirectPaint)
- {
- // only paint direct when no scaling and no MapMode, else the
- // more expensive conversions may be done for short-time Bitmap/BitmapEx
- // used for buffering only
- if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight)
- {
- bTryDirectPaint = false;
- }
- }
-
- if(bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this))
- {
- // tried to paint as alpha directly. If tis worked, we are done (except
- // alpha, see below)
- }
- else
- {
- // #4919452# reduce operation area to bounds of
- // cliprect. since masked transparency involves
- // creation of a large vdev and copying the screen
- // content into that (slooow read from framebuffer),
- // that should considerably increase performance for
- // large bitmaps and small clippings.
-
- // Note that this optimization is a workaround for a
- // Writer peculiarity, namely, to decompose background
- // graphics into myriads of disjunct, tiny
- // rectangles. That otherwise kills us here, since for
- // transparent output, SAL always prepares the whole
- // bitmap, if aPosAry contains the whole bitmap (and
- // it's _not_ to blame for that).
-
- // Note the call to ImplPixelToDevicePixel(), since
- // aPosAry already contains the mnOutOff-offsets, they
- // also have to be applied to the region
- Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
-
- // TODO: Also respect scaling (that's a bit tricky,
- // since the source points have to move fractional
- // amounts (which is not possible, thus has to be
- // emulated by increases copy area)
- // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
- // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
-
- // for now, only identity scales allowed
- if( !aClipRegionBounds.IsEmpty() &&
- aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
- aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
- {
- // now intersect dest rect with clip region
- aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
- aPosAry.mnDestY,
- aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
- aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
-
- // Note: I could theoretically optimize away the
- // DrawBitmap below, if the region is empty
- // here. Unfortunately, cannot rule out that
- // somebody relies on the side effects.
- if( !aClipRegionBounds.IsEmpty() )
- {
- aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
- aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
- aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
- aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
-
- aPosAry.mnDestX = aClipRegionBounds.Left();
- aPosAry.mnDestY = aClipRegionBounds.Top();
- aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
- aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
- }
- }
-
- mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp,
- *pMaskBmp->ImplGetSalBitmap(),
- this );
- }
-
- // #110958# Paint mask to alpha channel. Luckily, the
- // black and white representation of the mask maps to
- // the alpha channel
-
- // #i25167# Restrict mask painting to _opaque_ areas
- // of the mask, otherwise we spoil areas where no
- // bitmap content was ever visible. Interestingly
- // enough, this can be achieved by taking the mask as
- // the transparency mask of itself
- if( mpAlphaVDev )
- mpAlphaVDev->DrawBitmapEx( rDestPt,
- rDestSize,
- BitmapEx( rBmpEx.GetMask(),
- rBmpEx.GetMask() ) );
- }
- else
- {
- mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, this );
-
- if( mpAlphaVDev )
- {
- // #i32109#: Make bitmap area opaque
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
- }
- }
- }
- }
-}
-
-void OutputDevice::DrawMask( const Point& rDestPt,
- const Bitmap& rBitmap, const Color& rMaskColor )
-{
- const Size aSizePix( rBitmap.GetSizePixel() );
- DrawMask( rDestPt, PixelToLogic( aSizePix ), Point(), aSizePix, rBitmap, rMaskColor, META_MASK_ACTION );
-}
-
-void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
- const Bitmap& rBitmap, const Color& rMaskColor )
-{
- DrawMask( rDestPt, rDestSize, Point(), rBitmap.GetSizePixel(), rBitmap, rMaskColor, META_MASKSCALE_ACTION );
-}
-
-void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- const Bitmap& rBitmap, const Color& rMaskColor,
- const sal_uLong nAction )
-{
- if( ImplIsRecordLayout() )
- return;
-
- if( ROP_INVERT == meRasterOp )
- {
- DrawRect( Rectangle( rDestPt, rDestSize ) );
- return;
- }
-
- if ( mpMetaFile )
- {
- switch( nAction )
- {
- case( META_MASK_ACTION ):
- mpMetaFile->AddAction( new MetaMaskAction( rDestPt,
- rBitmap, rMaskColor ) );
- break;
-
- case( META_MASKSCALE_ACTION ):
- mpMetaFile->AddAction( new MetaMaskScaleAction( rDestPt,
- rDestSize, rBitmap, rMaskColor ) );
- break;
-
- case( META_MASKSCALEPART_ACTION ):
- mpMetaFile->AddAction( new MetaMaskScalePartAction( rDestPt, rDestSize,
- rSrcPtPixel, rSrcSizePixel, rBitmap, rMaskColor ) );
- break;
- }
- }
-
- OUTDEV_INIT();
-
- if ( OUTDEV_PRINTER == meOutDevType )
- {
- ImplPrintMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
- return;
- }
-
- const ImpBitmap* pImpBmp = rBitmap.ImplGetImpBitmap();
- if ( pImpBmp )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = rSrcPtPixel.X();
- aPosAry.mnSrcY = rSrcPtPixel.Y();
- aPosAry.mnSrcWidth = rSrcSizePixel.Width();
- aPosAry.mnSrcHeight = rSrcSizePixel.Height();
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- // we don't want to mirror via cooridates
- const sal_uLong nMirrFlags = ImplAdjustTwoRect( aPosAry, pImpBmp->ImplGetSize() );
-
- // check if output is necessary
- if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
-
- if( nMirrFlags )
- {
- Bitmap aTmp( rBitmap );
- aTmp.Mirror( nMirrFlags );
- mpGraphics->DrawMask( aPosAry, *aTmp.ImplGetImpBitmap()->ImplGetSalBitmap(),
- ImplColorToSal( rMaskColor ) , this);
- }
- else
- mpGraphics->DrawMask( aPosAry, *pImpBmp->ImplGetSalBitmap(),
- ImplColorToSal( rMaskColor ), this );
-
- }
- }
-
- // TODO: Use mask here
- if( mpAlphaVDev )
- {
- const Bitmap& rMask( rBitmap.CreateMask( rMaskColor ) );
-
- // #i25167# Restrict mask painting to _opaque_ areas
- // of the mask, otherwise we spoil areas where no
- // bitmap content was ever visible. Interestingly
- // enough, this can be achieved by taking the mask as
- // the transparency mask of itself
- mpAlphaVDev->DrawBitmapEx( rDestPt,
- rDestSize,
- rSrcPtPixel,
- rSrcSizePixel,
- BitmapEx( rMask, rMask ) );
- }
-}
-
-namespace
-{
- BitmapEx makeDisabledBitmap(const Bitmap &rBitmap)
- {
- const Size aTotalSize( rBitmap.GetSizePixel() );
- Bitmap aGrey( aTotalSize, 8, &Bitmap::GetGreyPalette( 256 ) );
- AlphaMask aGreyAlphaMask( aTotalSize );
- BitmapReadAccess* pBmp = const_cast<Bitmap&>(rBitmap).AcquireReadAccess();
- BitmapWriteAccess* pGrey = aGrey.AcquireWriteAccess();
- BitmapWriteAccess* pGreyAlphaMask = aGreyAlphaMask.AcquireWriteAccess();
-
- if( pBmp && pGrey && pGreyAlphaMask )
- {
- BitmapColor aGreyVal( 0 );
- BitmapColor aGreyAlphaMaskVal( 0 );
- const int nLeft = 0, nRight = aTotalSize.Width();
- const int nTop = 0, nBottom = nTop + aTotalSize.Height();
-
- for( int nY = nTop; nY < nBottom; ++nY )
- {
- for( int nX = nLeft; nX < nRight; ++nX )
- {
- aGreyVal.SetIndex( pBmp->GetLuminance( nY, nX ) );
- pGrey->SetPixel( nY, nX, aGreyVal );
-
- aGreyAlphaMaskVal.SetIndex( static_cast< sal_uInt8 >( 128ul ) );
- pGreyAlphaMask->SetPixel( nY, nX, aGreyAlphaMaskVal );
- }
- }
- }
-
- const_cast<Bitmap&>(rBitmap).ReleaseAccess( pBmp );
- aGrey.ReleaseAccess( pGrey );
- aGreyAlphaMask.ReleaseAccess( pGreyAlphaMask );
- return BitmapEx( aGrey, aGreyAlphaMask );
- }
-}
-
-void OutputDevice::DrawImage( const Point& rPos, const Image& rImage, sal_uInt16 nStyle )
-{
- DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
-
- if( !rImage.mpImplData || ImplIsRecordLayout() )
- return;
-
- switch( rImage.mpImplData->meType )
- {
- case IMAGETYPE_BITMAP:
- {
- const Bitmap &rBitmap = *static_cast< Bitmap* >( rImage.mpImplData->mpData );
- if( nStyle & IMAGE_DRAW_DISABLE )
- DrawBitmapEx( rPos, makeDisabledBitmap(rBitmap) );
- else
- DrawBitmap( rPos, rBitmap );
- }
- break;
-
- case IMAGETYPE_IMAGE:
- {
- ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
-
- if( !pData->mpImageBitmap )
- {
- const Size aSize( pData->maBmpEx.GetSizePixel() );
-
- pData->mpImageBitmap = new ImplImageBmp;
- pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
- }
-
- pData->mpImageBitmap->Draw( 0, this, rPos, nStyle );
- }
- break;
-
- default:
- break;
- }
-}
-
-void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
- const Image& rImage, sal_uInt16 nStyle )
-{
- DBG_ASSERT( GetOutDevType() != OUTDEV_PRINTER, "DrawImage(): Images can't be drawn on any mprinter" );
-
- if( rImage.mpImplData && !ImplIsRecordLayout() )
- {
- switch( rImage.mpImplData->meType )
- {
- case IMAGETYPE_BITMAP:
- {
- const Bitmap &rBitmap = *static_cast< Bitmap* >( rImage.mpImplData->mpData );
- if( nStyle & IMAGE_DRAW_DISABLE )
- DrawBitmapEx( rPos, rSize, makeDisabledBitmap(rBitmap) );
- else
- DrawBitmap( rPos, rSize, rBitmap );
- }
- break;
-
- case IMAGETYPE_IMAGE:
- {
- ImplImageData* pData = static_cast< ImplImageData* >( rImage.mpImplData->mpData );
-
- if ( !pData->mpImageBitmap )
- {
- const Size aSize( pData->maBmpEx.GetSizePixel() );
-
- pData->mpImageBitmap = new ImplImageBmp;
- pData->mpImageBitmap->Create( pData->maBmpEx, aSize.Width(), aSize.Height(), 1 );
- }
-
- pData->mpImageBitmap->Draw( 0, this, rPos, nStyle, &rSize );
- }
- break;
-
- default:
- break;
- }
- }
-}
-
-Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
-{
- OSL_ENSURE(OUTDEV_PRINTER != GetOutDevType(), "OutputDevice::GetBitmap with sorce type OUTDEV_PRINTER should not be used (!)");
-
- Bitmap aBmp;
- long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
- long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
- long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
- long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
-
- if ( mpGraphics || ( (OutputDevice*) this )->ImplGetGraphics() )
- {
- if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
- {
- Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
- bool bClipped = false;
-
- // X-Coordinate outside of draw area?
- if ( nX < mnOutOffX )
- {
- nWidth -= ( mnOutOffX - nX );
- nX = mnOutOffX;
- bClipped = true;
- }
-
- // Y-Coordinate outside of draw area?
- if ( nY < mnOutOffY )
- {
- nHeight -= ( mnOutOffY - nY );
- nY = mnOutOffY;
- bClipped = true;
- }
-
- // Width outside of draw area?
- if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
- {
- nWidth = mnOutOffX + mnOutWidth - nX;
- bClipped = true;
- }
-
- // Height outside of draw area?
- if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
- {
- nHeight = mnOutOffY + mnOutHeight - nY;
- bClipped = true;
- }
-
- if ( bClipped )
- {
- // If the visible part has been clipped, we have to create a
- // Bitmap with the correct size in which we copy the clipped
- // Bitmap to the correct position.
- VirtualDevice aVDev( *this );
-
- if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
- {
- if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->ImplGetGraphics() )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = nX;
- aPosAry.mnSrcY = nY;
- aPosAry.mnSrcWidth = nWidth;
- aPosAry.mnSrcHeight = nHeight;
- aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
- aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
- aPosAry.mnDestWidth = nWidth;
- aPosAry.mnDestHeight = nHeight;
-
- if ( (nWidth > 0) && (nHeight > 0) )
- {
- (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this );
- }
- else
- {
- OSL_ENSURE(false, "CopyBits with negative width or height (!)");
- }
-
- aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
- }
- else
- bClipped = false;
- }
- else
- bClipped = false;
- }
-
- if ( !bClipped )
- {
- SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
-
- if( pSalBmp )
- {
- ImpBitmap* pImpBmp = new ImpBitmap;
- pImpBmp->ImplSetSalBitmap( pSalBmp );
- aBmp.ImplSetImpBitmap( pImpBmp );
- }
- }
- }
- }
-
- return aBmp;
-}
-
-BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
-{
-
- // #110958# Extract alpha value from VDev, if any
- if( mpAlphaVDev )
- {
- Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
-
- // ensure 8 bit alpha
- if( aAlphaBitmap.GetBitCount() > 8 )
- aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
-
- return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
- }
- else
- return GetBitmap( rSrcPt, rSize );
-}
-
-Color OutputDevice::GetPixel( const Point& rPt ) const
-{
-
- Color aColor;
-
- if ( mpGraphics || ((OutputDevice*)this)->ImplGetGraphics() )
- {
- if ( mbInitClipRegion )
- ((OutputDevice*)this)->ImplInitClipRegion();
-
- if ( !mbOutputClipped )
- {
- const long nX = ImplLogicXToDevicePixel( rPt.X() );
- const long nY = ImplLogicYToDevicePixel( rPt.Y() );
- const SalColor aSalCol = mpGraphics->GetPixel( nX, nY, this );
- aColor.SetRed( SALCOLOR_RED( aSalCol ) );
- aColor.SetGreen( SALCOLOR_GREEN( aSalCol ) );
- aColor.SetBlue( SALCOLOR_BLUE( aSalCol ) );
- }
- }
- return aColor;
-}
-
-void OutputDevice::DrawPixel( const Point& rPt )
-{
-
- if ( mpMetaFile )
- mpMetaFile->AddAction( new MetaPointAction( rPt ) );
-
- if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() )
- return;
-
- Point aPt = ImplLogicToDevicePixel( rPt );
-
- if ( !mpGraphics )
- {
- if ( !ImplGetGraphics() )
- return;
- }
-
- if ( mbInitClipRegion )
- ImplInitClipRegion();
- if ( mbOutputClipped )
- return;
-
- if ( mbInitLineColor )
- ImplInitLineColor();
-
- mpGraphics->DrawPixel( aPt.X(), aPt.Y(), this );
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawPixel( rPt );
-}
-
-void OutputDevice::DrawPixel( const Point& rPt, const Color& rColor )
-{
-
- Color aColor = ImplDrawModeToColor( rColor );
-
- if ( mpMetaFile )
- mpMetaFile->AddAction( new MetaPixelAction( rPt, aColor ) );
-
- if ( !IsDeviceOutputNecessary() || ImplIsColorTransparent( aColor ) || ImplIsRecordLayout() )
- return;
-
- Point aPt = ImplLogicToDevicePixel( rPt );
-
- if ( !mpGraphics )
- {
- if ( !ImplGetGraphics() )
- return;
- }
-
- if ( mbInitClipRegion )
- ImplInitClipRegion();
- if ( mbOutputClipped )
- return;
-
- mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( aColor ), this );
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawPixel( rPt );
-}
-
-void OutputDevice::DrawPixel( const Polygon& rPts, const Color* pColors )
-{
- if ( !pColors )
- DrawPixel( rPts, GetLineColor() );
- else
- {
- DBG_ASSERT( pColors, "OutputDevice::DrawPixel: No color array specified" );
-
- const sal_uInt16 nSize = rPts.GetSize();
-
- if ( nSize )
- {
- if ( mpMetaFile )
- for ( sal_uInt16 i = 0; i < nSize; i++ )
- mpMetaFile->AddAction( new MetaPixelAction( rPts[ i ], pColors[ i ] ) );
-
- if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
- return;
-
- if ( mpGraphics || ImplGetGraphics() )
- {
- if ( mbInitClipRegion )
- ImplInitClipRegion();
-
- if ( mbOutputClipped )
- return;
-
- for ( sal_uInt16 i = 0; i < nSize; i++ )
- {
- const Point aPt( ImplLogicToDevicePixel( rPts[ i ] ) );
- mpGraphics->DrawPixel( aPt.X(), aPt.Y(), ImplColorToSal( pColors[ i ] ), this );
- }
- }
- }
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawPixel( rPts, pColors );
-}
-
-void OutputDevice::DrawPixel( const Polygon& rPts, const Color& rColor )
-{
- if( rColor != COL_TRANSPARENT && ! ImplIsRecordLayout() )
- {
- const sal_uInt16 nSize = rPts.GetSize();
- boost::scoped_array<Color> pColArray(new Color[ nSize ]);
-
- for( sal_uInt16 i = 0; i < nSize; i++ )
- pColArray[ i ] = rColor;
-
- DrawPixel( rPts, pColArray.get() );
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawPixel( rPts, rColor );
-}
-
-namespace
-{
- // Co = Cs + Cd*(1-As) premultiplied alpha -or-
- // Co = (AsCs + AdCd*(1-As)) / Ao
- inline sal_uInt8 lcl_calcColor( const sal_uInt8 nSourceColor, const sal_uInt8 nSourceAlpha,
- const sal_uInt8 nDstAlpha, const sal_uInt8 nResAlpha, const sal_uInt8 nDestColor )
- {
- int c = nResAlpha ? ( (int)nSourceAlpha*nSourceColor + (int)nDstAlpha*nDestColor -
- (int)nDstAlpha*nDestColor*nSourceAlpha/255 ) / (int)nResAlpha : 0;
- return sal_uInt8( c );
- }
-
-inline BitmapColor lcl_AlphaBlend( int nX, int nY,
- const long nMapX,
- const long nMapY,
- BitmapReadAccess* pP,
- BitmapReadAccess* pA,
- BitmapReadAccess* pB,
- BitmapWriteAccess* pAlphaW,
- sal_uInt8& nResAlpha )
-{
- BitmapColor aDstCol,aSrcCol;
- aSrcCol = pP->GetColor( nMapY, nMapX );
- aDstCol = pB->GetColor( nY, nX );
-
- // vcl stores transparency, not alpha - invert it
- const sal_uInt8 nSrcAlpha = 255 - pA->GetPixelIndex( nMapY, nMapX );
- const sal_uInt8 nDstAlpha = 255 - pAlphaW->GetPixelIndex( nY, nX );
-
- // Perform porter-duff compositing 'over' operation
-
- // Co = Cs + Cd*(1-As)
- // Ad = As + Ad*(1-As)
- nResAlpha = (int)nSrcAlpha + (int)nDstAlpha - (int)nDstAlpha*nSrcAlpha/255;
-
- aDstCol.SetRed( lcl_calcColor( aSrcCol.GetRed(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetRed() ) );
- aDstCol.SetBlue( lcl_calcColor( aSrcCol.GetBlue(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetBlue() ) );
- aDstCol.SetGreen( lcl_calcColor( aSrcCol.GetGreen(), nSrcAlpha, nDstAlpha, nResAlpha, aDstCol.GetGreen() ) );
-
- return aDstCol;
-}
-}
-
-Bitmap OutputDevice::ImplBlendWithAlpha( Bitmap aBmp,
- BitmapReadAccess* pP,
- BitmapReadAccess* pA,
- const Rectangle& aDstRect,
- const sal_Int32 nOffY,
- const sal_Int32 nDstHeight,
- const sal_Int32 nOffX,
- const sal_Int32 nDstWidth,
- const long* pMapX,
- const long* pMapY )
-{
- BitmapColor aDstCol;
- Bitmap res;
- int nX, nY;
- sal_uInt8 nResAlpha;
-
- OSL_ENSURE(mpAlphaVDev,
- "ImplBlendWithAlpha(): call me only with valid alpha VDev!" );
-
- bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
- mpAlphaVDev->EnableMapMode(false);
-
- Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
- BitmapWriteAccess* pAlphaW = aAlphaBitmap.AcquireWriteAccess();
-
- if( GetBitCount() <= 8 )
- {
- Bitmap aDither( aBmp.GetSizePixel(), 8 );
- BitmapColor aIndex( 0 );
- BitmapReadAccess* pB = aBmp.AcquireReadAccess();
- BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
-
- if( pB && pP && pA && pW && pAlphaW )
- {
- int nOutY;
-
- for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
- {
- const long nMapY = pMapY[ nY ];
- const long nModY = ( nOutY & 0x0FL ) << 4L;
- int nOutX;
-
- for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
- {
- const long nMapX = pMapX[ nX ];
- const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
-
- aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
-
- aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
- nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
- nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
- pW->SetPixel( nY, nX, aIndex );
-
- aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
- nVCLGLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] +
- nVCLBLut[ ( nVCLLut[ 255-nResAlpha ] + nD ) >> 16UL ] ) );
- pAlphaW->SetPixel( nY, nX, aIndex );
- }
- }
- }
-
- aBmp.ReleaseAccess( pB );
- aDither.ReleaseAccess( pW );
- res = aDither;
- }
- else
- {
- BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
- if( pP && pA && pB )
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- aDstCol = lcl_AlphaBlend( nX, nY, nMapX, nMapY, pP, pA, pB, pAlphaW, nResAlpha );
-
- pB->SetPixel( nY, nX, aDstCol );
- pAlphaW->SetPixel( nY, nX, Color(255L-nResAlpha, 255L-nResAlpha, 255L-nResAlpha) );
- }
- }
- }
-
- aBmp.ReleaseAccess( pB );
- res = aBmp;
- }
-
- aAlphaBitmap.ReleaseAccess( pAlphaW );
- mpAlphaVDev->DrawBitmap( aDstRect.TopLeft(), aAlphaBitmap );
- mpAlphaVDev->EnableMapMode( bOldMapMode );
-
- return res;
-}
-
-Bitmap OutputDevice::ImplBlend( Bitmap aBmp,
- BitmapReadAccess* pP,
- BitmapReadAccess* pA,
- const sal_Int32 nOffY,
- const sal_Int32 nDstHeight,
- const sal_Int32 nOffX,
- const sal_Int32 nDstWidth,
- const Rectangle& aBmpRect,
- const Size& aOutSz,
- const bool bHMirr,
- const bool bVMirr,
- const long* pMapX,
- const long* pMapY )
-{
- BitmapColor aDstCol;
- Bitmap res;
- int nX, nY;
-
- if( GetBitCount() <= 8 )
- {
- Bitmap aDither( aBmp.GetSizePixel(), 8 );
- BitmapColor aIndex( 0 );
- BitmapReadAccess* pB = aBmp.AcquireReadAccess();
- BitmapWriteAccess* pW = aDither.AcquireWriteAccess();
-
- if( pB && pP && pA && pW )
- {
- int nOutY;
-
- for( nY = 0, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
- {
- const long nMapY = pMapY[ nY ];
- const long nModY = ( nOutY & 0x0FL ) << 4L;
- int nOutX;
-
- for( nX = 0, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
- {
- const long nMapX = pMapX[ nX ];
- const sal_uLong nD = nVCLDitherLut[ nModY | ( nOutX & 0x0FL ) ];
-
- aDstCol = pB->GetColor( nY, nX );
- aDstCol.Merge( pP->GetColor( nMapY, nMapX ), pA->GetPixelIndex( nMapY, nMapX ) );
- aIndex.SetIndex( (sal_uInt8) ( nVCLRLut[ ( nVCLLut[ aDstCol.GetRed() ] + nD ) >> 16UL ] +
- nVCLGLut[ ( nVCLLut[ aDstCol.GetGreen() ] + nD ) >> 16UL ] +
- nVCLBLut[ ( nVCLLut[ aDstCol.GetBlue() ] + nD ) >> 16UL ] ) );
- pW->SetPixel( nY, nX, aIndex );
- }
- }
- }
-
- aBmp.ReleaseAccess( pB );
- aDither.ReleaseAccess( pW );
- res = aDither;
- }
- else
- {
- BitmapWriteAccess* pB = aBmp.AcquireWriteAccess();
-
- bool bFastBlend = false;
- if( pP && pA && pB )
- {
- SalTwoRect aTR;
- aTR.mnSrcX = aBmpRect.Left();
- aTR.mnSrcY = aBmpRect.Top();
- aTR.mnSrcWidth = aBmpRect.GetWidth();
- aTR.mnSrcHeight = aBmpRect.GetHeight();
- aTR.mnDestX = nOffX;
- aTR.mnDestY = nOffY;
- aTR.mnDestWidth = aOutSz.Width();
- aTR.mnDestHeight= aOutSz.Height();
-
- if( !bHMirr && !bVMirr )
- bFastBlend = ImplFastBitmapBlending( *pB,*pP,*pA, aTR );
- }
-
- if( pP && pA && pB && !bFastBlend )
- {
- switch( pP->GetScanlineFormat() )
- {
- case( BMP_FORMAT_8BIT_PAL ):
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pPScan = pP->GetScanline( nMapY );
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetPaletteColor( pPScan[ nMapX ] ),
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
-
- case( BMP_FORMAT_24BIT_TC_BGR ):
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pPScan = pP->GetScanline( nMapY );
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- Scanline pTmp = pPScan + nMapX * 3;
-
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
-
- case( BMP_FORMAT_24BIT_TC_RGB ):
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pPScan = pP->GetScanline( nMapY );
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- Scanline pTmp = pPScan + nMapX * 3;
-
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
-
- default:
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pP->GetColor( nMapY, nMapX ),
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
- }
- }
-
- aBmp.ReleaseAccess( pB );
- res = aBmp;
- }
-
- return res;
-}
-
-void OutputDevice::ClipToPaintRegion(Rectangle& /*rDstRect*/)
-{
-}
-
-void OutputDevice::ImplDrawAlpha( const Bitmap& rBmp, const AlphaMask& rAlpha,
- const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel )
-{
- const Point aNullPt;
- Point aOutPt( LogicToPixel( rDestPt ) );
- Size aOutSz( LogicToPixel( rDestSize ) );
- Rectangle aDstRect( aNullPt, GetOutputSizePixel() );
- const bool bHMirr = aOutSz.Width() < 0;
- const bool bVMirr = aOutSz.Height() < 0;
-
- ClipToPaintRegion(aDstRect);
-
- if( bHMirr )
- {
- aOutSz.Width() = -aOutSz.Width();
- aOutPt.X() -= ( aOutSz.Width() - 1L );
- }
-
- if( bVMirr )
- {
- aOutSz.Height() = -aOutSz.Height();
- aOutPt.Y() -= ( aOutSz.Height() - 1L );
- }
-
- if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
- {
- bool bNativeAlpha = false;
- static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
- // #i83087# Naturally, system alpha blending cannot work with
- // separate alpha VDev
- bool bTryDirectPaint(!mpAlphaVDev && !pDisableNative && !bHMirr && !bVMirr);
-
-#ifdef WNT
- if(bTryDirectPaint)
- {
- // only paint direct when no scaling and no MapMode, else the
- // more expensive conversions may be done for short-time Bitmap/BitmapEx
- // used for buffering only
- if(!IsMapMode() && rSrcSizePixel.Width() == aOutSz.Width() && rSrcSizePixel.Height() == aOutSz.Height())
- {
- bTryDirectPaint = false;
- }
- }
-#endif
-
- if(bTryDirectPaint)
- {
- Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
- SalTwoRect aTR = {
- rSrcPtPixel.X(), rSrcPtPixel.Y(),
- rSrcSizePixel.Width(), rSrcSizePixel.Height(),
- aRelPt.X(), aRelPt.Y(),
- aOutSz.Width(), aOutSz.Height()
- };
- SalBitmap* pSalSrcBmp = rBmp.ImplGetImpBitmap()->ImplGetSalBitmap();
- SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
- bNativeAlpha = mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this );
- }
-
- VirtualDevice* pOldVDev = mpAlphaVDev;
-
- Rectangle aBmpRect( aNullPt, rBmp.GetSizePixel() );
- if( !bNativeAlpha
- && !aBmpRect.Intersection( Rectangle( rSrcPtPixel, rSrcSizePixel ) ).IsEmpty() )
- {
- // The scaling in this code path produces really ugly results - it
- // does the most trivial scaling with no smoothing.
-
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- const bool bOldMap = mbMap;
- mpMetaFile = NULL; // fdo#55044 reset before GetBitmap!
- mbMap = false;
- Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
-
- // #109044# The generated bitmap need not necessarily be
- // of aDstRect dimensions, it's internally clipped to
- // window bounds. Thus, we correct the dest size here,
- // since we later use it (in nDstWidth/Height) for pixel
- // access)
- // #i38887# reading from screen may sometimes fail
- if( aBmp.ImplGetImpBitmap() )
- aDstRect.SetSize( aBmp.GetSizePixel() );
-
- BitmapColor aDstCol;
- const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
- const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
- const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
- // calculate offset in original bitmap
- // in RTL case this is a little more complicated since the contents of the
- // bitmap is not mirrored (it never is), however the paint region and bmp region
- // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
- // is content wise somewhere else and needs to take mirroring into account
- const long nOffX = IsRTLEnabled()
- ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
- : aDstRect.Left() - aOutPt.X(),
- nOffY = aDstRect.Top() - aOutPt.Y();
- long nX, nOutX, nY, nOutY;
- long nMirrOffX = 0;
- long nMirrOffY = 0;
- boost::scoped_array<long> pMapX(new long[ nDstWidth ]);
- boost::scoped_array<long> pMapY(new long[ nDstHeight ]);
-
- // create horizontal mapping table
- if( bHMirr )
- nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
-
- for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
- {
- pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
- if( bHMirr )
- pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
- }
-
- // create vertical mapping table
- if( bVMirr )
- nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
-
- for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
- {
- pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
-
- if( bVMirr )
- pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
- }
-
- BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
- BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
-
- DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
- pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
- "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
-
- // #i38887# reading from screen may sometimes fail
- if( aBmp.ImplGetImpBitmap() )
- {
- Bitmap aTmp;
-
- if( mpAlphaVDev )
- {
- aTmp = ImplBlendWithAlpha(
- aBmp,pP,pA,
- aDstRect,
- nOffY,nDstHeight,
- nOffX,nDstWidth,
- pMapX.get(),pMapY.get() );
- }
- else
- {
- aTmp = ImplBlend(
- aBmp,pP,pA,
- nOffY,nDstHeight,
- nOffX,nDstWidth,
- aBmpRect,aOutSz,
- bHMirr,bVMirr,
- pMapX.get(),pMapY.get() );
- }
-
- // #110958# Disable alpha VDev, we're doing the necessary
- // stuff explicitly furher below
- if( mpAlphaVDev )
- mpAlphaVDev = NULL;
-
- DrawBitmap( aDstRect.TopLeft(),
- aTmp );
-
- // #110958# Enable alpha VDev again
- mpAlphaVDev = pOldVDev;
- }
-
- ( (Bitmap&) rBmp ).ReleaseAccess( pP );
- ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
-
- mbMap = bOldMap;
- mpMetaFile = pOldMetaFile;
- }
- }
-}
-
-void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
- const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel )
-{
- Point aPt;
- Point aDestPt( LogicToPixel( rDestPt ) );
- Size aDestSz( LogicToPixel( rDestSize ) );
- Rectangle aSrcRect( rSrcPtPixel, rSrcSizePixel );
-
- aSrcRect.Justify();
-
- if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
- {
- Bitmap aPaint( rBmp ), aMask( rMask );
- sal_uLong nMirrFlags = 0UL;
-
- if( aMask.GetBitCount() > 1 )
- aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
-
- // mirrored horizontically
- if( aDestSz.Width() < 0L )
- {
- aDestSz.Width() = -aDestSz.Width();
- aDestPt.X() -= ( aDestSz.Width() - 1L );
- nMirrFlags |= BMP_MIRROR_HORZ;
- }
-
- // mirrored vertically
- if( aDestSz.Height() < 0L )
- {
- aDestSz.Height() = -aDestSz.Height();
- aDestPt.Y() -= ( aDestSz.Height() - 1L );
- nMirrFlags |= BMP_MIRROR_VERT;
- }
-
- // source cropped?
- if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
- {
- aPaint.Crop( aSrcRect );
- aMask.Crop( aSrcRect );
- }
-
- // destination mirrored
- if( nMirrFlags )
- {
- aPaint.Mirror( nMirrFlags );
- aMask.Mirror( nMirrFlags );
- }
-
- // we always want to have a mask
- if( aMask.IsEmpty() )
- {
- aMask = Bitmap( aSrcRect.GetSize(), 1 );
- aMask.Erase( Color( COL_BLACK ) );
- }
-
- // do painting
- const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
- long nX, nY; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
- boost::scoped_array<long> pMapX(new long[ nSrcWidth + 1 ]);
- boost::scoped_array<long> pMapY(new long[ nSrcHeight + 1 ]);
- const bool bOldMap = mbMap;
-
- mbMap = false;
-
- // create forward mapping tables
- for( nX = 0L; nX <= nSrcWidth; nX++ )
- pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
-
- for( nY = 0L; nY <= nSrcHeight; nY++ )
- pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
-
- // walk through all rectangles of mask
- const Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
- RectangleVector aRectangles;
- aWorkRgn.GetRegionRectangles(aRectangles);
-
- for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
- {
- const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
- const Size aMapSz(
- pMapX[aRectIter->Right() + 1] - aMapPt.X(), // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
- pMapY[aRectIter->Bottom() + 1] - aMapPt.Y()); // same for Y
- Bitmap aBandBmp(aPaint);
-
- aBandBmp.Crop(*aRectIter);
- ImplDrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION);
- }
-
- mbMap = bOldMap;
- }
-}
-
-void OutputDevice::ImplPrintMask( const Bitmap& /*rMask*/, const Color& /*rMaskColor*/,
- const Point& /*rDestPt*/, const Size& /*rDestSize*/,
- const Point& /*rSrcPtPixel*/, const Size& /*rSrcSizePixel*/ )
-{
- // let's leave this for Printer
- return;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */