LCOV - code coverage report
Current view: top level - vcl/source/outdev - transparent.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 150 398 37.7 %
Date: 2014-11-03 Functions: 10 14 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : #include <sal/types.h>
      20             : 
      21             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      22             : #include <boost/scoped_array.hpp>
      23             : 
      24             : #include <vcl/outdev.hxx>
      25             : #include <vcl/virdev.hxx>
      26             : #include <vcl/bmpacc.hxx>
      27             : #include <vcl/settings.hxx>
      28             : 
      29             : #include "outdata.hxx"
      30             : #include "salgdi.hxx"
      31             : 
      32             : namespace
      33             : {
      34             :     /**
      35             :      * Perform a safe approximation of a polygon from double-precision
      36             :      * coordinates to integer coordinates, to ensure that it has at least 2
      37             :      * pixels in both X and Y directions.
      38             :      */
      39      141885 :     Polygon toPolygon( const basegfx::B2DPolygon& rPoly )
      40             :     {
      41      141885 :         basegfx::B2DRange aRange = rPoly.getB2DRange();
      42      141885 :         double fW = aRange.getWidth(), fH = aRange.getHeight();
      43      141885 :         if (0.0 < fW && 0.0 < fH && (fW <= 1.0 || fH <= 1.0))
      44             :         {
      45             :             // This polygon not empty but is too small to display.  Approximate it
      46             :             // with a rectangle large enough to be displayed.
      47       22636 :             double nX = aRange.getMinX(), nY = aRange.getMinY();
      48       22636 :             double nW = std::max<double>(1.0, rtl::math::round(fW));
      49       22636 :             double nH = std::max<double>(1.0, rtl::math::round(fH));
      50             : 
      51       22636 :             Polygon aTarget;
      52       22636 :             aTarget.Insert(0, Point(nX, nY));
      53       22636 :             aTarget.Insert(1, Point(nX+nW, nY));
      54       22636 :             aTarget.Insert(2, Point(nX+nW, nY+nH));
      55       22636 :             aTarget.Insert(3, Point(nX, nY+nH));
      56       22636 :             aTarget.Insert(4, Point(nX, nY));
      57       22636 :             return aTarget;
      58             :         }
      59      119249 :         return Polygon(rPoly);
      60             :     }
      61             : 
      62      138212 :     tools::PolyPolygon toPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly )
      63             :     {
      64      138212 :         tools::PolyPolygon aTarget;
      65      280097 :         for (sal_uInt32 i = 0; i < rPolyPoly.count(); ++i)
      66      141885 :             aTarget.Insert(toPolygon(rPolyPoly.getB2DPolygon(i)));
      67             : 
      68      138212 :         return aTarget;
      69             :     }
      70             : }
      71             : 
      72     3874319 : Color OutputDevice::ImplDrawModeToColor( const Color& rColor ) const
      73             : {
      74     3874319 :     Color aColor( rColor );
      75     3874319 :     sal_uLong  nDrawMode = GetDrawMode();
      76             : 
      77     3874319 :     if( nDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
      78             :                       DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE |
      79             :                       DRAWMODE_SETTINGSLINE ) )
      80             :     {
      81           0 :         if( !ImplIsColorTransparent( aColor ) )
      82             :         {
      83           0 :             if( nDrawMode & DRAWMODE_BLACKLINE )
      84             :             {
      85           0 :                 aColor = Color( COL_BLACK );
      86             :             }
      87           0 :             else if( nDrawMode & DRAWMODE_WHITELINE )
      88             :             {
      89           0 :                 aColor = Color( COL_WHITE );
      90             :             }
      91           0 :             else if( nDrawMode & DRAWMODE_GRAYLINE )
      92             :             {
      93           0 :                 const sal_uInt8 cLum = aColor.GetLuminance();
      94           0 :                 aColor = Color( cLum, cLum, cLum );
      95             :             }
      96           0 :             else if( nDrawMode & DRAWMODE_SETTINGSLINE )
      97             :             {
      98           0 :                 aColor = GetSettings().GetStyleSettings().GetFontColor();
      99             :             }
     100             : 
     101           0 :             if( nDrawMode & DRAWMODE_GHOSTEDLINE )
     102             :             {
     103           0 :                 aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
     104           0 :                                 ( aColor.GetGreen() >> 1 ) | 0x80,
     105           0 :                                 ( aColor.GetBlue() >> 1 ) | 0x80);
     106             :             }
     107             :         }
     108             :     }
     109     3874319 :     return aColor;
     110             : }
     111             : 
     112           0 : sal_uInt16 OutputDevice::GetAlphaBitCount() const
     113             : {
     114           0 :     return 0;
     115             : }
     116             : 
     117           0 : bool OutputDevice::HasAlpha()
     118             : {
     119           0 :     return mpAlphaVDev != NULL;
     120             : }
     121             : 
     122           0 : void OutputDevice::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
     123             :                                          const Point& rDestPt, const Size& rDestSize,
     124             :                                          const Point& rSrcPtPixel, const Size& rSrcSizePixel )
     125             : {
     126           0 :     Point       aPt;
     127           0 :     Point       aDestPt( LogicToPixel( rDestPt ) );
     128           0 :     Size        aDestSz( LogicToPixel( rDestSize ) );
     129           0 :     Rectangle   aSrcRect( rSrcPtPixel, rSrcSizePixel );
     130             : 
     131           0 :     aSrcRect.Justify();
     132             : 
     133           0 :     if( !rBmp.IsEmpty() && aSrcRect.GetWidth() && aSrcRect.GetHeight() && aDestSz.Width() && aDestSz.Height() )
     134             :     {
     135           0 :         Bitmap  aPaint( rBmp ), aMask( rMask );
     136           0 :         sal_uLong   nMirrFlags = 0UL;
     137             : 
     138           0 :         if( aMask.GetBitCount() > 1 )
     139           0 :             aMask.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
     140             : 
     141             :         // mirrored horizontically
     142           0 :         if( aDestSz.Width() < 0L )
     143             :         {
     144           0 :             aDestSz.Width() = -aDestSz.Width();
     145           0 :             aDestPt.X() -= ( aDestSz.Width() - 1L );
     146           0 :             nMirrFlags |= BMP_MIRROR_HORZ;
     147             :         }
     148             : 
     149             :         // mirrored vertically
     150           0 :         if( aDestSz.Height() < 0L )
     151             :         {
     152           0 :             aDestSz.Height() = -aDestSz.Height();
     153           0 :             aDestPt.Y() -= ( aDestSz.Height() - 1L );
     154           0 :             nMirrFlags |= BMP_MIRROR_VERT;
     155             :         }
     156             : 
     157             :         // source cropped?
     158           0 :         if( aSrcRect != Rectangle( aPt, aPaint.GetSizePixel() ) )
     159             :         {
     160           0 :             aPaint.Crop( aSrcRect );
     161           0 :             aMask.Crop( aSrcRect );
     162             :         }
     163             : 
     164             :         // destination mirrored
     165           0 :         if( nMirrFlags )
     166             :         {
     167           0 :             aPaint.Mirror( nMirrFlags );
     168           0 :             aMask.Mirror( nMirrFlags );
     169             :         }
     170             : 
     171             :         // we always want to have a mask
     172           0 :         if( aMask.IsEmpty() )
     173             :         {
     174           0 :             aMask = Bitmap( aSrcRect.GetSize(), 1 );
     175           0 :             aMask.Erase( Color( COL_BLACK ) );
     176             :         }
     177             : 
     178             :         // do painting
     179           0 :         const long nSrcWidth = aSrcRect.GetWidth(), nSrcHeight = aSrcRect.GetHeight();
     180             :         long nX, nY; // , nWorkX, nWorkY, nWorkWidth, nWorkHeight;
     181           0 :         boost::scoped_array<long> pMapX(new long[ nSrcWidth + 1 ]);
     182           0 :         boost::scoped_array<long> pMapY(new long[ nSrcHeight + 1 ]);
     183           0 :         const bool bOldMap = mbMap;
     184             : 
     185           0 :         mbMap = false;
     186             : 
     187             :         // create forward mapping tables
     188           0 :         for( nX = 0L; nX <= nSrcWidth; nX++ )
     189           0 :             pMapX[ nX ] = aDestPt.X() + FRound( (double) aDestSz.Width() * nX / nSrcWidth );
     190             : 
     191           0 :         for( nY = 0L; nY <= nSrcHeight; nY++ )
     192           0 :             pMapY[ nY ] = aDestPt.Y() + FRound( (double) aDestSz.Height() * nY / nSrcHeight );
     193             : 
     194             :         // walk through all rectangles of mask
     195           0 :         const vcl::Region aWorkRgn(aMask.CreateRegion(COL_BLACK, Rectangle(Point(), aMask.GetSizePixel())));
     196           0 :         RectangleVector aRectangles;
     197           0 :         aWorkRgn.GetRegionRectangles(aRectangles);
     198             : 
     199           0 :         for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
     200             :         {
     201           0 :             const Point aMapPt(pMapX[aRectIter->Left()], pMapY[aRectIter->Top()]);
     202           0 :             const Size aMapSz( pMapX[aRectIter->Right() + 1] - aMapPt.X(),      // pMapX[L + W] -> L + ((R - L) + 1) -> R + 1
     203           0 :                                pMapY[aRectIter->Bottom() + 1] - aMapPt.Y());    // same for Y
     204           0 :             Bitmap aBandBmp(aPaint);
     205             : 
     206           0 :             aBandBmp.Crop(*aRectIter);
     207           0 :             DrawBitmap(aMapPt, aMapSz, Point(), aBandBmp.GetSizePixel(), aBandBmp, META_BMPSCALEPART_ACTION);
     208           0 :         }
     209             : 
     210           0 :         mbMap = bOldMap;
     211             :     }
     212           0 : }
     213             : 
     214             : // Caution: This method is nearly the same as
     215             : // void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly )
     216             : // so when changes are made here do not forget to make changes there, too
     217             : 
     218      138212 : void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly, double fTransparency)
     219             : {
     220             :     // AW: Do NOT paint empty PolyPolygons
     221      138212 :     if(!rB2DPolyPoly.count())
     222           0 :         return;
     223             : 
     224             :     // we need a graphics
     225      138212 :     if( !mpGraphics && !AcquireGraphics() )
     226           0 :         return;
     227             : 
     228      138212 :     if( mbInitClipRegion )
     229        1573 :         InitClipRegion();
     230             : 
     231      138212 :     if( mbOutputClipped )
     232           0 :         return;
     233             : 
     234      138212 :     if( mbInitLineColor )
     235        8229 :         InitLineColor();
     236             : 
     237      138212 :     if( mbInitFillColor )
     238       75181 :         InitFillColor();
     239             : 
     240      276424 :     if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) &&
     241      138212 :        mpGraphics->supportsOperation(OutDevSupport_B2DDraw) &&
     242           0 :        (ROP_OVERPAINT == GetRasterOp()) )
     243             :     {
     244             :         // b2dpolygon support not implemented yet on non-UNX platforms
     245           0 :         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
     246           0 :         basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
     247             : 
     248             :         // transform the polygon into device space and ensure it is closed
     249           0 :         aB2DPolyPolygon.transform( aTransform );
     250           0 :         aB2DPolyPolygon.setClosed( true );
     251             : 
     252           0 :         bool bDrawnOk = true;
     253           0 :         if( IsFillColor() )
     254           0 :             bDrawnOk = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
     255             : 
     256           0 :         if( bDrawnOk && IsLineColor() )
     257             :         {
     258           0 :             const basegfx::B2DVector aHairlineWidth(1,1);
     259           0 :             const int nPolyCount = aB2DPolyPolygon.count();
     260           0 :             for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
     261             :             {
     262           0 :                 const ::basegfx::B2DPolygon aOnePoly = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
     263           0 :                 mpGraphics->DrawPolyLine( aOnePoly, fTransparency, aHairlineWidth, ::basegfx::B2DLINEJOIN_NONE, com::sun::star::drawing::LineCap_BUTT, this );
     264           0 :             }
     265             :         }
     266             : 
     267           0 :         if( bDrawnOk )
     268             :         {
     269           0 :             if( mpMetaFile )
     270           0 :                 mpMetaFile->AddAction( new MetaTransparentAction( tools::PolyPolygon( rB2DPolyPoly ), static_cast< sal_uInt16 >(fTransparency * 100.0)));
     271             : 
     272           0 :             return;
     273           0 :         }
     274             :     }
     275             : 
     276             :     // fallback to old polygon drawing if needed
     277      138212 :     DrawTransparent(toPolyPolygon(rB2DPolyPoly), static_cast<sal_uInt16>(fTransparency * 100.0));
     278             : }
     279             : 
     280          14 : void OutputDevice::DrawInvisiblePolygon( const tools::PolyPolygon& rPolyPoly )
     281             : {
     282             :     // short circuit if the polygon border is invisible too
     283          14 :     if( !mbLineColor )
     284          28 :         return;
     285             : 
     286             :     // we assume that the border is NOT to be drawn transparently???
     287           0 :     Push( PushFlags::FILLCOLOR );
     288           0 :     SetFillColor();
     289           0 :     DrawPolyPolygon( rPolyPoly );
     290           0 :     Pop();
     291             : }
     292             : 
     293        7112 : bool OutputDevice::DrawTransparentNatively ( const tools::PolyPolygon& rPolyPoly,
     294             :                                              sal_uInt16 nTransparencePercent )
     295             : {
     296        7112 :     bool bDrawn = false;
     297             : 
     298             :     // debug helper:
     299        7112 :     static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
     300             : 
     301       21336 :     if( !pDisableNative &&
     302        7112 :         mpGraphics->supportsOperation( OutDevSupport_B2DDraw )
     303             : #if defined UNX && ! defined MACOSX && ! defined IOS
     304        7112 :         && GetBitCount() > 8
     305             : #endif
     306             : #ifdef WIN32
     307             :         // workaround bad dithering on remote displaying when using GDI+ with toolbar button highlighting
     308             :         && !rPolyPoly.IsRect()
     309             : #endif
     310             :         )
     311             :     {
     312             :         // prepare the graphics device
     313           0 :         if( mbInitClipRegion )
     314           0 :             InitClipRegion();
     315             : 
     316           0 :         if( mbOutputClipped )
     317           0 :             return false;
     318             : 
     319           0 :         if( mbInitLineColor )
     320           0 :             InitLineColor();
     321             : 
     322           0 :         if( mbInitFillColor )
     323           0 :             InitFillColor();
     324             : 
     325             :         // get the polygon in device coordinates
     326           0 :         basegfx::B2DPolyPolygon aB2DPolyPolygon( rPolyPoly.getB2DPolyPolygon() );
     327           0 :         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
     328           0 :         aB2DPolyPolygon.transform( aTransform );
     329             : 
     330           0 :         const double fTransparency = 0.01 * nTransparencePercent;
     331           0 :         if( mbFillColor )
     332             :         {
     333             :             // #i121591#
     334             :             // CAUTION: Only non printing (pixel-renderer) VCL commands from OutputDevices
     335             :             // should be used when printing. Normally this is avoided by the printer being
     336             :             // non-AAed and thus e.g. on WIN GdiPlus calls are not used. It may be necessary
     337             :             // to figure out a way of moving this code to it's own function that is
     338             :             // overriden by the Print class, which will mean we deliberately override the
     339             :             // functionality and we use the fallback some lines below (which is not very good,
     340             :             // though. For now, WinSalGraphics::drawPolyPolygon will detect printer usage and
     341             :             // correct the wrong mapping (see there for details)
     342           0 :             bDrawn = mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, fTransparency, this );
     343             :         }
     344             : 
     345           0 :         if( mbLineColor )
     346             :         {
     347             :             // disable the fill color for now
     348           0 :             mpGraphics->SetFillColor();
     349             :             // draw the border line
     350           0 :             const basegfx::B2DVector aLineWidths( 1, 1 );
     351           0 :             const int nPolyCount = aB2DPolyPolygon.count();
     352           0 :             for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
     353             :             {
     354           0 :                 const ::basegfx::B2DPolygon& rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
     355             :                 bDrawn = mpGraphics->DrawPolyLine( rPolygon, fTransparency, aLineWidths,
     356           0 :                                                    ::basegfx::B2DLINEJOIN_NONE, css::drawing::LineCap_BUTT, this );
     357           0 :             }
     358             :             // prepare to restore the fill color
     359           0 :             mbInitFillColor = mbFillColor;
     360           0 :         }
     361             :     }
     362             : 
     363        7112 :     return bDrawn;
     364             : }
     365             : 
     366        7112 : void OutputDevice::EmulateDrawTransparent ( const tools::PolyPolygon& rPolyPoly,
     367             :                                             sal_uInt16 nTransparencePercent )
     368             : {
     369             :     // debug helper:
     370        7112 :     static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA" );
     371             : 
     372             :     // #110958# Disable alpha VDev, we perform the necessary
     373        7112 :     VirtualDevice* pOldAlphaVDev = mpAlphaVDev;
     374             : 
     375             :     // operation explicitly further below.
     376        7112 :     if( mpAlphaVDev )
     377           0 :         mpAlphaVDev = NULL;
     378             : 
     379        7112 :     GDIMetaFile* pOldMetaFile = mpMetaFile;
     380        7112 :     mpMetaFile = NULL;
     381             : 
     382        7112 :     tools::PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
     383        7112 :     Rectangle aPolyRect( aPolyPoly.GetBoundRect() );
     384        7112 :     Point aPoint;
     385        7112 :     Rectangle aDstRect( aPoint, GetOutputSizePixel() );
     386             : 
     387        7112 :     aDstRect.Intersection( aPolyRect );
     388             : 
     389        7112 :     ClipToPaintRegion( aDstRect );
     390             : 
     391        7112 :     if( !aDstRect.IsEmpty() )
     392             :     {
     393        7112 :         bool bDrawn = false;
     394             : 
     395             :         // #i66849# Added fast path for exactly rectangular
     396             :         // polygons
     397             :         // #i83087# Naturally, system alpha blending cannot
     398             :         // work with separate alpha VDev
     399        7112 :         if( !mpAlphaVDev && !pDisableNative && aPolyPoly.IsRect() )
     400             :         {
     401             :             // setup Graphics only here (other cases delegate
     402             :             // to basic OutDev methods)
     403          32 :             if ( mbInitClipRegion )
     404          10 :                 InitClipRegion();
     405             : 
     406          32 :             if ( mbInitLineColor )
     407          18 :                 InitLineColor();
     408             : 
     409          32 :             if ( mbInitFillColor )
     410          24 :                 InitFillColor();
     411             : 
     412          32 :             Rectangle aLogicPolyRect( rPolyPoly.GetBoundRect() );
     413          32 :             Rectangle aPixelRect( ImplLogicToDevicePixel( aLogicPolyRect ) );
     414             : 
     415          32 :             if( !mbOutputClipped )
     416             :             {
     417          64 :                 bDrawn = mpGraphics->DrawAlphaRect( aPixelRect.Left(), aPixelRect.Top(),
     418             :                     // #i98405# use methods with small g, else one pixel too much will be painted.
     419             :                     // This is because the source is a polygon which when painted would not paint
     420             :                     // the rightmost and lowest pixel line(s), so use one pixel less for the
     421             :                     // rectangle, too.
     422             :                                                     aPixelRect.getWidth(), aPixelRect.getHeight(),
     423          32 :                                                     sal::static_int_cast<sal_uInt8>(nTransparencePercent),
     424          96 :                                                     this );
     425             :             }
     426             :             else
     427             :             {
     428           0 :                 bDrawn = true;
     429             :             }
     430             :         }
     431             : 
     432        7112 :         if( !bDrawn )
     433             :         {
     434        7112 :             VirtualDevice aVDev( *this, 1 );
     435        7112 :             const Size aDstSz( aDstRect.GetSize() );
     436        7112 :             const sal_uInt8 cTrans = (sal_uInt8) MinMax( FRound( nTransparencePercent * 2.55 ), 0, 255 );
     437             : 
     438        7112 :             if( aDstRect.Left() || aDstRect.Top() )
     439        4204 :                 aPolyPoly.Move( -aDstRect.Left(), -aDstRect.Top() );
     440             : 
     441        7112 :             if( aVDev.SetOutputSizePixel( aDstSz ) )
     442             :             {
     443        7112 :                 const bool bOldMap = mbMap;
     444             : 
     445        7112 :                 EnableMapMode( false );
     446             : 
     447        7112 :                 aVDev.SetLineColor( COL_BLACK );
     448        7112 :                 aVDev.SetFillColor( COL_BLACK );
     449        7112 :                 aVDev.DrawPolyPolygon( aPolyPoly );
     450             : 
     451        7112 :                 Bitmap aPaint( GetBitmap( aDstRect.TopLeft(), aDstSz ) );
     452       14224 :                 Bitmap aPolyMask( aVDev.GetBitmap( Point(), aDstSz ) );
     453             : 
     454             :                 // #107766# check for non-empty bitmaps before accessing them
     455        7112 :                 if( !!aPaint && !!aPolyMask )
     456             :                 {
     457        7112 :                     BitmapWriteAccess* pW = aPaint.AcquireWriteAccess();
     458        7112 :                     BitmapReadAccess* pR = aPolyMask.AcquireReadAccess();
     459             : 
     460        7112 :                     if( pW && pR )
     461             :                     {
     462        7112 :                         BitmapColor aPixCol;
     463       14224 :                         const BitmapColor aFillCol( GetFillColor() );
     464       14224 :                         const BitmapColor aWhite( pR->GetBestMatchingColor( Color( COL_WHITE ) ) );
     465       14224 :                         const BitmapColor aBlack( pR->GetBestMatchingColor( Color( COL_BLACK ) ) );
     466        7112 :                         const long nWidth = pW->Width();
     467        7112 :                         const long nHeight = pW->Height();
     468        7112 :                         const long nR = aFillCol.GetRed();
     469        7112 :                         const long nG = aFillCol.GetGreen();
     470        7112 :                         const long nB = aFillCol.GetBlue();
     471             :                         long nX, nY;
     472             : 
     473        7112 :                         if( aPaint.GetBitCount() <= 8 )
     474             :                         {
     475           0 :                             const BitmapPalette& rPal = pW->GetPalette();
     476           0 :                             const sal_uInt16 nCount = rPal.GetEntryCount();
     477           0 :                             BitmapColor* pMap = (BitmapColor*) new sal_uInt8[ nCount * sizeof( BitmapColor ) ];
     478             : 
     479           0 :                             for( sal_uInt16 i = 0; i < nCount; i++ )
     480             :                             {
     481           0 :                                 BitmapColor aCol( rPal[ i ] );
     482           0 :                                 pMap[ i ] = BitmapColor( (sal_uInt8) rPal.GetBestIndex( aCol.Merge( aFillCol, cTrans ) ) );
     483           0 :                             }
     484             : 
     485           0 :                             if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
     486           0 :                                 pW->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
     487             :                             {
     488           0 :                                 const sal_uInt8 cBlack = aBlack.GetIndex();
     489             : 
     490           0 :                                 for( nY = 0; nY < nHeight; nY++ )
     491             :                                 {
     492           0 :                                     Scanline pWScan = pW->GetScanline( nY );
     493           0 :                                     Scanline pRScan = pR->GetScanline( nY );
     494           0 :                                     sal_uInt8 cBit = 128;
     495             : 
     496           0 :                                     for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan++ )
     497             :                                     {
     498           0 :                                         if( !cBit )
     499             :                                         {
     500           0 :                                             cBit = 128;
     501           0 :                                             pRScan += 1;
     502             :                                         }
     503           0 :                                         if( ( *pRScan & cBit ) == cBlack )
     504             :                                         {
     505           0 :                                             *pWScan = (sal_uInt8) pMap[ *pWScan ].GetIndex();
     506             :                                         }
     507             :                                     }
     508             :                                 }
     509             :                             }
     510             :                             else
     511             :                             {
     512           0 :                                 for( nY = 0; nY < nHeight; nY++ )
     513             :                                 {
     514           0 :                                     for( nX = 0; nX < nWidth; nX++ )
     515             :                                     {
     516           0 :                                         if( pR->GetPixel( nY, nX ) == aBlack )
     517             :                                         {
     518           0 :                                             pW->SetPixel( nY, nX, pMap[ pW->GetPixel( nY, nX ).GetIndex() ] );
     519             :                                         }
     520             :                                     }
     521             :                                 }
     522             :                             }
     523           0 :                             delete[] (sal_uInt8*) pMap;
     524             :                         }
     525             :                         else
     526             :                         {
     527       14224 :                             if( pR->GetScanlineFormat() == BMP_FORMAT_1BIT_MSB_PAL &&
     528        7112 :                                 pW->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR )
     529             :                             {
     530        7112 :                                 const sal_uInt8 cBlack = aBlack.GetIndex();
     531             : 
     532      200906 :                                 for( nY = 0; nY < nHeight; nY++ )
     533             :                                 {
     534      193794 :                                     Scanline pWScan = pW->GetScanline( nY );
     535      193794 :                                     Scanline pRScan = pR->GetScanline( nY );
     536      193794 :                                     sal_uInt8 cBit = 128;
     537             : 
     538     8712844 :                                     for( nX = 0; nX < nWidth; nX++, cBit >>= 1, pWScan += 3 )
     539             :                                     {
     540     8519050 :                                         if( !cBit )
     541             :                                         {
     542      912965 :                                             cBit = 128;
     543      912965 :                                             pRScan += 1;
     544             :                                         }
     545     8519050 :                                         if( ( *pRScan & cBit ) == cBlack )
     546             :                                         {
     547     5602028 :                                             pWScan[ 0 ] = COLOR_CHANNEL_MERGE( pWScan[ 0 ], nB, cTrans );
     548     5602028 :                                             pWScan[ 1 ] = COLOR_CHANNEL_MERGE( pWScan[ 1 ], nG, cTrans );
     549     5602028 :                                             pWScan[ 2 ] = COLOR_CHANNEL_MERGE( pWScan[ 2 ], nR, cTrans );
     550             :                                         }
     551             :                                     }
     552             :                                 }
     553             :                             }
     554             :                             else
     555             :                             {
     556           0 :                                 for( nY = 0; nY < nHeight; nY++ )
     557             :                                 {
     558           0 :                                     for( nX = 0; nX < nWidth; nX++ )
     559             :                                     {
     560           0 :                                         if( pR->GetPixel( nY, nX ) == aBlack )
     561             :                                         {
     562           0 :                                             aPixCol = pW->GetColor( nY, nX );
     563           0 :                                             pW->SetPixel( nY, nX, aPixCol.Merge( aFillCol, cTrans ) );
     564             :                                         }
     565             :                                     }
     566             :                                 }
     567             :                             }
     568        7112 :                         }
     569             :                     }
     570             : 
     571        7112 :                     aPolyMask.ReleaseAccess( pR );
     572        7112 :                     aPaint.ReleaseAccess( pW );
     573             : 
     574        7112 :                     DrawBitmap( aDstRect.TopLeft(), aPaint );
     575             : 
     576        7112 :                     EnableMapMode( bOldMap );
     577             : 
     578        7112 :                     if( mbLineColor )
     579             :                     {
     580        6334 :                         Push( PushFlags::FILLCOLOR );
     581        6334 :                         SetFillColor();
     582        6334 :                         DrawPolyPolygon( rPolyPoly );
     583        6334 :                         Pop();
     584             :                     }
     585        7112 :                 }
     586             :             }
     587             :             else
     588             :             {
     589           0 :                 DrawPolyPolygon( rPolyPoly );
     590        7112 :             }
     591             :         }
     592             :     }
     593             : 
     594        7112 :     mpMetaFile = pOldMetaFile;
     595             : 
     596             :     // #110958# Restore disabled alpha VDev
     597        7112 :     mpAlphaVDev = pOldAlphaVDev;
     598        7112 : }
     599             : 
     600      144644 : void OutputDevice::DrawTransparent( const tools::PolyPolygon& rPolyPoly,
     601             :                                     sal_uInt16 nTransparencePercent )
     602             : {
     603             :     // short circuit for drawing an opaque polygon
     604      144644 :     if( (nTransparencePercent < 1) || ((mnDrawMode & DRAWMODE_NOTRANSPARENCY) != 0) )
     605             :     {
     606      137452 :         DrawPolyPolygon( rPolyPoly );
     607      137452 :         return;
     608             :     }
     609             : 
     610             :     // short circuit for drawing an invisible polygon
     611        7192 :     if( !mbFillColor || (nTransparencePercent >= 100) )
     612             :     {
     613          14 :         DrawInvisiblePolygon( rPolyPoly );
     614             :     }
     615             : 
     616             :     // handle metafile recording
     617        7192 :     if( mpMetaFile )
     618          78 :         mpMetaFile->AddAction( new MetaTransparentAction( rPolyPoly, nTransparencePercent ) );
     619             : 
     620        7192 :     bool bDrawn = !IsDeviceOutputNecessary() || ImplIsRecordLayout();
     621        7192 :     if( bDrawn )
     622          80 :         return;
     623             : 
     624             :     // get the device graphics as drawing target
     625        7112 :     if( !mpGraphics && !AcquireGraphics() )
     626           0 :         return;
     627             : 
     628             :     // try hard to draw it directly, because the emulation layers are slower
     629        7112 :     bDrawn = DrawTransparentNatively( rPolyPoly, nTransparencePercent );
     630        7112 :     if( bDrawn )
     631           0 :         return;
     632             : 
     633        7112 :     EmulateDrawTransparent( rPolyPoly, nTransparencePercent );
     634             : 
     635             :     // #110958# Apply alpha value also to VDev alpha channel
     636        7112 :     if( mpAlphaVDev )
     637             :     {
     638           0 :         const Color aFillCol( mpAlphaVDev->GetFillColor() );
     639           0 :         mpAlphaVDev->SetFillColor( Color(sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
     640           0 :                                          sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100),
     641           0 :                                          sal::static_int_cast<sal_uInt8>(255*nTransparencePercent/100)) );
     642             : 
     643           0 :         mpAlphaVDev->DrawTransparent( rPolyPoly, nTransparencePercent );
     644             : 
     645           0 :         mpAlphaVDev->SetFillColor( aFillCol );
     646             :     }
     647             : }
     648             : 
     649           0 : void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
     650             :                                     const Size& rSize, const Gradient& rTransparenceGradient )
     651             : {
     652             : 
     653           0 :     const Color aBlack( COL_BLACK );
     654             : 
     655           0 :     if( mpMetaFile )
     656             :     {
     657             :          // missing here is to map the data using the DeviceTransformation
     658           0 :         mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
     659             :     }
     660             : 
     661           0 :     if ( !IsDeviceOutputNecessary() )
     662           0 :         return;
     663             : 
     664           0 :     if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
     665           0 :         ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
     666             :     {
     667           0 :         ( (GDIMetaFile&) rMtf ).WindStart();
     668           0 :         ( (GDIMetaFile&) rMtf ).Play( this, rPos, rSize );
     669           0 :         ( (GDIMetaFile&) rMtf ).WindStart();
     670             :     }
     671             :     else
     672             :     {
     673           0 :         GDIMetaFile* pOldMetaFile = mpMetaFile;
     674           0 :         Rectangle aOutRect( LogicToPixel( rPos ), LogicToPixel( rSize ) );
     675           0 :         Point aPoint;
     676           0 :         Rectangle aDstRect( aPoint, GetOutputSizePixel() );
     677             : 
     678           0 :         mpMetaFile = NULL;
     679           0 :         aDstRect.Intersection( aOutRect );
     680             : 
     681           0 :         ClipToPaintRegion( aDstRect );
     682             : 
     683           0 :         if( !aDstRect.IsEmpty() )
     684             :         {
     685           0 :             boost::scoped_ptr<VirtualDevice> pVDev(new VirtualDevice);
     686             : 
     687           0 :             ((OutputDevice*)pVDev.get())->mnDPIX = mnDPIX;
     688           0 :             ((OutputDevice*)pVDev.get())->mnDPIY = mnDPIY;
     689             : 
     690           0 :             if( pVDev->SetOutputSizePixel( aDstRect.GetSize() ) )
     691             :             {
     692           0 :                 if(GetAntialiasing())
     693             :                 {
     694             :                     // #i102109#
     695             :                     // For MetaFile replay (see task) it may now be necessary to take
     696             :                     // into account that the content is AntiAlialised and needs to be masked
     697             :                     // like that. Instead of masking, i will use a copy-modify-paste cycle
     698             :                     // here (as i already use in the VclPrimiziveRenderer with successs)
     699           0 :                     pVDev->SetAntialiasing(GetAntialiasing());
     700             : 
     701             :                     // create MapMode for buffer (offset needed) and set
     702           0 :                     MapMode aMap(GetMapMode());
     703           0 :                     const Point aOutPos(PixelToLogic(aDstRect.TopLeft()));
     704           0 :                     aMap.SetOrigin(Point(-aOutPos.X(), -aOutPos.Y()));
     705           0 :                     pVDev->SetMapMode(aMap);
     706             : 
     707             :                     // copy MapMode state and disable for target
     708           0 :                     const bool bOrigMapModeEnabled(IsMapModeEnabled());
     709           0 :                     EnableMapMode(false);
     710             : 
     711             :                     // copy MapMode state and disable for buffer
     712           0 :                     const bool bBufferMapModeEnabled(pVDev->IsMapModeEnabled());
     713           0 :                     pVDev->EnableMapMode(false);
     714             : 
     715             :                     // copy content from original to buffer
     716           0 :                     pVDev->DrawOutDev( aPoint, pVDev->GetOutputSizePixel(), // dest
     717           0 :                                        aDstRect.TopLeft(), pVDev->GetOutputSizePixel(), // source
     718           0 :                                        *this);
     719             : 
     720             :                     // draw MetaFile to buffer
     721           0 :                     pVDev->EnableMapMode(bBufferMapModeEnabled);
     722           0 :                     ((GDIMetaFile&)rMtf).WindStart();
     723           0 :                     ((GDIMetaFile&)rMtf).Play(pVDev.get(), rPos, rSize);
     724           0 :                     ((GDIMetaFile&)rMtf).WindStart();
     725             : 
     726             :                     // get content bitmap from buffer
     727           0 :                     pVDev->EnableMapMode(false);
     728             : 
     729           0 :                     const Bitmap aPaint(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
     730             : 
     731             :                     // create alpha mask from gradient and get as Bitmap
     732           0 :                     pVDev->EnableMapMode(bBufferMapModeEnabled);
     733           0 :                     pVDev->SetDrawMode(DRAWMODE_GRAYGRADIENT);
     734           0 :                     pVDev->DrawGradient(Rectangle(rPos, rSize), rTransparenceGradient);
     735           0 :                     pVDev->SetDrawMode(DRAWMODE_DEFAULT);
     736           0 :                     pVDev->EnableMapMode(false);
     737             : 
     738           0 :                     const AlphaMask aAlpha(pVDev->GetBitmap(aPoint, pVDev->GetOutputSizePixel()));
     739             : 
     740           0 :                     pVDev.reset();
     741             : 
     742             :                     // draw masked content to target and restore MapMode
     743           0 :                     DrawBitmapEx(aDstRect.TopLeft(), BitmapEx(aPaint, aAlpha));
     744           0 :                     EnableMapMode(bOrigMapModeEnabled);
     745             :                 }
     746             :                 else
     747             :                 {
     748           0 :                     Bitmap aPaint, aMask;
     749           0 :                     AlphaMask aAlpha;
     750           0 :                     MapMode aMap( GetMapMode() );
     751           0 :                     Point aOutPos( PixelToLogic( aDstRect.TopLeft() ) );
     752           0 :                     const bool bOldMap = mbMap;
     753             : 
     754           0 :                     aMap.SetOrigin( Point( -aOutPos.X(), -aOutPos.Y() ) );
     755           0 :                     pVDev->SetMapMode( aMap );
     756           0 :                     const bool bVDevOldMap = pVDev->IsMapModeEnabled();
     757             : 
     758             :                     // create paint bitmap
     759           0 :                     ( (GDIMetaFile&) rMtf ).WindStart();
     760           0 :                     ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
     761           0 :                     ( (GDIMetaFile&) rMtf ).WindStart();
     762           0 :                     pVDev->EnableMapMode( false );
     763           0 :                     aPaint = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
     764           0 :                     pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
     765             : 
     766             :                     // create mask bitmap
     767           0 :                     pVDev->SetLineColor( COL_BLACK );
     768           0 :                     pVDev->SetFillColor( COL_BLACK );
     769           0 :                     pVDev->DrawRect( Rectangle( pVDev->PixelToLogic( Point() ), pVDev->GetOutputSize() ) );
     770           0 :                     pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
     771           0 :                                         DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
     772           0 :                     ( (GDIMetaFile&) rMtf ).WindStart();
     773           0 :                     ( (GDIMetaFile&) rMtf ).Play( pVDev.get(), rPos, rSize );
     774           0 :                     ( (GDIMetaFile&) rMtf ).WindStart();
     775           0 :                     pVDev->EnableMapMode( false );
     776           0 :                     aMask = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
     777           0 :                     pVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
     778             : 
     779             :                     // create alpha mask from gradient
     780           0 :                     pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
     781           0 :                     pVDev->DrawGradient( Rectangle( rPos, rSize ), rTransparenceGradient );
     782           0 :                     pVDev->SetDrawMode( DRAWMODE_DEFAULT );
     783           0 :                     pVDev->EnableMapMode( false );
     784           0 :                     pVDev->DrawMask( Point(), pVDev->GetOutputSizePixel(), aMask, Color( COL_WHITE ) );
     785             : 
     786           0 :                     aAlpha = pVDev->GetBitmap( Point(), pVDev->GetOutputSizePixel() );
     787             : 
     788           0 :                     pVDev.reset();
     789             : 
     790           0 :                     EnableMapMode( false );
     791           0 :                     DrawBitmapEx( aDstRect.TopLeft(), BitmapEx( aPaint, aAlpha ) );
     792           0 :                     EnableMapMode( bOldMap );
     793             :                 }
     794           0 :             }
     795             :         }
     796             : 
     797           0 :         mpMetaFile = pOldMetaFile;
     798             :     }
     799        1233 : }
     800             : 
     801             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10