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

Generated by: LCOV version 1.11