summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2014-04-15 01:06:48 +1000
committerChris Sherlock <chris.sherlock79@gmail.com>2014-04-16 07:33:58 +1000
commitaa5b97fa3d8970813c3fd7c9fc88cd38db80482e (patch)
tree8879d79e105e6e71230feba9bc850331ab53744a
parentd92ee5d8bebdd6f120c7478127a1be5f78d4b1af (diff)
Split outdev5.cxx and outdev6.cxx
outdev5.cxx deals with curved shapes, so renamed to curvedshapes.cxx Moved polygon functions to polygon.cxx, transparency functions to transparent.cxx, a few miscellaneous functions to outdev.cxx and as the rest of the functions are wallpaper functions then renamed outdev6.cxx to wallpaper.cxx Change-Id: I62a0b66d4d66740fb5f70ecb558db1ad3bf76eb5
-rw-r--r--vcl/Library_vcl.mk6
-rw-r--r--vcl/source/outdev/curvedshapes.cxx (renamed from vcl/source/outdev/outdev5.cxx)0
-rw-r--r--vcl/source/outdev/outdev.cxx118
-rw-r--r--vcl/source/outdev/outdev6.cxx1196
-rw-r--r--vcl/source/outdev/polygon.cxx94
-rw-r--r--vcl/source/outdev/transparent.cxx603
-rw-r--r--vcl/source/outdev/wallpaper.cxx384
7 files changed, 1202 insertions, 1199 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index b1fd7e8d52fe..6851f0cc8b65 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -234,6 +234,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/gdi/metric \
vcl/source/gdi/octree \
vcl/source/gdi/oldprintadaptor \
+ vcl/source/outdev/outdev \
vcl/source/outdev/tworect \
vcl/source/outdev/bezier \
vcl/source/outdev/polygon \
@@ -250,9 +251,8 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/outdev/polyline \
vcl/source/outdev/hatch \
vcl/source/outdev/gradient \
- vcl/source/outdev/outdev5 \
- vcl/source/outdev/outdev6 \
- vcl/source/outdev/outdev \
+ vcl/source/outdev/curvedshapes \
+ vcl/source/outdev/wallpaper \
vcl/source/outdev/outdevnative \
vcl/source/outdev/outmap \
vcl/source/gdi/pdfextoutdevdata \
diff --git a/vcl/source/outdev/outdev5.cxx b/vcl/source/outdev/curvedshapes.cxx
index 7fe7e684db58..7fe7e684db58 100644
--- a/vcl/source/outdev/outdev5.cxx
+++ b/vcl/source/outdev/curvedshapes.cxx
diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx
index 25d8992e3927..cba75421b4e4 100644
--- a/vcl/source/outdev/outdev.cxx
+++ b/vcl/source/outdev/outdev.cxx
@@ -1576,4 +1576,122 @@ css::uno::Reference< css::rendering::XCanvas > OutputDevice::GetCanvas() const
return xCanvas;
}
+void OutputDevice::Erase()
+{
+ if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
+ return;
+
+ bool bNativeOK = false;
+
+ if( meOutDevType == OUTDEV_WINDOW )
+ {
+ Window* pWindow = static_cast<Window*>(this);
+ ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground;
+ if( aCtrlPart != 0 && ! pWindow->IsControlBackground() )
+ {
+ ImplControlValue aControlValue;
+ Point aGcc3WorkaroundTemporary;
+ Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() );
+ ControlState nState = 0;
+
+ if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED;
+ bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
+ nState, aControlValue, OUString() );
+ }
+ }
+
+ if ( mbBackground && ! bNativeOK )
+ {
+ RasterOp eRasterOp = GetRasterOp();
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( ROP_OVERPAINT );
+ ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
+ if ( eRasterOp != ROP_OVERPAINT )
+ SetRasterOp( eRasterOp );
+ }
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->Erase();
+}
+
+bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
+ const GfxLink& rGfxLink, GDIMetaFile* pSubst )
+{
+ bool bDrawn(true);
+
+ if ( mpMetaFile )
+ {
+ GDIMetaFile aSubst;
+
+ if( pSubst )
+ aSubst = *pSubst;
+
+ mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
+ }
+
+ if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
+ return bDrawn;
+
+ if( mbOutputClipped )
+ return bDrawn;
+
+ Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
+
+ if( !aRect.IsEmpty() )
+ {
+ // draw the real EPS graphics
+ if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
+ {
+ if( !mpGraphics && !ImplGetGraphics() )
+ return bDrawn;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ aRect.Justify();
+ bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this );
+ }
+
+ // else draw the substitution graphics
+ if( !bDrawn && pSubst )
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+
+ mpMetaFile = NULL;
+ Graphic( *pSubst ).Draw( this, rPoint, rSize );
+ mpMetaFile = pOldMetaFile;
+ }
+ }
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
+
+ return bDrawn;
+}
+
+void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd)
+{
+ const sal_uInt32 nMaxX(rPos.X() + rSize.Width());
+ const sal_uInt32 nMaxY(rPos.Y() + rSize.Height());
+
+ Push(PUSH_LINECOLOR|PUSH_FILLCOLOR);
+ SetLineColor();
+
+ for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen)
+ {
+ const sal_uInt32 nRight(std::min(nMaxX, nX + nLen));
+
+ for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen)
+ {
+ const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen));
+
+ SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd);
+ DrawRect(Rectangle(nX, nY, nRight, nBottom));
+ }
+ }
+
+ Pop();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/outdev6.cxx b/vcl/source/outdev/outdev6.cxx
deleted file mode 100644
index b4de152f6ad4..000000000000
--- a/vcl/source/outdev/outdev6.cxx
+++ /dev/null
@@ -1,1196 +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/outdev.hxx>
-#include <vcl/virdev.hxx>
-#include <vcl/bmpacc.hxx>
-#include <vcl/metaact.hxx>
-#include <vcl/gdimtf.hxx>
-#include <vcl/svapp.hxx>
-#include <vcl/wrkwin.hxx>
-#include <vcl/graph.hxx>
-
-#include <wall2.hxx>
-#include <salgdi.hxx>
-#include <window.h>
-#include <svdata.hxx>
-#include <outdev.h>
-
-#include <com/sun/star/uno/Sequence.hxx>
-
-#include <basegfx/vector/b2dvector.hxx>
-#include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <basegfx/polygon/b2dpolygon.hxx>
-#include <basegfx/matrix/b2dhommatrix.hxx>
-
-#include <math.h>
-#include <boost/scoped_ptr.hpp>
-
-namespace {
-
-/**
- * Perform a safe approximation of a polygon from double-precision
- * coordinates to integer coordinates, to ensure that it has at least 2
- * pixels in both X and Y directions.
- */
-Polygon toPolygon( const basegfx::B2DPolygon& rPoly )
-{
- basegfx::B2DRange aRange = rPoly.getB2DRange();
- double fW = aRange.getWidth(), fH = aRange.getHeight();
- if (0.0 < fW && 0.0 < fH && (fW <= 1.0 || fH <= 1.0))
- {
- // This polygon not empty but is too small to display. Approximate it
- // with a rectangle large enough to be displayed.
- double nX = aRange.getMinX(), nY = aRange.getMinY();
- double nW = std::max<double>(1.0, rtl::math::round(fW));
- double nH = std::max<double>(1.0, rtl::math::round(fH));
-
- Polygon aTarget;
- aTarget.Insert(0, Point(nX, nY));
- aTarget.Insert(1, Point(nX+nW, nY));
- aTarget.Insert(2, Point(nX+nW, nY+nH));
- aTarget.Insert(3, Point(nX, nY+nH));
- aTarget.Insert(4, Point(nX, nY));
- return aTarget;
- }
- return Polygon(rPoly);
-}
-
-PolyPolygon toPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly )
-{
- PolyPolygon aTarget;
- for (sal_uInt32 i = 0; i < rPolyPoly.count(); ++i)
- aTarget.Insert(toPolygon(rPolyPoly.getB2DPolygon(i)));
-
- return aTarget;
-}
-
-}
-
-void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags )
-{
-
- Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
- aDstRect.Intersection( rRect );
-
- if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
- return;
-
- if( !mpGraphics && !ImplGetGraphics() )
- return;
-
- if( mbInitClipRegion )
- ImplInitClipRegion();
-
- if( mbOutputClipped )
- return;
-
- const long nDistX = std::max( rDist.Width(), 1L );
- const long nDistY = std::max( rDist.Height(), 1L );
- long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
- long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
- const long nRight = aDstRect.Right();
- const long nBottom = aDstRect.Bottom();
- const long nStartX = ImplLogicXToDevicePixel( nX );
- const long nEndX = ImplLogicXToDevicePixel( nRight );
- const long nStartY = ImplLogicYToDevicePixel( nY );
- const long nEndY = ImplLogicYToDevicePixel( nBottom );
- long nHorzCount = 0L;
- long nVertCount = 0L;
-
- ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
- ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
-
- if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
- {
- aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
- aVertBuf[ nVertCount++ ] = nStartY;
- while( ( nY += nDistY ) <= nBottom )
- aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
- }
-
- if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
- {
- aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
- aHorzBuf[ nHorzCount++ ] = nStartX;
- while( ( nX += nDistX ) <= nRight )
- aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
- }
-
- if( mbInitLineColor )
- ImplInitLineColor();
-
- if( mbInitFillColor )
- ImplInitFillColor();
-
- const bool bOldMap = mbMap;
- EnableMapMode( false );
-
- if( nFlags & GRID_DOTS )
- {
- for( long i = 0L; i < nVertCount; i++ )
- for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
- mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
- }
- else
- {
- if( nFlags & GRID_HORZLINES )
- {
- for( long i = 0L; i < nVertCount; i++ )
- {
- nY = aVertBuf[ i ];
- mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
- }
- }
-
- if( nFlags & GRID_VERTLINES )
- {
- for( long i = 0L; i < nHorzCount; i++ )
- {
- nX = aHorzBuf[ i ];
- mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
- }
- }
- }
-
- EnableMapMode( bOldMap );
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
-}
-
-// Caution: This method is nearly the same as
-// void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
-// so when changes are made here do not forget to make changes there, too
-
-void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
-{
- // AW: Do NOT paint empty PolyPolygons
- if(!rB2DPolyPoly.count())
- return;
-
- // we need a graphics
- if( !mpGraphics )
- if( !ImplGetGraphics() )
- return;
-
- if( mbInitClipRegion )
- ImplInitClipRegion();
- if( mbOutputClipped )
- return;
-
- if( mbInitLineColor )
- ImplInitLineColor();
- if( mbInitFillColor )
- ImplInitFillColor();
-
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
- && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
- && ROP_OVERPAINT == GetRasterOp() )
- {
- // b2dpolygon support not implemented yet on non-UNX platforms
- const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
-
- // transform the polygon into device space and ensure it is closed
- aB2DPolyPolygon.transform( aTransform );
- aB2DPolyPolygon.setClosed( true );
-
- bool bDrawnOk = true;
- if( IsFillColor() )
- bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
- if( bDrawnOk && IsLineColor() )
- {
- const basegfx::B2DVector aHairlineWidth(1,1);
- const int nPolyCount = aB2DPolyPolygon.count();
- for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
- {
- const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
- mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
- }
- }
-
- if( bDrawnOk )
- {
- if( mpMetaFile )
- mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
- return;
- }
- }
-
- // fallback to old polygon drawing if needed
- DrawTransparent(toPolyPolygon(rB2DPolyPoly), static_cast<sal_uInt16>(fTransparency * 100.0));
-}
-
-void OutputDevice::DrawInvisiblePolygon( const PolyPolygon& rPolyPoly )
-{
- // short circuit if the polygon border is invisible too
- if( !mbLineColor )
- return;
-
- // we assume that the border is NOT to be drawn transparently???
- Push( PUSH_FILLCOLOR );
- SetFillColor();
- DrawPolyPolygon( rPolyPoly );
- Pop();
-}
-
-bool OutputDevice::DrawTransparentNatively ( const PolyPolygon& rPolyPoly,
- sal_uInt16 nTransparencePercent )
-{
- bool bDrawn = false;
-
- // debug helper:
- static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
-
- if( !pDisableNative
- && mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
-#if defined UNX && ! defined MACOSX && ! defined IOS
- && GetBitCount() > 8
-#endif
-#ifdef WIN32
- // workaround bad dithering on remote displaying when using GDI+ with toolbar button highlighting
- && !rPolyPoly.IsRect()
-#endif
- )
- {
- // prepare the graphics device
- if( mbInitClipRegion )
- ImplInitClipRegion();
- if( mbOutputClipped )
- return false;
- if( mbInitLineColor )
- ImplInitLineColor();
- if( mbInitFillColor )
- ImplInitFillColor();
-
- // get the polygon in device coordinates
- basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
- const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyPolygon.transform( aTransform );
-
- const double fTransparency = 0.01 * nTransparencePercent;
- if( mbFillColor )
- {
- // #i121591#
- // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
- // should be used when printing. Normally this is avoided by the printer being
- // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
- // to figure out a way of moving this code to it's own function that is
- // overriden by the Print class, which will mean we deliberately override the
- // functionality and we use the fallback some lines below (which is not very good,
- // though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
- // correct the wrong mapping (see there for details)
- bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
- }
-
- if( mbLineColor )
- {
- // disable the fill color for now
- mpGraphics->SetFillColor();
- // draw the border line
- const basegfx::B2DVector aLineWidths( 1, 1 );
- const int nPolyCount = aB2DPolyPolygon.count();
- for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
- {
- const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
- bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
- }
- // prepare to restore the fill color
- mbInitFillColor = mbFillColor;
- }
- }
-
- return bDrawn;
-}
-
-void OutputDevice::EmulateDrawTransparent ( const PolyPolygon& rPolyPoly,
- sal_uInt16 nTransparencePercent )
-{
- // debug helper:
- static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
-
- // #110958# Disable alpha VDev, we perform the necessary
- VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
-
- // operation explicitly further below.
- if( mpAlphaVDev )
- mpAlphaVDev = NULL;
-
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- mpMetaFile = NULL;
-
- PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
- Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
- Point aPoint;
- Rectangle aDstRect( aPoint, GetOutputSizePixel() );
-
- aDstRect.Intersection( aPolyRect );
-
- ClipToPaintRegion( aDstRect );
-
- if( !aDstRect.IsEmpty() )
- {
- bool bDrawn = false;
-
- // #i66849# Added fast path for exactly rectangular
- // polygons
- // #i83087# Naturally, system alpha blending cannot
- // work with separate alpha VDev
- if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
- {
- // setup Graphics only here (other cases delegate
- // to basic OutDev methods)
- if ( mbInitClipRegion )
- ImplInitClipRegion();
- if ( mbInitLineColor )
- ImplInitLineColor();
- if ( mbInitFillColor )
- ImplInitFillColor();
-
- Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
- Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
-
- if( !mbOutputClipped )
- {
- bDrawn = mpGraphics->DrawAlphaRect(
- aPixelRect.Left(), aPixelRect.Top(),
- // #i98405# use methods with small g, else one pixel too much will be painted.
- // This is because the source is a polygon which when painted would not paint
- // the rightmost and lowest pixel line(s), so use one pixel less for the
- // rectangle, too.
- aPixelRect.getWidth(), aPixelRect.getHeight(),
- sal::static_int_cast<sal_uInt8>(nTransparencePercent),
- this );
- }
- else
- bDrawn = true;
- }
-
- if( !bDrawn )
- {
- VirtualDevice aVDev( *this, 1 );
- const Size aDstSz( aDstRect.GetSize() );
- const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
-
- if( aDstRect.Left() || aDstRect.Top() )
- aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
-
- if( aVDev.SetOutputSizePixel( aDstSz ) )
- {
- const bool bOldMap = mbMap;
-
- EnableMapMode( false );
-
- aVDev.SetLineColor( COL_BLACK );
- aVDev.SetFillColor( COL_BLACK );
- aVDev.DrawPolyPolygon( aPolyPoly );
-
- Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
- Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
-
- // #107766# check for non-empty bitmaps before accessing them
- if( !!aPaint && !!aPolyMask )
- {
- BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
- BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
-
- if( pW && pR )
- {
- BitmapColor aPixCol;
- const BitmapColor aFillCol( GetFillColor() );
- const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
- const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
- const long nWidth = pW->Width(), nHeight = pW->Height();
- const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
- long nX, nY;
-
- if( aPaint.GetBitCount() <= 8 )
- {
- const BitmapPalette& rPal = pW->GetPalette();
- const sal_uInt16 nCount = rPal.GetEntryCount();
- BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ];
-
- for( sal_uInt16 i = 0; i < nCount; i++ )
- {
- BitmapColor aCol( rPal[ i ] );
- pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
- }
-
- if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
- pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
- {
- const sal_uInt8 cBlack = aBlack.GetIndex();
-
- for( nY = 0; nY < nHeight; nY++ )
- {
- Scanline pWScan = pW->GetScanline( nY );
- Scanline pRScan = pR->GetScanline( nY );
- sal_uInt8 cBit = 128;
-
- for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
- {
- if( !cBit )
- cBit = 128, pRScan++;
-
- if( ( *pRScan & cBit ) == cBlack )
- *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex();
- }
- }
- }
- else
- {
- for( nY = 0; nY < nHeight; nY++ )
- for( nX = 0; nX < nWidth; nX++ )
- if( pR->GetPixel( nY, nX ) == aBlack )
- pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
- }
-
- delete[] (sal_uInt8*) pMap;
- }
- else
- {
- if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
- pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
- {
- const sal_uInt8 cBlack = aBlack.GetIndex();
-
- for( nY = 0; nY < nHeight; nY++ )
- {
- Scanline pWScan = pW->GetScanline( nY );
- Scanline pRScan = pR->GetScanline( nY );
- sal_uInt8 cBit = 128;
-
- for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
- {
- if( !cBit )
- cBit = 128, pRScan++;
-
- if( ( *pRScan & cBit ) == cBlack )
- {
- pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
- pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
- pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
- }
- }
- }
- }
- else
- {
- for( nY = 0; nY < nHeight; nY++ )
- {
- for( nX = 0; nX < nWidth; nX++ )
- {
- if( pR->GetPixel( nY, nX ) == aBlack )
- {
- aPixCol = pW->GetColor( nY, nX );
- pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
- }
- }
- }
- }
- }
- }
-
- aPolyMask.ReleaseAccess( pR );
- aPaint.ReleaseAccess( pW );
-
- DrawBitmap( aDstRect.TopLeft(), aPaint );
-
- EnableMapMode( bOldMap );
-
- if( mbLineColor )
- {
- Push( PUSH_FILLCOLOR );
- SetFillColor();
- DrawPolyPolygon( rPolyPoly );
- Pop();
- }
- }
- }
- else
- DrawPolyPolygon( rPolyPoly );
- }
- }
-
- mpMetaFile = pOldMetaFile;
-
- // #110958# Restore disabled alpha VDev
- mpAlphaVDev = pOldAlphaVDev;
-}
-
-void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
- sal_uInt16 nTransparencePercent )
-{
- // short circuit for drawing an opaque polygon
- if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
- {
- DrawPolyPolygon( rPolyPoly );
- return;
- }
-
- // short circuit for drawing an invisible polygon
- if( !mbFillColor || (nTransparencePercent >= 100) )
- {
- DrawInvisiblePolygon( rPolyPoly );
- }
-
- // handle metafile recording
- if( mpMetaFile )
- mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
-
- bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
- if( bDrawn )
- return;
-
- // get the device graphics as drawing target
- if( !mpGraphics )
- if( !ImplGetGraphics() )
- return;
-
- // try hard to draw it directly, because the emulation layers are slower
- bDrawn = DrawTransparentNatively( rPolyPoly, nTransparencePercent );
- if( bDrawn )
- return;
-
- EmulateDrawTransparent( rPolyPoly, nTransparencePercent );
-
- // #110958# Apply alpha value also to VDev alpha channel
- if( mpAlphaVDev )
- {
- const Color aFillCol( mpAlphaVDev->GetFillColor() );
- mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
- sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
- sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
-
- mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
-
- mpAlphaVDev->SetFillColor( aFillCol );
- }
-}
-
-void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
- const Size& rSize, const Gradient& rTransparenceGradient )
-{
-
- const Color aBlack( COL_BLACK );
-
- if( mpMetaFile )
- {
- // missing here is to map the data using the DeviceTransformation
- mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
- }
-
- if ( !IsDeviceOutputNecessary() )
- return;
-
- if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
- ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
- {
- ( (GDIMetaFile&) rMtf ).WindStart();
- ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
- ( (GDIMetaFile&) rMtf ).WindStart();
- }
- else
- {
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
- Point aPoint;
- Rectangle aDstRect( aPoint, GetOutputSizePixel() );
-
- mpMetaFile = NULL;
- aDstRect.Intersection( aOutRect );
-
- ClipToPaintRegion( aDstRect );
-
- if( !aDstRect.IsEmpty() )
- {
- boost::scoped_ptr<VirtualDevice> pVDev(new VirtualDevice);
-
- ((OutputDevice*)pVDev.get())->mnDPIX = mnDPIX;
- ((OutputDevice*)pVDev.get())->mnDPIY = mnDPIY;
-
- if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
- {
- if(GetAntialiasing())
- {
- // #i102109#
- // For MetaFile replay (see task) it may now be necessary to take
- // into account that the content is AntiAlialised and needs to be masked
- // like that. Instead of masking, i will use a copy-modify-paste cycle
- // here (as i already use in the VclPrimiziveRenderer with successs)
- pVDev->SetAntialiasing(GetAntialiasing());
-
- // create MapMode for buffer (offset needed) and set
- MapMode aMap(GetMapMode());
- const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
- aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
- pVDev->SetMapMode(aMap);
-
- // copy MapMode state and disable for target
- const bool bOrigMapModeEnabled(IsMapModeEnabled());
- EnableMapMode(false);
-
- // copy MapMode state and disable for buffer
- const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
- pVDev->EnableMapMode(false);
-
- // copy content from original to buffer
- pVDev->DrawOutDev(
- aPoint, pVDev->GetOutputSizePixel(), // dest
- aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
- *this);
-
- // draw MetaFile to buffer
- pVDev->EnableMapMode(bBufferMapModeEnabled);
- ((GDIMetaFile&)rMtf).WindStart();
- ((GDIMetaFile&)rMtf).Play(pVDev.get(), rPos, rSize);
- ((GDIMetaFile&)rMtf).WindStart();
-
- // get content bitmap from buffer
- pVDev->EnableMapMode(false);
- const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
-
- // create alpha mask from gradient and get as Bitmap
- pVDev->EnableMapMode(bBufferMapModeEnabled);
- pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
- pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
- pVDev->SetDrawMode(DRAWMODE_DEFAULT);
- pVDev->EnableMapMode(false);
- const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
-
- pVDev.reset();
-
- // draw masked content to target and restore MapMode
- DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
- EnableMapMode(bOrigMapModeEnabled);
- }
- else
- {
- Bitmap aPaint, aMask;
- AlphaMask aAlpha;
- MapMode aMap( GetMapMode() );
- Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
- const bool bOldMap = mbMap;
-
- aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
- pVDev->SetMapMode( aMap );
- const bool bVDevOldMap = pVDev->IsMapModeEnabled();
-
- // create paint bitmap
- ( (GDIMetaFile&) rMtf ).WindStart();
- ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
- ( (GDIMetaFile&) rMtf ).WindStart();
- pVDev->EnableMapMode( false );
- aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
- pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
-
- // create mask bitmap
- pVDev->SetLineColor( COL_BLACK );
- pVDev->SetFillColor( COL_BLACK );
- pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
- pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
- DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
- ( (GDIMetaFile&) rMtf ).WindStart();
- ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
- ( (GDIMetaFile&) rMtf ).WindStart();
- pVDev->EnableMapMode( false );
- aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
- pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
-
- // create alpha mask from gradient
- pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
- pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
- pVDev->SetDrawMode( DRAWMODE_DEFAULT );
- pVDev->EnableMapMode( false );
- pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
-
- aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
-
- pVDev.reset();
-
- EnableMapMode( false );
- DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
- EnableMapMode( bOldMap );
- }
- }
- }
-
- mpMetaFile = pOldMetaFile;
- }
-}
-
-void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
- long nWidth, long nHeight,
- const Wallpaper& rWallpaper )
-{
- // draw wallpaper without border
- Color aOldLineColor = GetLineColor();
- Color aOldFillColor = GetFillColor();
- SetLineColor();
- SetFillColor( rWallpaper.GetColor() );
- bool bMap = mbMap;
- EnableMapMode( false );
- DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
- SetLineColor( aOldLineColor );
- SetFillColor( aOldFillColor );
- EnableMapMode( bMap );
-}
-
-void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
- long nWidth, long nHeight,
- const Wallpaper& rWallpaper )
-{
- BitmapEx aBmpEx;
- const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
- Point aPos;
- Size aSize;
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- const WallpaperStyle eStyle = rWallpaper.GetStyle();
- const bool bOldMap = mbMap;
- bool bDrawn = false;
- bool bDrawGradientBackground = false;
- bool bDrawColorBackground = false;
-
- if( pCached )
- aBmpEx = *pCached;
- else
- aBmpEx = rWallpaper.GetBitmap();
-
- const long nBmpWidth = aBmpEx.GetSizePixel().Width();
- const long nBmpHeight = aBmpEx.GetSizePixel().Height();
- const bool bTransparent = aBmpEx.IsTransparent();
-
- // draw background
- if( bTransparent )
- {
- if( rWallpaper.IsGradient() )
- bDrawGradientBackground = true;
- else
- {
- if( !pCached && !rWallpaper.GetColor().GetTransparency() )
- {
- VirtualDevice aVDev( *this );
- aVDev.SetBackground( rWallpaper.GetColor() );
- aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
- aVDev.DrawBitmapEx( Point(), aBmpEx );
- aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
- }
-
- bDrawColorBackground = true;
- }
- }
- else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
- {
- if( rWallpaper.IsGradient() )
- bDrawGradientBackground = true;
- else
- bDrawColorBackground = true;
- }
-
- // background of bitmap?
- if( bDrawGradientBackground )
- ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
- else if( bDrawColorBackground && bTransparent )
- {
- ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
- bDrawColorBackground = false;
- }
-
- // calc pos and size
- if( rWallpaper.IsRect() )
- {
- const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
- aPos = aBound.TopLeft();
- aSize = aBound.GetSize();
- }
- else
- {
- aPos = Point( 0, 0 );
- aSize = Size( mnOutWidth, mnOutHeight );
- }
-
- mpMetaFile = NULL;
- EnableMapMode( false );
- Push( PUSH_CLIPREGION );
- IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
-
- switch( eStyle )
- {
- case( WALLPAPER_SCALE ):
- {
- if( !pCached || ( pCached->GetSizePixel() != aSize ) )
- {
- if( pCached )
- rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
-
- aBmpEx = rWallpaper.GetBitmap();
- aBmpEx.Scale( aSize );
- aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
- }
- }
- break;
-
- case( WALLPAPER_TOPLEFT ):
- break;
-
- case( WALLPAPER_TOP ):
- aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
- break;
-
- case( WALLPAPER_TOPRIGHT ):
- aPos.X() += ( aSize.Width() - nBmpWidth );
- break;
-
- case( WALLPAPER_LEFT ):
- aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
- break;
-
- case( WALLPAPER_CENTER ):
- {
- aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
- aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
- }
- break;
-
- case( WALLPAPER_RIGHT ):
- {
- aPos.X() += ( aSize.Width() - nBmpWidth );
- aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
- }
- break;
-
- case( WALLPAPER_BOTTOMLEFT ):
- aPos.Y() += ( aSize.Height() - nBmpHeight );
- break;
-
- case( WALLPAPER_BOTTOM ):
- {
- aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
- aPos.Y() += ( aSize.Height() - nBmpHeight );
- }
- break;
-
- case( WALLPAPER_BOTTOMRIGHT ):
- {
- aPos.X() += ( aSize.Width() - nBmpWidth );
- aPos.Y() += ( aSize.Height() - nBmpHeight );
- }
- break;
-
- default:
- {
- const long nRight = nX + nWidth - 1L;
- const long nBottom = nY + nHeight - 1L;
- long nFirstX;
- long nFirstY;
-
- if( eStyle == WALLPAPER_TILE )
- {
- nFirstX = aPos.X();
- nFirstY = aPos.Y();
- }
- else
- {
- nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
- nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
- }
-
- const long nOffX = ( nFirstX - nX ) % nBmpWidth;
- const long nOffY = ( nFirstY - nY ) % nBmpHeight;
- long nStartX = nX + nOffX;
- long nStartY = nY + nOffY;
-
- if( nOffX > 0L )
- nStartX -= nBmpWidth;
-
- if( nOffY > 0L )
- nStartY -= nBmpHeight;
-
- for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
- for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
- DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
-
- bDrawn = true;
- }
- break;
- }
-
- if( !bDrawn )
- {
- // optimized for non-transparent bitmaps
- if( bDrawColorBackground )
- {
- const Size aBmpSize( aBmpEx.GetSizePixel() );
- const Point aTmpPoint;
- const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
- const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
- Rectangle aWorkRect;
-
- aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
- aWorkRect.Justify();
- aWorkRect.Intersection( aColRect );
- if( !aWorkRect.IsEmpty() )
- {
- ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
- aWorkRect.GetWidth(), aWorkRect.GetHeight(),
- rWallpaper );
- }
-
- aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
- aWorkRect.Justify();
- aWorkRect.Intersection( aColRect );
- if( !aWorkRect.IsEmpty() )
- {
- ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
- aWorkRect.GetWidth(), aWorkRect.GetHeight(),
- rWallpaper );
- }
-
- aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
- aWorkRect.Justify();
- aWorkRect.Intersection( aColRect );
- if( !aWorkRect.IsEmpty() )
- {
- ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
- aWorkRect.GetWidth(), aWorkRect.GetHeight(),
- rWallpaper );
- }
-
- aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
- aWorkRect.Justify();
- aWorkRect.Intersection( aColRect );
- if( !aWorkRect.IsEmpty() )
- {
- ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
- aWorkRect.GetWidth(), aWorkRect.GetHeight(),
- rWallpaper );
- }
- }
-
- DrawBitmapEx( aPos, aBmpEx );
- }
-
- rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
-
- Pop();
- EnableMapMode( bOldMap );
- mpMetaFile = pOldMetaFile;
-}
-
-void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
- long nWidth, long nHeight,
- const Wallpaper& rWallpaper )
-{
- Rectangle aBound;
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- const bool bOldMap = mbMap;
- bool bNeedGradient = true;
-
- aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
-
- mpMetaFile = NULL;
- EnableMapMode( false );
- Push( PUSH_CLIPREGION );
- IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
-
- if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT )
- {
- Window *pWin = dynamic_cast< Window* >( this );
- if( pWin )
- {
- // limit gradient to useful size, so that it still can be noticed
- // in maximized windows
- long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width();
- if( gradientWidth > 1024 )
- gradientWidth = 1024;
- if( mnOutOffX+nWidth > gradientWidth )
- ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() );
- if( mnOutOffX > gradientWidth )
- bNeedGradient = false;
- else
- aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) );
- }
- }
-
- if( bNeedGradient )
- DrawGradient( aBound, rWallpaper.GetGradient() );
-
- Pop();
- EnableMapMode( bOldMap );
- mpMetaFile = pOldMetaFile;
-}
-
-void OutputDevice::ImplDrawWallpaper( long nX, long nY,
- long nWidth, long nHeight,
- const Wallpaper& rWallpaper )
-{
- if( rWallpaper.IsBitmap() )
- ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
- else if( rWallpaper.IsGradient() )
- ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
- else
- ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
-}
-
-void OutputDevice::DrawWallpaper( const Rectangle& rRect,
- const Wallpaper& rWallpaper )
-{
- if ( mpMetaFile )
- mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
-
- if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
- return;
-
- if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
- {
- Rectangle aRect = LogicToPixel( rRect );
- aRect.Justify();
-
- if ( !aRect.IsEmpty() )
- {
- ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
- rWallpaper );
- }
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
-}
-
-void OutputDevice::Erase()
-{
- if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
- return;
-
- bool bNativeOK = false;
-
- if( meOutDevType == OUTDEV_WINDOW )
- {
- Window* pWindow = static_cast<Window*>(this);
- ControlPart aCtrlPart = pWindow->ImplGetWindowImpl()->mnNativeBackground;
- if( aCtrlPart != 0 && ! pWindow->IsControlBackground() )
- {
- ImplControlValue aControlValue;
- Point aGcc3WorkaroundTemporary;
- Rectangle aCtrlRegion( aGcc3WorkaroundTemporary, GetOutputSizePixel() );
- ControlState nState = 0;
-
- if( pWindow->IsEnabled() ) nState |= CTRL_STATE_ENABLED;
- bNativeOK = pWindow->DrawNativeControl( CTRL_WINDOW_BACKGROUND, aCtrlPart, aCtrlRegion,
- nState, aControlValue, OUString() );
- }
- }
-
- if ( mbBackground && ! bNativeOK )
- {
- RasterOp eRasterOp = GetRasterOp();
- if ( eRasterOp != ROP_OVERPAINT )
- SetRasterOp( ROP_OVERPAINT );
- ImplDrawWallpaper( 0, 0, mnOutWidth, mnOutHeight, maBackground );
- if ( eRasterOp != ROP_OVERPAINT )
- SetRasterOp( eRasterOp );
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->Erase();
-}
-
-bool OutputDevice::DrawEPS( const Point& rPoint, const Size& rSize,
- const GfxLink& rGfxLink, GDIMetaFile* pSubst )
-{
- bool bDrawn(true);
-
- if ( mpMetaFile )
- {
- GDIMetaFile aSubst;
-
- if( pSubst )
- aSubst = *pSubst;
-
- mpMetaFile->AddAction( new MetaEPSAction( rPoint, rSize, rGfxLink, aSubst ) );
- }
-
- if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
- return bDrawn;
-
- if( mbOutputClipped )
- return bDrawn;
-
- Rectangle aRect( ImplLogicToDevicePixel( Rectangle( rPoint, rSize ) ) );
-
- if( !aRect.IsEmpty() )
- {
- // draw the real EPS graphics
- if( rGfxLink.GetData() && rGfxLink.GetDataSize() )
- {
- if( !mpGraphics && !ImplGetGraphics() )
- return bDrawn;
-
- if( mbInitClipRegion )
- ImplInitClipRegion();
-
- aRect.Justify();
- bDrawn = mpGraphics->DrawEPS( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
- (sal_uInt8*) rGfxLink.GetData(), rGfxLink.GetDataSize(), this );
- }
-
- // else draw the substitution graphics
- if( !bDrawn && pSubst )
- {
- GDIMetaFile* pOldMetaFile = mpMetaFile;
-
- mpMetaFile = NULL;
- Graphic( *pSubst ).Draw( this, rPoint, rSize );
- mpMetaFile = pOldMetaFile;
- }
- }
-
- if( mpAlphaVDev )
- mpAlphaVDev->DrawEPS( rPoint, rSize, rGfxLink, pSubst );
-
- return bDrawn;
-}
-
-void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd)
-{
- const sal_uInt32 nMaxX(rPos.X() + rSize.Width());
- const sal_uInt32 nMaxY(rPos.Y() + rSize.Height());
-
- Push(PUSH_LINECOLOR|PUSH_FILLCOLOR);
- SetLineColor();
-
- for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen)
- {
- const sal_uInt32 nRight(std::min(nMaxX, nX + nLen));
-
- for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen)
- {
- const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen));
-
- SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd);
- DrawRect(Rectangle(nX, nY, nRight, nBottom));
- }
- }
-
- Pop();
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/polygon.cxx b/vcl/source/outdev/polygon.cxx
index 09561a6055a2..312625dfd850 100644
--- a/vcl/source/outdev/polygon.cxx
+++ b/vcl/source/outdev/polygon.cxx
@@ -476,3 +476,97 @@ void OutputDevice::ImplDrawPolyPolygon( const PolyPolygon& rPolyPoly, const Poly
if( pClipPolyPoly )
delete pPolyPoly;
}
+
+void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, sal_uLong nFlags )
+{
+
+ Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() );
+ aDstRect.Intersection( rRect );
+
+ if( aDstRect.IsEmpty() || ImplIsRecordLayout() )
+ return;
+
+ if( !mpGraphics && !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if( mbOutputClipped )
+ return;
+
+ const long nDistX = std::max( rDist.Width(), 1L );
+ const long nDistY = std::max( rDist.Height(), 1L );
+ long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX );
+ long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY );
+ const long nRight = aDstRect.Right();
+ const long nBottom = aDstRect.Bottom();
+ const long nStartX = ImplLogicXToDevicePixel( nX );
+ const long nEndX = ImplLogicXToDevicePixel( nRight );
+ const long nStartY = ImplLogicYToDevicePixel( nY );
+ const long nEndY = ImplLogicYToDevicePixel( nBottom );
+ long nHorzCount = 0L;
+ long nVertCount = 0L;
+
+ ::com::sun::star::uno::Sequence< sal_Int32 > aVertBuf;
+ ::com::sun::star::uno::Sequence< sal_Int32 > aHorzBuf;
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_HORZLINES ) )
+ {
+ aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L );
+ aVertBuf[ nVertCount++ ] = nStartY;
+ while( ( nY += nDistY ) <= nBottom )
+ aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY );
+ }
+
+ if( ( nFlags & GRID_DOTS ) || ( nFlags & GRID_VERTLINES ) )
+ {
+ aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L );
+ aHorzBuf[ nHorzCount++ ] = nStartX;
+ while( ( nX += nDistX ) <= nRight )
+ aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX );
+ }
+
+ if( mbInitLineColor )
+ ImplInitLineColor();
+
+ if( mbInitFillColor )
+ ImplInitFillColor();
+
+ const bool bOldMap = mbMap;
+ EnableMapMode( false );
+
+ if( nFlags & GRID_DOTS )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ )
+ mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this );
+ }
+ else
+ {
+ if( nFlags & GRID_HORZLINES )
+ {
+ for( long i = 0L; i < nVertCount; i++ )
+ {
+ nY = aVertBuf[ i ];
+ mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this );
+ }
+ }
+
+ if( nFlags & GRID_VERTLINES )
+ {
+ for( long i = 0L; i < nHorzCount; i++ )
+ {
+ nX = aHorzBuf[ i ];
+ mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this );
+ }
+ }
+ }
+
+ EnableMapMode( bOldMap );
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->DrawGrid( rRect, rDist, nFlags );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx
index 9bc8e392b701..c5b630abc22c 100644
--- a/vcl/source/outdev/transparent.cxx
+++ b/vcl/source/outdev/transparent.cxx
@@ -40,6 +40,48 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <boost/scoped_array.hpp>
+
+namespace
+{
+ /**
+ * Perform a safe approximation of a polygon from double-precision
+ * coordinates to integer coordinates, to ensure that it has at least 2
+ * pixels in both X and Y directions.
+ */
+ Polygon toPolygon( const basegfx::B2DPolygon& rPoly )
+ {
+ basegfx::B2DRange aRange = rPoly.getB2DRange();
+ double fW = aRange.getWidth(), fH = aRange.getHeight();
+ if (0.0 < fW && 0.0 < fH && (fW <= 1.0 || fH <= 1.0))
+ {
+ // This polygon not empty but is too small to display. Approximate it
+ // with a rectangle large enough to be displayed.
+ double nX = aRange.getMinX(), nY = aRange.getMinY();
+ double nW = std::max<double>(1.0, rtl::math::round(fW));
+ double nH = std::max<double>(1.0, rtl::math::round(fH));
+
+ Polygon aTarget;
+ aTarget.Insert(0, Point(nX, nY));
+ aTarget.Insert(1, Point(nX+nW, nY));
+ aTarget.Insert(2, Point(nX+nW, nY+nH));
+ aTarget.Insert(3, Point(nX, nY+nH));
+ aTarget.Insert(4, Point(nX, nY));
+ return aTarget;
+ }
+ return Polygon(rPoly);
+ }
+
+ PolyPolygon toPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly )
+ {
+ PolyPolygon aTarget;
+ for (sal_uInt32 i = 0; i < rPolyPoly.count(); ++i)
+ aTarget.Insert(toPolygon(rPolyPoly.getB2DPolygon(i)));
+
+ return aTarget;
+ }
+
+}
+
void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
const Point& rDestPt, const Size& rDestSize,
const Point& rSrcPtPixel, const Size& rSrcSizePixel )
@@ -133,4 +175,565 @@ void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask
}
}
+// Caution: This method is nearly the same as
+// void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
+// so when changes are made here do not forget to make changes there, too
+
+void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
+{
+ // AW: Do NOT paint empty PolyPolygons
+ if(!rB2DPolyPoly.count())
+ return;
+
+ // we need a graphics
+ if( !mpGraphics )
+ if( !ImplGetGraphics() )
+ return;
+
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+ if( mbOutputClipped )
+ return;
+
+ if( mbInitLineColor )
+ ImplInitLineColor();
+ if( mbInitFillColor )
+ ImplInitFillColor();
+
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp() )
+ {
+ // b2dpolygon support not implemented yet on non-UNX platforms
+ const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
+
+ // transform the polygon into device space and ensure it is closed
+ aB2DPolyPolygon.transform( aTransform );
+ aB2DPolyPolygon.setClosed( true );
+
+ bool bDrawnOk = true;
+ if( IsFillColor() )
+ bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
+ if( bDrawnOk && IsLineColor() )
+ {
+ const basegfx::B2DVector aHairlineWidth(1,1);
+ const int nPolyCount = aB2DPolyPolygon.count();
+ for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
+ {
+ const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
+ mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
+ }
+ }
+
+ if( bDrawnOk )
+ {
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTransparentAction( PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
+ return;
+ }
+ }
+
+ // fallback to old polygon drawing if needed
+ DrawTransparent(toPolyPolygon(rB2DPolyPoly), static_cast<sal_uInt16>(fTransparency * 100.0));
+}
+
+void OutputDevice::DrawInvisiblePolygon( const PolyPolygon& rPolyPoly )
+{
+ // short circuit if the polygon border is invisible too
+ if( !mbLineColor )
+ return;
+
+ // we assume that the border is NOT to be drawn transparently???
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+}
+
+bool OutputDevice::DrawTransparentNatively ( const PolyPolygon& rPolyPoly,
+ sal_uInt16 nTransparencePercent )
+{
+ bool bDrawn = false;
+
+ // debug helper:
+ static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
+
+ if( !pDisableNative
+ && mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
+#if defined UNX && ! defined MACOSX && ! defined IOS
+ && GetBitCount() > 8
+#endif
+#ifdef WIN32
+ // workaround bad dithering on remote displaying when using GDI+ with toolbar button highlighting
+ && !rPolyPoly.IsRect()
+#endif
+ )
+ {
+ // prepare the graphics device
+ if( mbInitClipRegion )
+ ImplInitClipRegion();
+ if( mbOutputClipped )
+ return false;
+ if( mbInitLineColor )
+ ImplInitLineColor();
+ if( mbInitFillColor )
+ ImplInitFillColor();
+
+ // get the polygon in device coordinates
+ basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
+ const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
+ aB2DPolyPolygon.transform( aTransform );
+
+ const double fTransparency = 0.01 * nTransparencePercent;
+ if( mbFillColor )
+ {
+ // #i121591#
+ // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
+ // should be used when printing. Normally this is avoided by the printer being
+ // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
+ // to figure out a way of moving this code to it's own function that is
+ // overriden by the Print class, which will mean we deliberately override the
+ // functionality and we use the fallback some lines below (which is not very good,
+ // though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
+ // correct the wrong mapping (see there for details)
+ bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
+ }
+
+ if( mbLineColor )
+ {
+ // disable the fill color for now
+ mpGraphics->SetFillColor();
+ // draw the border line
+ const basegfx::B2DVector aLineWidths( 1, 1 );
+ const int nPolyCount = aB2DPolyPolygon.count();
+ for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
+ {
+ const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
+ bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
+ }
+ // prepare to restore the fill color
+ mbInitFillColor = mbFillColor;
+ }
+ }
+
+ return bDrawn;
+}
+
+void OutputDevice::EmulateDrawTransparent ( const PolyPolygon& rPolyPoly,
+ sal_uInt16 nTransparencePercent )
+{
+ // debug helper:
+ static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
+
+ // #110958# Disable alpha VDev, we perform the necessary
+ VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
+
+ // operation explicitly further below.
+ if( mpAlphaVDev )
+ mpAlphaVDev = NULL;
+
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ mpMetaFile = NULL;
+
+ PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
+ Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ aDstRect.Intersection( aPolyRect );
+
+ ClipToPaintRegion( aDstRect );
+
+ if( !aDstRect.IsEmpty() )
+ {
+ bool bDrawn = false;
+
+ // #i66849# Added fast path for exactly rectangular
+ // polygons
+ // #i83087# Naturally, system alpha blending cannot
+ // work with separate alpha VDev
+ if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
+ {
+ // setup Graphics only here (other cases delegate
+ // to basic OutDev methods)
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+ if ( mbInitLineColor )
+ ImplInitLineColor();
+ if ( mbInitFillColor )
+ ImplInitFillColor();
+
+ Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
+ Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
+
+ if( !mbOutputClipped )
+ {
+ bDrawn = mpGraphics->DrawAlphaRect(
+ aPixelRect.Left(), aPixelRect.Top(),
+ // #i98405# use methods with small g, else one pixel too much will be painted.
+ // This is because the source is a polygon which when painted would not paint
+ // the rightmost and lowest pixel line(s), so use one pixel less for the
+ // rectangle, too.
+ aPixelRect.getWidth(), aPixelRect.getHeight(),
+ sal::static_int_cast<sal_uInt8>(nTransparencePercent),
+ this );
+ }
+ else
+ bDrawn = true;
+ }
+
+ if( !bDrawn )
+ {
+ VirtualDevice aVDev( *this, 1 );
+ const Size aDstSz( aDstRect.GetSize() );
+ const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
+
+ if( aDstRect.Left() || aDstRect.Top() )
+ aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
+
+ if( aVDev.SetOutputSizePixel( aDstSz ) )
+ {
+ const bool bOldMap = mbMap;
+
+ EnableMapMode( false );
+
+ aVDev.SetLineColor( COL_BLACK );
+ aVDev.SetFillColor( COL_BLACK );
+ aVDev.DrawPolyPolygon( aPolyPoly );
+
+ Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
+ Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
+
+ // #107766# check for non-empty bitmaps before accessing them
+ if( !!aPaint && !!aPolyMask )
+ {
+ BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
+ BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
+
+ if( pW && pR )
+ {
+ BitmapColor aPixCol;
+ const BitmapColor aFillCol( GetFillColor() );
+ const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
+ const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
+ const long nWidth = pW->Width(), nHeight = pW->Height();
+ const long nR = aFillCol.GetRed(), nG = aFillCol.GetGreen(), nB = aFillCol.GetBlue();
+ long nX, nY;
+
+ if( aPaint.GetBitCount() <= 8 )
+ {
+ const BitmapPalette& rPal = pW->GetPalette();
+ const sal_uInt16 nCount = rPal.GetEntryCount();
+ BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ];
+
+ for( sal_uInt16 i = 0; i < nCount; i++ )
+ {
+ BitmapColor aCol( rPal[ i ] );
+ pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
+ }
+
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
+ {
+ const sal_uInt8 cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ sal_uInt8 cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex();
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ for( nX = 0; nX < nWidth; nX++ )
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
+ }
+
+ delete[] (sal_uInt8*) pMap;
+ }
+ else
+ {
+ if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
+ pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
+ {
+ const sal_uInt8 cBlack = aBlack.GetIndex();
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pWScan = pW->GetScanline( nY );
+ Scanline pRScan = pR->GetScanline( nY );
+ sal_uInt8 cBit = 128;
+
+ for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
+ {
+ if( !cBit )
+ cBit = 128, pRScan++;
+
+ if( ( *pRScan & cBit ) == cBlack )
+ {
+ pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
+ pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
+ pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
+ }
+ }
+ }
+ }
+ else
+ {
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ for( nX = 0; nX < nWidth; nX++ )
+ {
+ if( pR->GetPixel( nY, nX ) == aBlack )
+ {
+ aPixCol = pW->GetColor( nY, nX );
+ pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ aPolyMask.ReleaseAccess( pR );
+ aPaint.ReleaseAccess( pW );
+
+ DrawBitmap( aDstRect.TopLeft(), aPaint );
+
+ EnableMapMode( bOldMap );
+
+ if( mbLineColor )
+ {
+ Push( PUSH_FILLCOLOR );
+ SetFillColor();
+ DrawPolyPolygon( rPolyPoly );
+ Pop();
+ }
+ }
+ }
+ else
+ DrawPolyPolygon( rPolyPoly );
+ }
+ }
+
+ mpMetaFile = pOldMetaFile;
+
+ // #110958# Restore disabled alpha VDev
+ mpAlphaVDev = pOldAlphaVDev;
+}
+
+void OutputDevice::DrawTransparent( const PolyPolygon& rPolyPoly,
+ sal_uInt16 nTransparencePercent )
+{
+ // short circuit for drawing an opaque polygon
+ if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
+ {
+ DrawPolyPolygon( rPolyPoly );
+ return;
+ }
+
+ // short circuit for drawing an invisible polygon
+ if( !mbFillColor || (nTransparencePercent >= 100) )
+ {
+ DrawInvisiblePolygon( rPolyPoly );
+ }
+
+ // handle metafile recording
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
+
+ bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
+ if( bDrawn )
+ return;
+
+ // get the device graphics as drawing target
+ if( !mpGraphics )
+ if( !ImplGetGraphics() )
+ return;
+
+ // try hard to draw it directly, because the emulation layers are slower
+ bDrawn = DrawTransparentNatively( rPolyPoly, nTransparencePercent );
+ if( bDrawn )
+ return;
+
+ EmulateDrawTransparent( rPolyPoly, nTransparencePercent );
+
+ // #110958# Apply alpha value also to VDev alpha channel
+ if( mpAlphaVDev )
+ {
+ const Color aFillCol( mpAlphaVDev->GetFillColor() );
+ mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
+ sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
+ sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
+
+ mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
+
+ mpAlphaVDev->SetFillColor( aFillCol );
+ }
+}
+
+void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
+ const Size& rSize, const Gradient& rTransparenceGradient )
+{
+
+ const Color aBlack( COL_BLACK );
+
+ if( mpMetaFile )
+ {
+ // missing here is to map the data using the DeviceTransformation
+ mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
+ }
+
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
+ ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
+ {
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ }
+ else
+ {
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
+ Point aPoint;
+ Rectangle aDstRect( aPoint, GetOutputSizePixel() );
+
+ mpMetaFile = NULL;
+ aDstRect.Intersection( aOutRect );
+
+ ClipToPaintRegion( aDstRect );
+
+ if( !aDstRect.IsEmpty() )
+ {
+ boost::scoped_ptr<VirtualDevice> pVDev(new VirtualDevice);
+
+ ((OutputDevice*)pVDev.get())->mnDPIX = mnDPIX;
+ ((OutputDevice*)pVDev.get())->mnDPIY = mnDPIY;
+
+ if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
+ {
+ if(GetAntialiasing())
+ {
+ // #i102109#
+ // For MetaFile replay (see task) it may now be necessary to take
+ // into account that the content is AntiAlialised and needs to be masked
+ // like that. Instead of masking, i will use a copy-modify-paste cycle
+ // here (as i already use in the VclPrimiziveRenderer with successs)
+ pVDev->SetAntialiasing(GetAntialiasing());
+
+ // create MapMode for buffer (offset needed) and set
+ MapMode aMap(GetMapMode());
+ const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
+ aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
+ pVDev->SetMapMode(aMap);
+
+ // copy MapMode state and disable for target
+ const bool bOrigMapModeEnabled(IsMapModeEnabled());
+ EnableMapMode(false);
+
+ // copy MapMode state and disable for buffer
+ const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
+ pVDev->EnableMapMode(false);
+
+ // copy content from original to buffer
+ pVDev->DrawOutDev(
+ aPoint, pVDev->GetOutputSizePixel(), // dest
+ aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
+ *this);
+
+ // draw MetaFile to buffer
+ pVDev->EnableMapMode(bBufferMapModeEnabled);
+ ((GDIMetaFile&)rMtf).WindStart();
+ ((GDIMetaFile&)rMtf).Play(pVDev.get(), rPos, rSize);
+ ((GDIMetaFile&)rMtf).WindStart();
+
+ // get content bitmap from buffer
+ pVDev->EnableMapMode(false);
+ const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
+
+ // create alpha mask from gradient and get as Bitmap
+ pVDev->EnableMapMode(bBufferMapModeEnabled);
+ pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
+ pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
+ pVDev->SetDrawMode(DRAWMODE_DEFAULT);
+ pVDev->EnableMapMode(false);
+ const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
+
+ pVDev.reset();
+
+ // draw masked content to target and restore MapMode
+ DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
+ EnableMapMode(bOrigMapModeEnabled);
+ }
+ else
+ {
+ Bitmap aPaint, aMask;
+ AlphaMask aAlpha;
+ MapMode aMap( GetMapMode() );
+ Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
+ const bool bOldMap = mbMap;
+
+ aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
+ pVDev->SetMapMode( aMap );
+ const bool bVDevOldMap = pVDev->IsMapModeEnabled();
+
+ // create paint bitmap
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( false );
+ aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
+
+ // create mask bitmap
+ pVDev->SetLineColor( COL_BLACK );
+ pVDev->SetFillColor( COL_BLACK );
+ pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
+ pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
+ DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
+ ( (GDIMetaFile&) rMtf ).WindStart();
+ pVDev->EnableMapMode( false );
+ aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+ pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
+
+ // create alpha mask from gradient
+ pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
+ pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
+ pVDev->SetDrawMode( DRAWMODE_DEFAULT );
+ pVDev->EnableMapMode( false );
+ pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
+
+ aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
+
+ pVDev.reset();
+
+ EnableMapMode( false );
+ DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
+ EnableMapMode( bOldMap );
+ }
+ }
+ }
+
+ mpMetaFile = pOldMetaFile;
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/wallpaper.cxx b/vcl/source/outdev/wallpaper.cxx
new file mode 100644
index 000000000000..c53c1ecf6a39
--- /dev/null
+++ b/vcl/source/outdev/wallpaper.cxx
@@ -0,0 +1,384 @@
+/* -*- 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/outdev.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/graph.hxx>
+
+#include <wall2.hxx>
+#include <salgdi.hxx>
+#include <window.h>
+#include <svdata.hxx>
+#include <outdev.h>
+
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <math.h>
+#include <boost/scoped_ptr.hpp>
+
+void OutputDevice::ImplDrawColorWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ // draw wallpaper without border
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ SetLineColor();
+ SetFillColor( rWallpaper.GetColor() );
+ bool bMap = mbMap;
+ EnableMapMode( false );
+ DrawRect( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ EnableMapMode( bMap );
+}
+
+void OutputDevice::ImplDrawBitmapWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ BitmapEx aBmpEx;
+ const BitmapEx* pCached = rWallpaper.ImplGetImpWallpaper()->ImplGetCachedBitmap();
+ Point aPos;
+ Size aSize;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const WallpaperStyle eStyle = rWallpaper.GetStyle();
+ const bool bOldMap = mbMap;
+ bool bDrawn = false;
+ bool bDrawGradientBackground = false;
+ bool bDrawColorBackground = false;
+
+ if( pCached )
+ aBmpEx = *pCached;
+ else
+ aBmpEx = rWallpaper.GetBitmap();
+
+ const long nBmpWidth = aBmpEx.GetSizePixel().Width();
+ const long nBmpHeight = aBmpEx.GetSizePixel().Height();
+ const bool bTransparent = aBmpEx.IsTransparent();
+
+ // draw background
+ if( bTransparent )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = true;
+ else
+ {
+ if( !pCached && !rWallpaper.GetColor().GetTransparency() )
+ {
+ VirtualDevice aVDev( *this );
+ aVDev.SetBackground( rWallpaper.GetColor() );
+ aVDev.SetOutputSizePixel( Size( nBmpWidth, nBmpHeight ) );
+ aVDev.DrawBitmapEx( Point(), aBmpEx );
+ aBmpEx = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+
+ bDrawColorBackground = true;
+ }
+ }
+ else if( eStyle != WALLPAPER_TILE && eStyle != WALLPAPER_SCALE )
+ {
+ if( rWallpaper.IsGradient() )
+ bDrawGradientBackground = true;
+ else
+ bDrawColorBackground = true;
+ }
+
+ // background of bitmap?
+ if( bDrawGradientBackground )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( bDrawColorBackground && bTransparent )
+ {
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ bDrawColorBackground = false;
+ }
+
+ // calc pos and size
+ if( rWallpaper.IsRect() )
+ {
+ const Rectangle aBound( LogicToPixel( rWallpaper.GetRect() ) );
+ aPos = aBound.TopLeft();
+ aSize = aBound.GetSize();
+ }
+ else
+ {
+ aPos = Point( 0, 0 );
+ aSize = Size( mnOutWidth, mnOutHeight );
+ }
+
+ mpMetaFile = NULL;
+ EnableMapMode( false );
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ switch( eStyle )
+ {
+ case( WALLPAPER_SCALE ):
+ {
+ if( !pCached || ( pCached->GetSizePixel() != aSize ) )
+ {
+ if( pCached )
+ rWallpaper.ImplGetImpWallpaper()->ImplReleaseCachedBitmap();
+
+ aBmpEx = rWallpaper.GetBitmap();
+ aBmpEx.Scale( aSize );
+ aBmpEx = BitmapEx( aBmpEx.GetBitmap().CreateDisplayBitmap( this ), aBmpEx.GetMask() );
+ }
+ }
+ break;
+
+ case( WALLPAPER_TOPLEFT ):
+ break;
+
+ case( WALLPAPER_TOP ):
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ break;
+
+ case( WALLPAPER_TOPRIGHT ):
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ break;
+
+ case( WALLPAPER_LEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ break;
+
+ case( WALLPAPER_CENTER ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_RIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight ) >> 1;
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMLEFT ):
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ break;
+
+ case( WALLPAPER_BOTTOM ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth ) >> 1;
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ case( WALLPAPER_BOTTOMRIGHT ):
+ {
+ aPos.X() += ( aSize.Width() - nBmpWidth );
+ aPos.Y() += ( aSize.Height() - nBmpHeight );
+ }
+ break;
+
+ default:
+ {
+ const long nRight = nX + nWidth - 1L;
+ const long nBottom = nY + nHeight - 1L;
+ long nFirstX;
+ long nFirstY;
+
+ if( eStyle == WALLPAPER_TILE )
+ {
+ nFirstX = aPos.X();
+ nFirstY = aPos.Y();
+ }
+ else
+ {
+ nFirstX = aPos.X() + ( ( aSize.Width() - nBmpWidth ) >> 1 );
+ nFirstY = aPos.Y() + ( ( aSize.Height() - nBmpHeight ) >> 1 );
+ }
+
+ const long nOffX = ( nFirstX - nX ) % nBmpWidth;
+ const long nOffY = ( nFirstY - nY ) % nBmpHeight;
+ long nStartX = nX + nOffX;
+ long nStartY = nY + nOffY;
+
+ if( nOffX > 0L )
+ nStartX -= nBmpWidth;
+
+ if( nOffY > 0L )
+ nStartY -= nBmpHeight;
+
+ for( long nBmpY = nStartY; nBmpY <= nBottom; nBmpY += nBmpHeight )
+ for( long nBmpX = nStartX; nBmpX <= nRight; nBmpX += nBmpWidth )
+ DrawBitmapEx( Point( nBmpX, nBmpY ), aBmpEx );
+
+ bDrawn = true;
+ }
+ break;
+ }
+
+ if( !bDrawn )
+ {
+ // optimized for non-transparent bitmaps
+ if( bDrawColorBackground )
+ {
+ const Size aBmpSize( aBmpEx.GetSizePixel() );
+ const Point aTmpPoint;
+ const Rectangle aOutRect( aTmpPoint, GetOutputSizePixel() );
+ const Rectangle aColRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ Rectangle aWorkRect;
+
+ aWorkRect = Rectangle( 0, 0, aOutRect.Right(), aPos.Y() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y(), aPos.X() - 1L, aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( aPos.X() + aBmpSize.Width(), aPos.Y(), aOutRect.Right(), aPos.Y() + aBmpSize.Height() - 1L );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+
+ aWorkRect = Rectangle( 0, aPos.Y() + aBmpSize.Height(), aOutRect.Right(), aOutRect.Bottom() );
+ aWorkRect.Justify();
+ aWorkRect.Intersection( aColRect );
+ if( !aWorkRect.IsEmpty() )
+ {
+ ImplDrawColorWallpaper( aWorkRect.Left(), aWorkRect.Top(),
+ aWorkRect.GetWidth(), aWorkRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+
+ DrawBitmapEx( aPos, aBmpEx );
+ }
+
+ rWallpaper.ImplGetImpWallpaper()->ImplSetCachedBitmap( aBmpEx );
+
+ Pop();
+ EnableMapMode( bOldMap );
+ mpMetaFile = pOldMetaFile;
+}
+
+void OutputDevice::ImplDrawGradientWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ Rectangle aBound;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const bool bOldMap = mbMap;
+ bool bNeedGradient = true;
+
+ aBound = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
+
+ mpMetaFile = NULL;
+ EnableMapMode( false );
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ) );
+
+ if( OUTDEV_WINDOW == meOutDevType && rWallpaper.GetStyle() == WALLPAPER_APPLICATIONGRADIENT )
+ {
+ Window *pWin = dynamic_cast< Window* >( this );
+ if( pWin )
+ {
+ // limit gradient to useful size, so that it still can be noticed
+ // in maximized windows
+ long gradientWidth = pWin->GetDesktopRectPixel().GetSize().Width();
+ if( gradientWidth > 1024 )
+ gradientWidth = 1024;
+ if( mnOutOffX+nWidth > gradientWidth )
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper.GetGradient().GetEndColor() );
+ if( mnOutOffX > gradientWidth )
+ bNeedGradient = false;
+ else
+ aBound = Rectangle( Point( -mnOutOffX, nY ), Size( gradientWidth, nHeight ) );
+ }
+ }
+
+ if( bNeedGradient )
+ DrawGradient( aBound, rWallpaper.GetGradient() );
+
+ Pop();
+ EnableMapMode( bOldMap );
+ mpMetaFile = pOldMetaFile;
+}
+
+void OutputDevice::ImplDrawWallpaper( long nX, long nY,
+ long nWidth, long nHeight,
+ const Wallpaper& rWallpaper )
+{
+ if( rWallpaper.IsBitmap() )
+ ImplDrawBitmapWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else if( rWallpaper.IsGradient() )
+ ImplDrawGradientWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+ else
+ ImplDrawColorWallpaper( nX, nY, nWidth, nHeight, rWallpaper );
+}
+
+void OutputDevice::DrawWallpaper( const Rectangle& rRect,
+ const Wallpaper& rWallpaper )
+{
+ if ( mpMetaFile )
+ mpMetaFile->AddAction( new MetaWallpaperAction( rRect, rWallpaper ) );
+
+ if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
+ return;
+
+ if ( rWallpaper.GetStyle() != WALLPAPER_NULL )
+ {
+ Rectangle aRect = LogicToPixel( rRect );
+ aRect.Justify();
+
+ if ( !aRect.IsEmpty() )
+ {
+ ImplDrawWallpaper( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(),
+ rWallpaper );
+ }
+ }
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->DrawWallpaper( rRect, rWallpaper );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */