LCOV - code coverage report
Current view: top level - vcl/source/gdi - print2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 562 0.0 %
Date: 2012-08-25 Functions: 0 12 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 1054 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <functional>
      31                 :            : #include <algorithm>
      32                 :            : #include <utility>
      33                 :            : #include <list>
      34                 :            : #include <vector>
      35                 :            : 
      36                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      37                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      38                 :            : 
      39                 :            : #include <tools/debug.hxx>
      40                 :            : 
      41                 :            : #include <vcl/virdev.hxx>
      42                 :            : #include <vcl/metaact.hxx>
      43                 :            : #include <vcl/gdimtf.hxx>
      44                 :            : #include <vcl/print.hxx>
      45                 :            : #include <vcl/svapp.hxx>
      46                 :            : #include <vcl/bmpacc.hxx>
      47                 :            : #include <vcl/rendergraphicrasterizer.hxx>
      48                 :            : 
      49                 :            : #include <print.h>
      50                 :            : 
      51                 :            : #include "pdfwriter_impl.hxx"
      52                 :            : 
      53                 :            : // -----------
      54                 :            : // - Defines -
      55                 :            : // -----------
      56                 :            : 
      57                 :            : #define MAX_TILE_WIDTH  1024
      58                 :            : #define MAX_TILE_HEIGHT 1024
      59                 :            : 
      60                 :            : // ---------
      61                 :            : // - Types -
      62                 :            : // ---------
      63                 :            : 
      64                 :            : typedef ::std::pair< MetaAction*, int > Component; // MetaAction plus index in metafile
      65                 :            : 
      66                 :            : typedef ::std::list< Component > ComponentList;
      67                 :            : 
      68                 :            : // List of (intersecting) actions, plus overall bounds
      69                 :          0 : struct ConnectedComponents
      70                 :            : {
      71                 :          0 :     ConnectedComponents() :
      72                 :            :         aComponentList(),
      73                 :            :         aBounds(),
      74                 :            :         aBgColor(COL_WHITE),
      75                 :            :         bIsSpecial(false),
      76         [ #  # ]:          0 :         bIsFullyTransparent(false)
      77                 :          0 :     {}
      78                 :            : 
      79                 :            :     ComponentList   aComponentList;
      80                 :            :     Rectangle       aBounds;
      81                 :            :     Color           aBgColor;
      82                 :            :     bool            bIsSpecial;
      83                 :            :     bool            bIsFullyTransparent;
      84                 :            : };
      85                 :            : 
      86                 :            : typedef ::std::list< ConnectedComponents > ConnectedComponentsList;
      87                 :            : 
      88                 :            : 
      89                 :            : // -----------
      90                 :            : // - Printer -
      91                 :            : // -----------
      92                 :            : 
      93                 :            : /** #i10613# Extracted from Printer::GetPreparedMetaFile. Returns true
      94                 :            :     if given action requires special handling (usually because of
      95                 :            :     transparency)
      96                 :            : */
      97                 :          0 : static bool ImplIsActionSpecial( const MetaAction& rAct )
      98                 :            : {
      99   [ #  #  #  #  :          0 :     switch( rAct.GetType() )
                #  #  # ]
     100                 :            :     {
     101                 :            :         case META_TRANSPARENT_ACTION:
     102                 :          0 :             return true;
     103                 :            : 
     104                 :            :         case META_FLOATTRANSPARENT_ACTION:
     105                 :          0 :             return true;
     106                 :            : 
     107                 :            :         case META_BMPEX_ACTION:
     108                 :          0 :             return static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx().IsTransparent();
     109                 :            : 
     110                 :            :         case META_BMPEXSCALE_ACTION:
     111                 :          0 :             return static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx().IsTransparent();
     112                 :            : 
     113                 :            :         case META_BMPEXSCALEPART_ACTION:
     114                 :          0 :             return static_cast<const MetaBmpExScalePartAction&>(rAct).GetBitmapEx().IsTransparent();
     115                 :            : 
     116                 :            :         case META_RENDERGRAPHIC_ACTION:
     117                 :          0 :             return true;
     118                 :            : 
     119                 :            :         default:
     120                 :          0 :             return false;
     121                 :            :     }
     122                 :            : }
     123                 :            : 
     124                 :            : /** Check whether rCurrRect rectangle fully covers io_rPrevRect - if
     125                 :            :     yes, return true and update o_rBgColor
     126                 :            :  */
     127                 :          0 : static bool checkRect( Rectangle&       io_rPrevRect,
     128                 :            :                        Color&           o_rBgColor,
     129                 :            :                        const Rectangle& rCurrRect,
     130                 :            :                        OutputDevice&    rMapModeVDev )
     131                 :            : {
     132                 :            :     // shape needs to fully cover previous content, and have uniform
     133                 :            :     // color
     134                 :            :     const bool bRet(
     135 [ #  # ][ #  # ]:          0 :         rMapModeVDev.LogicToPixel(rCurrRect).IsInside(io_rPrevRect) &&
         [ #  # ][ #  # ]
     136 [ #  # ][ #  # ]:          0 :         rMapModeVDev.IsFillColor() );
     137                 :            : 
     138         [ #  # ]:          0 :     if( bRet )
     139                 :            :     {
     140                 :          0 :         io_rPrevRect = rCurrRect;
     141                 :          0 :         o_rBgColor = rMapModeVDev.GetFillColor();
     142                 :            :     }
     143                 :            : 
     144                 :          0 :     return bRet;
     145                 :            : }
     146                 :            : 
     147                 :            : /** #107169# Convert BitmapEx to Bitmap with appropriately blended
     148                 :            :     color. Convert MetaTransparentAction to plain polygon,
     149                 :            :     appropriately colored
     150                 :            : 
     151                 :            :     @param o_rMtf
     152                 :            :     Add converted actions to this metafile
     153                 :            : */
     154                 :          0 : static void ImplConvertTransparentAction( GDIMetaFile&        o_rMtf,
     155                 :            :                                           const MetaAction&   rAct,
     156                 :            :                                           const OutputDevice& rStateOutDev,
     157                 :            :                                           Color               aBgColor )
     158                 :            : {
     159         [ #  # ]:          0 :     if( rAct.GetType() == META_TRANSPARENT_ACTION )
     160                 :            :     {
     161                 :          0 :         const MetaTransparentAction* pTransAct = static_cast<const MetaTransparentAction*>(&rAct);
     162                 :          0 :         sal_uInt16                       nTransparency( pTransAct->GetTransparence() );
     163                 :            : 
     164                 :            :         // #i10613# Respect transparency for draw color
     165         [ #  # ]:          0 :         if( nTransparency )
     166                 :            :         {
     167 [ #  # ][ #  # ]:          0 :             o_rMtf.AddAction( new MetaPushAction( PUSH_LINECOLOR|PUSH_FILLCOLOR ) );
                 [ #  # ]
     168                 :            : 
     169                 :            :             // assume white background for alpha blending
     170                 :          0 :             Color aLineColor( rStateOutDev.GetLineColor() );
     171         [ #  # ]:          0 :             aLineColor.SetRed( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetRed()) / 100L ) );
     172         [ #  # ]:          0 :             aLineColor.SetGreen( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetGreen()) / 100L ) );
     173         [ #  # ]:          0 :             aLineColor.SetBlue( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aLineColor.GetBlue()) / 100L ) );
     174 [ #  # ][ #  # ]:          0 :             o_rMtf.AddAction( new MetaLineColorAction(aLineColor, sal_True) );
                 [ #  # ]
     175                 :            : 
     176                 :          0 :             Color aFillColor( rStateOutDev.GetFillColor() );
     177         [ #  # ]:          0 :             aFillColor.SetRed( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetRed()) / 100L ) );
     178         [ #  # ]:          0 :             aFillColor.SetGreen( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetGreen()) / 100L ) );
     179         [ #  # ]:          0 :             aFillColor.SetBlue( static_cast<sal_uInt8>( (255L*nTransparency + (100L - nTransparency)*aFillColor.GetBlue()) / 100L ) );
     180 [ #  # ][ #  # ]:          0 :             o_rMtf.AddAction( new MetaFillColorAction(aFillColor, sal_True) );
                 [ #  # ]
     181                 :            :         }
     182                 :            : 
     183         [ #  # ]:          0 :         o_rMtf.AddAction( new MetaPolyPolygonAction(pTransAct->GetPolyPolygon()) );
     184                 :            : 
     185         [ #  # ]:          0 :         if( nTransparency )
     186         [ #  # ]:          0 :             o_rMtf.AddAction( new MetaPopAction() );
     187                 :            :     }
     188                 :            :     else
     189                 :            :     {
     190         [ #  # ]:          0 :         BitmapEx aBmpEx;
     191                 :            : 
     192   [ #  #  #  #  :          0 :         switch( rAct.GetType() )
                      # ]
     193                 :            :         {
     194                 :            :             case META_BMPEX_ACTION:
     195         [ #  # ]:          0 :                 aBmpEx = static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx();
     196                 :          0 :                 break;
     197                 :            : 
     198                 :            :             case META_BMPEXSCALE_ACTION:
     199         [ #  # ]:          0 :                 aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx();
     200                 :          0 :                 break;
     201                 :            : 
     202                 :            :             case META_BMPEXSCALEPART_ACTION:
     203         [ #  # ]:          0 :                 aBmpEx = static_cast<const MetaBmpExScaleAction&>(rAct).GetBitmapEx();
     204                 :          0 :                 break;
     205                 :            : 
     206                 :            :             case META_RENDERGRAPHIC_ACTION:
     207                 :            :             {
     208                 :            :                 const ::vcl::RenderGraphicRasterizer aRasterizer( static_cast<const MetaRenderGraphicAction&>(rAct).
     209         [ #  # ]:          0 :                                                                       GetRenderGraphic() );
     210                 :            : 
     211                 :            :                 aBmpEx = aRasterizer.Rasterize( rStateOutDev.LogicToPixel(
     212 [ #  # ][ #  # ]:          0 :                              static_cast<const MetaRenderGraphicAction&>(rAct).GetSize() ) );
                 [ #  # ]
     213         [ #  # ]:          0 :                 break;
     214                 :            :             }
     215                 :            : 
     216                 :            :             case META_TRANSPARENT_ACTION:
     217                 :            : 
     218                 :            :             default:
     219                 :            :                 OSL_FAIL("Printer::GetPreparedMetafile impossible state reached");
     220                 :          0 :                 break;
     221                 :            :         }
     222                 :            : 
     223         [ #  # ]:          0 :         Bitmap aBmp( aBmpEx.GetBitmap() );
     224 [ #  # ][ #  # ]:          0 :         if( !aBmpEx.IsAlpha() )
     225                 :            :         {
     226                 :            :             // blend with mask
     227         [ #  # ]:          0 :             BitmapReadAccess* pRA = aBmp.AcquireReadAccess();
     228                 :            : 
     229         [ #  # ]:          0 :             if( !pRA )
     230                 :          0 :                 return; // what else should I do?
     231                 :            : 
     232                 :          0 :             Color aActualColor( aBgColor );
     233                 :            : 
     234         [ #  # ]:          0 :             if( pRA->HasPalette() )
     235 [ #  # ][ #  # ]:          0 :                 aActualColor = pRA->GetBestPaletteColor( aBgColor ).operator Color();
     236                 :            : 
     237         [ #  # ]:          0 :             aBmp.ReleaseAccess(pRA);
     238                 :            : 
     239                 :            :             // did we get true white?
     240 [ #  # ][ #  # ]:          0 :             if( aActualColor.GetColorError( aBgColor ) )
     241                 :            :             {
     242                 :            :                 // no, create truecolor bitmap, then
     243         [ #  # ]:          0 :                 aBmp.Convert( BMP_CONVERSION_24BIT );
     244                 :            : 
     245                 :            :                 // fill masked out areas white
     246 [ #  # ][ #  # ]:          0 :                 aBmp.Replace( aBmpEx.GetMask(), aBgColor );
                 [ #  # ]
     247                 :            :             }
     248                 :            :             else
     249                 :            :             {
     250                 :            :                 // fill masked out areas white
     251 [ #  # ][ #  # ]:          0 :                 aBmp.Replace( aBmpEx.GetMask(), aActualColor );
                 [ #  # ]
     252                 :            :             }
     253                 :            :         }
     254                 :            :         else
     255                 :            :         {
     256                 :            :             // blend with alpha channel
     257         [ #  # ]:          0 :             aBmp.Convert( BMP_CONVERSION_24BIT );
     258 [ #  # ][ #  # ]:          0 :             aBmp.Blend(aBmpEx.GetAlpha(),aBgColor);
                 [ #  # ]
     259                 :            :         }
     260                 :            : 
     261                 :            :         // add corresponding action
     262   [ #  #  #  #  :          0 :         switch( rAct.GetType() )
                      # ]
     263                 :            :         {
     264                 :            :             case META_BMPEX_ACTION:
     265                 :            :                 o_rMtf.AddAction( new MetaBmpAction(
     266                 :            :                                        static_cast<const MetaBmpExAction&>(rAct).GetPoint(),
     267 [ #  # ][ #  # ]:          0 :                                        aBmp ));
                 [ #  # ]
     268                 :          0 :                 break;
     269                 :            :             case META_BMPEXSCALE_ACTION:
     270                 :            :                 o_rMtf.AddAction( new MetaBmpScaleAction(
     271                 :            :                                        static_cast<const MetaBmpExScaleAction&>(rAct).GetPoint(),
     272                 :            :                                        static_cast<const MetaBmpExScaleAction&>(rAct).GetSize(),
     273 [ #  # ][ #  # ]:          0 :                                        aBmp ));
                 [ #  # ]
     274                 :          0 :                 break;
     275                 :            :             case META_BMPEXSCALEPART_ACTION:
     276                 :            :                 o_rMtf.AddAction( new MetaBmpScalePartAction(
     277                 :            :                                        static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestPoint(),
     278                 :            :                                        static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestSize(),
     279                 :            :                                        static_cast<const MetaBmpExScalePartAction&>(rAct).GetSrcPoint(),
     280                 :            :                                        static_cast<const MetaBmpExScalePartAction&>(rAct).GetSrcSize(),
     281 [ #  # ][ #  # ]:          0 :                                        aBmp ));
                 [ #  # ]
     282                 :          0 :                 break;
     283                 :            :             case META_RENDERGRAPHIC_ACTION:
     284                 :            :                 o_rMtf.AddAction( new MetaBmpScaleAction(
     285                 :            :                                        static_cast<const MetaRenderGraphicAction&>(rAct).GetPoint(),
     286                 :            :                                        static_cast<const MetaRenderGraphicAction&>(rAct).GetSize(),
     287 [ #  # ][ #  # ]:          0 :                                        aBmp ));
                 [ #  # ]
     288                 :            :             default:
     289                 :            :                 OSL_FAIL("Unexpected case");
     290                 :          0 :                 break;
     291 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
     292                 :            :     }
     293                 :            : }
     294                 :            : 
     295                 :            : // #i10613# Extracted from ImplCheckRect::ImplCreate
     296                 :            : // Returns true, if given action creates visible (i.e. non-transparent) output
     297                 :          0 : static bool ImplIsNotTransparent( const MetaAction& rAct, const OutputDevice& rOut )
     298                 :            : {
     299 [ #  # ][ #  # ]:          0 :     const bool  bLineTransparency( rOut.IsLineColor() ? rOut.GetLineColor().GetTransparency() == 255 : true );
     300 [ #  # ][ #  # ]:          0 :     const bool  bFillTransparency( rOut.IsFillColor() ? rOut.GetFillColor().GetTransparency() == 255 : true );
     301                 :          0 :     bool        bRet( false );
     302                 :            : 
     303   [ #  #  #  #  :          0 :     switch( rAct.GetType() )
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     304                 :            :     {
     305                 :            :         case META_POINT_ACTION:
     306         [ #  # ]:          0 :             if( !bLineTransparency )
     307                 :          0 :                 bRet = true;
     308                 :          0 :             break;
     309                 :            : 
     310                 :            :         case META_LINE_ACTION:
     311         [ #  # ]:          0 :             if( !bLineTransparency )
     312                 :          0 :                 bRet = true;
     313                 :          0 :             break;
     314                 :            : 
     315                 :            :         case META_RECT_ACTION:
     316 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     317                 :          0 :                 bRet = true;
     318                 :          0 :             break;
     319                 :            : 
     320                 :            :         case META_ROUNDRECT_ACTION:
     321 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     322                 :          0 :                 bRet = true;
     323                 :          0 :             break;
     324                 :            : 
     325                 :            :         case META_ELLIPSE_ACTION:
     326 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     327                 :          0 :                 bRet = true;
     328                 :          0 :             break;
     329                 :            : 
     330                 :            :         case META_ARC_ACTION:
     331 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     332                 :          0 :                 bRet = true;
     333                 :          0 :             break;
     334                 :            : 
     335                 :            :         case META_PIE_ACTION:
     336 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     337                 :          0 :                 bRet = true;
     338                 :          0 :             break;
     339                 :            : 
     340                 :            :         case META_CHORD_ACTION:
     341 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     342                 :          0 :                 bRet = true;
     343                 :          0 :             break;
     344                 :            : 
     345                 :            :         case META_POLYLINE_ACTION:
     346         [ #  # ]:          0 :             if( !bLineTransparency )
     347                 :          0 :                 bRet = true;
     348                 :          0 :             break;
     349                 :            : 
     350                 :            :         case META_POLYGON_ACTION:
     351 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     352                 :          0 :                 bRet = true;
     353                 :          0 :             break;
     354                 :            : 
     355                 :            :         case META_POLYPOLYGON_ACTION:
     356 [ #  # ][ #  # ]:          0 :             if( !bLineTransparency || !bFillTransparency )
     357                 :          0 :                 bRet = true;
     358                 :          0 :             break;
     359                 :            : 
     360                 :            :         case META_TEXT_ACTION:
     361                 :            :         {
     362                 :          0 :             const MetaTextAction& rTextAct = static_cast<const MetaTextAction&>(rAct);
     363 [ #  # ][ #  # ]:          0 :             const XubString aString( rTextAct.GetText(), rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     364                 :            : 
     365         [ #  # ]:          0 :             if( aString.Len() )
     366         [ #  # ]:          0 :                 bRet = true;
     367                 :            :         }
     368                 :          0 :         break;
     369                 :            : 
     370                 :            :         case META_TEXTARRAY_ACTION:
     371                 :            :         {
     372                 :          0 :             const MetaTextArrayAction& rTextAct = static_cast<const MetaTextArrayAction&>(rAct);
     373 [ #  # ][ #  # ]:          0 :             const XubString aString( rTextAct.GetText(), rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     374                 :            : 
     375         [ #  # ]:          0 :             if( aString.Len() )
     376         [ #  # ]:          0 :                 bRet = true;
     377                 :            :         }
     378                 :          0 :         break;
     379                 :            : 
     380                 :            :         case META_PIXEL_ACTION:
     381                 :            :         case META_BMP_ACTION:
     382                 :            :         case META_BMPSCALE_ACTION:
     383                 :            :         case META_BMPSCALEPART_ACTION:
     384                 :            :         case META_BMPEX_ACTION:
     385                 :            :         case META_BMPEXSCALE_ACTION:
     386                 :            :         case META_BMPEXSCALEPART_ACTION:
     387                 :            :         case META_MASK_ACTION:
     388                 :            :         case META_MASKSCALE_ACTION:
     389                 :            :         case META_MASKSCALEPART_ACTION:
     390                 :            :         case META_GRADIENT_ACTION:
     391                 :            :         case META_GRADIENTEX_ACTION:
     392                 :            :         case META_HATCH_ACTION:
     393                 :            :         case META_WALLPAPER_ACTION:
     394                 :            :         case META_TRANSPARENT_ACTION:
     395                 :            :         case META_FLOATTRANSPARENT_ACTION:
     396                 :            :         case META_EPS_ACTION:
     397                 :            :         case META_TEXTRECT_ACTION:
     398                 :            :         case META_STRETCHTEXT_ACTION:
     399                 :            :         case META_TEXTLINE_ACTION:
     400                 :            :         case META_RENDERGRAPHIC_ACTION:
     401                 :            :             // all other actions: generate non-transparent output
     402                 :          0 :             bRet = true;
     403                 :          0 :             break;
     404                 :            : 
     405                 :            :         default:
     406                 :          0 :             break;
     407                 :            :     }
     408                 :            : 
     409                 :          0 :     return bRet;
     410                 :            : }
     411                 :            : 
     412                 :            : // #i10613# Extracted from ImplCheckRect::ImplCreate
     413                 :          0 : static Rectangle ImplCalcActionBounds( const MetaAction& rAct, const OutputDevice& rOut )
     414                 :            : {
     415         [ #  # ]:          0 :     Rectangle aActionBounds;
     416                 :            : 
     417   [ #  #  #  #  :          0 :     switch( rAct.GetType() )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     418                 :            :     {
     419                 :            :         case META_PIXEL_ACTION:
     420         [ #  # ]:          0 :             aActionBounds = Rectangle( static_cast<const MetaPixelAction&>(rAct).GetPoint(), Size( 1, 1 ) );
     421                 :          0 :             break;
     422                 :            : 
     423                 :            :         case META_POINT_ACTION:
     424         [ #  # ]:          0 :             aActionBounds = Rectangle( static_cast<const MetaPointAction&>(rAct).GetPoint(), Size( 1, 1 ) );
     425                 :          0 :             break;
     426                 :            : 
     427                 :            :         case META_LINE_ACTION:
     428                 :            :         {
     429                 :          0 :             const MetaLineAction& rMetaLineAction = static_cast<const MetaLineAction&>(rAct);
     430         [ #  # ]:          0 :             aActionBounds = Rectangle( rMetaLineAction.GetStartPoint(),  rMetaLineAction.GetEndPoint() );
     431         [ #  # ]:          0 :             aActionBounds.Justify();
     432                 :          0 :             const long nLineWidth(rMetaLineAction.GetLineInfo().GetWidth());
     433         [ #  # ]:          0 :             if(nLineWidth)
     434                 :            :             {
     435                 :          0 :                 const long nHalfLineWidth((nLineWidth + 1) / 2);
     436                 :          0 :                 aActionBounds.Left() -= nHalfLineWidth;
     437                 :          0 :                 aActionBounds.Top() -= nHalfLineWidth;
     438                 :          0 :                 aActionBounds.Right() += nHalfLineWidth;
     439                 :          0 :                 aActionBounds.Bottom() += nHalfLineWidth;
     440                 :            :             }
     441                 :          0 :             break;
     442                 :            :         }
     443                 :            : 
     444                 :            :         case META_RECT_ACTION:
     445                 :          0 :             aActionBounds = static_cast<const MetaRectAction&>(rAct).GetRect();
     446                 :          0 :             break;
     447                 :            : 
     448                 :            :         case META_ROUNDRECT_ACTION:
     449                 :          0 :             aActionBounds = Polygon( static_cast<const MetaRoundRectAction&>(rAct).GetRect(),
     450                 :            :                                      static_cast<const MetaRoundRectAction&>(rAct).GetHorzRound(),
     451 [ #  # ][ #  # ]:          0 :                                      static_cast<const MetaRoundRectAction&>(rAct).GetVertRound() ).GetBoundRect();
                 [ #  # ]
     452                 :          0 :             break;
     453                 :            : 
     454                 :            :         case META_ELLIPSE_ACTION:
     455                 :            :         {
     456                 :          0 :             const Rectangle& rRect = static_cast<const MetaEllipseAction&>(rAct).GetRect();
     457                 :            :             aActionBounds = Polygon( rRect.Center(),
     458         [ #  # ]:          0 :                                      rRect.GetWidth() >> 1,
     459 [ #  # ][ #  # ]:          0 :                                      rRect.GetHeight() >> 1 ).GetBoundRect();
         [ #  # ][ #  # ]
                 [ #  # ]
     460                 :          0 :             break;
     461                 :            :         }
     462                 :            : 
     463                 :            :         case META_ARC_ACTION:
     464                 :          0 :             aActionBounds = Polygon( static_cast<const MetaArcAction&>(rAct).GetRect(),
     465                 :          0 :                                      static_cast<const MetaArcAction&>(rAct).GetStartPoint(),
     466 [ #  # ][ #  # ]:          0 :                                      static_cast<const MetaArcAction&>(rAct).GetEndPoint(), POLY_ARC ).GetBoundRect();
                 [ #  # ]
     467                 :          0 :             break;
     468                 :            : 
     469                 :            :         case META_PIE_ACTION:
     470                 :          0 :             aActionBounds = Polygon( static_cast<const MetaPieAction&>(rAct).GetRect(),
     471                 :          0 :                                      static_cast<const MetaPieAction&>(rAct).GetStartPoint(),
     472 [ #  # ][ #  # ]:          0 :                                      static_cast<const MetaPieAction&>(rAct).GetEndPoint(), POLY_PIE ).GetBoundRect();
                 [ #  # ]
     473                 :          0 :             break;
     474                 :            : 
     475                 :            :         case META_CHORD_ACTION:
     476                 :          0 :             aActionBounds = Polygon( static_cast<const MetaChordAction&>(rAct).GetRect(),
     477                 :          0 :                                      static_cast<const MetaChordAction&>(rAct).GetStartPoint(),
     478 [ #  # ][ #  # ]:          0 :                                      static_cast<const MetaChordAction&>(rAct).GetEndPoint(), POLY_CHORD ).GetBoundRect();
                 [ #  # ]
     479                 :          0 :             break;
     480                 :            : 
     481                 :            :         case META_POLYLINE_ACTION:
     482                 :            :         {
     483                 :          0 :             const MetaPolyLineAction& rMetaPolyLineAction = static_cast<const MetaPolyLineAction&>(rAct);
     484         [ #  # ]:          0 :             aActionBounds = rMetaPolyLineAction.GetPolygon().GetBoundRect();
     485                 :          0 :             const long nLineWidth(rMetaPolyLineAction.GetLineInfo().GetWidth());
     486         [ #  # ]:          0 :             if(nLineWidth)
     487                 :            :             {
     488                 :          0 :                 const long nHalfLineWidth((nLineWidth + 1) / 2);
     489                 :          0 :                 aActionBounds.Left() -= nHalfLineWidth;
     490                 :          0 :                 aActionBounds.Top() -= nHalfLineWidth;
     491                 :          0 :                 aActionBounds.Right() += nHalfLineWidth;
     492                 :          0 :                 aActionBounds.Bottom() += nHalfLineWidth;
     493                 :            :             }
     494                 :          0 :             break;
     495                 :            :         }
     496                 :            : 
     497                 :            :         case META_POLYGON_ACTION:
     498         [ #  # ]:          0 :             aActionBounds = static_cast<const MetaPolygonAction&>(rAct).GetPolygon().GetBoundRect();
     499                 :          0 :             break;
     500                 :            : 
     501                 :            :         case META_POLYPOLYGON_ACTION:
     502         [ #  # ]:          0 :             aActionBounds = static_cast<const MetaPolyPolygonAction&>(rAct).GetPolyPolygon().GetBoundRect();
     503                 :          0 :             break;
     504                 :            : 
     505                 :            :         case META_BMP_ACTION:
     506                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpAction&>(rAct).GetPoint(),
     507         [ #  # ]:          0 :                                        rOut.PixelToLogic( static_cast<const MetaBmpAction&>(rAct).GetBitmap().GetSizePixel() ) );
           [ #  #  #  # ]
     508                 :          0 :             break;
     509                 :            : 
     510                 :            :         case META_BMPSCALE_ACTION:
     511                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpScaleAction&>(rAct).GetPoint(),
     512         [ #  # ]:          0 :                                        static_cast<const MetaBmpScaleAction&>(rAct).GetSize() );
     513                 :          0 :             break;
     514                 :            : 
     515                 :            :         case META_BMPSCALEPART_ACTION:
     516                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpScalePartAction&>(rAct).GetDestPoint(),
     517         [ #  # ]:          0 :                                        static_cast<const MetaBmpScalePartAction&>(rAct).GetDestSize() );
     518                 :          0 :             break;
     519                 :            : 
     520                 :            :         case META_BMPEX_ACTION:
     521                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpExAction&>(rAct).GetPoint(),
     522   [ #  #  #  # ]:          0 :                                        rOut.PixelToLogic( static_cast<const MetaBmpExAction&>(rAct).GetBitmapEx().GetSizePixel() ) );
     523                 :          0 :             break;
     524                 :            : 
     525                 :            :         case META_BMPEXSCALE_ACTION:
     526                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpExScaleAction&>(rAct).GetPoint(),
     527         [ #  # ]:          0 :                                        static_cast<const MetaBmpExScaleAction&>(rAct).GetSize() );
     528                 :          0 :             break;
     529                 :            : 
     530                 :            :         case META_BMPEXSCALEPART_ACTION:
     531                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestPoint(),
     532         [ #  # ]:          0 :                                        static_cast<const MetaBmpExScalePartAction&>(rAct).GetDestSize() );
     533                 :          0 :             break;
     534                 :            : 
     535                 :            :         case META_MASK_ACTION:
     536                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaMaskAction&>(rAct).GetPoint(),
     537         [ #  # ]:          0 :                                        rOut.PixelToLogic( static_cast<const MetaMaskAction&>(rAct).GetBitmap().GetSizePixel() ) );
           [ #  #  #  # ]
     538                 :          0 :             break;
     539                 :            : 
     540                 :            :         case META_MASKSCALE_ACTION:
     541                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaMaskScaleAction&>(rAct).GetPoint(),
     542         [ #  # ]:          0 :                                        static_cast<const MetaMaskScaleAction&>(rAct).GetSize() );
     543                 :          0 :             break;
     544                 :            : 
     545                 :            :         case META_MASKSCALEPART_ACTION:
     546                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaMaskScalePartAction&>(rAct).GetDestPoint(),
     547         [ #  # ]:          0 :                                        static_cast<const MetaMaskScalePartAction&>(rAct).GetDestSize() );
     548                 :          0 :             break;
     549                 :            : 
     550                 :            :         case META_GRADIENT_ACTION:
     551                 :          0 :             aActionBounds = static_cast<const MetaGradientAction&>(rAct).GetRect();
     552                 :          0 :             break;
     553                 :            : 
     554                 :            :         case META_GRADIENTEX_ACTION:
     555         [ #  # ]:          0 :             aActionBounds = static_cast<const MetaGradientExAction&>(rAct).GetPolyPolygon().GetBoundRect();
     556                 :          0 :             break;
     557                 :            : 
     558                 :            :         case META_HATCH_ACTION:
     559         [ #  # ]:          0 :             aActionBounds = static_cast<const MetaHatchAction&>(rAct).GetPolyPolygon().GetBoundRect();
     560                 :          0 :             break;
     561                 :            : 
     562                 :            :         case META_WALLPAPER_ACTION:
     563                 :          0 :             aActionBounds = static_cast<const MetaWallpaperAction&>(rAct).GetRect();
     564                 :          0 :             break;
     565                 :            : 
     566                 :            :         case META_TRANSPARENT_ACTION:
     567         [ #  # ]:          0 :             aActionBounds = static_cast<const MetaTransparentAction&>(rAct).GetPolyPolygon().GetBoundRect();
     568                 :          0 :             break;
     569                 :            : 
     570                 :            :         case META_FLOATTRANSPARENT_ACTION:
     571                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaFloatTransparentAction&>(rAct).GetPoint(),
     572         [ #  # ]:          0 :                                        static_cast<const MetaFloatTransparentAction&>(rAct).GetSize() );
     573                 :          0 :             break;
     574                 :            : 
     575                 :            :         case META_EPS_ACTION:
     576                 :          0 :             aActionBounds = Rectangle( static_cast<const MetaEPSAction&>(rAct).GetPoint(),
     577         [ #  # ]:          0 :                                        static_cast<const MetaEPSAction&>(rAct).GetSize() );
     578                 :          0 :             break;
     579                 :            : 
     580                 :            :         case META_TEXT_ACTION:
     581                 :            :         {
     582                 :          0 :             const MetaTextAction& rTextAct = static_cast<const MetaTextAction&>(rAct);
     583 [ #  # ][ #  # ]:          0 :             const XubString aString( rTextAct.GetText(), rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     584                 :            : 
     585         [ #  # ]:          0 :             if( aString.Len() )
     586                 :            :             {
     587                 :          0 :                 const Point aPtLog( rTextAct.GetPoint() );
     588                 :            : 
     589                 :            :                 // #105987# Use API method instead of Impl* methods
     590                 :            :                 // #107490# Set base parameter equal to index parameter
     591                 :          0 :                 rOut.GetTextBoundRect( aActionBounds, rTextAct.GetText(), rTextAct.GetIndex(),
     592 [ #  # ][ #  # ]:          0 :                                        rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     593         [ #  # ]:          0 :                 aActionBounds.Move( aPtLog.X(), aPtLog.Y() );
     594         [ #  # ]:          0 :             }
     595                 :            :         }
     596                 :          0 :         break;
     597                 :            : 
     598                 :            :         case META_TEXTARRAY_ACTION:
     599                 :            :         {
     600                 :          0 :             const MetaTextArrayAction&  rTextAct = static_cast<const MetaTextArrayAction&>(rAct);
     601 [ #  # ][ #  # ]:          0 :             const XubString             aString( rTextAct.GetText(), rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     602                 :          0 :             const long                  nLen = aString.Len();
     603                 :            : 
     604         [ #  # ]:          0 :             if( nLen )
     605                 :            :             {
     606                 :            :                 // #105987# ImplLayout takes everything in logical coordinates
     607                 :          0 :                 SalLayout* pSalLayout = rOut.ImplLayout( rTextAct.GetText(), rTextAct.GetIndex(),
     608                 :          0 :                                                          rTextAct.GetLen(), rTextAct.GetPoint(),
     609 [ #  # ][ #  # ]:          0 :                                                          0, rTextAct.GetDXArray() );
                 [ #  # ]
     610         [ #  # ]:          0 :                 if( pSalLayout )
     611                 :            :                 {
     612         [ #  # ]:          0 :                     Rectangle aBoundRect( const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect( *pSalLayout ) );
     613         [ #  # ]:          0 :                     aActionBounds = rOut.PixelToLogic( aBoundRect );
     614         [ #  # ]:          0 :                     pSalLayout->Release();
     615                 :            :                 }
     616         [ #  # ]:          0 :             }
     617                 :            :         }
     618                 :          0 :         break;
     619                 :            : 
     620                 :            :         case META_TEXTRECT_ACTION:
     621                 :          0 :             aActionBounds = static_cast<const MetaTextRectAction&>(rAct).GetRect();
     622                 :          0 :             break;
     623                 :            : 
     624                 :            :         case META_STRETCHTEXT_ACTION:
     625                 :            :         {
     626                 :          0 :             const MetaStretchTextAction& rTextAct = static_cast<const MetaStretchTextAction&>(rAct);
     627 [ #  # ][ #  # ]:          0 :             const XubString              aString( rTextAct.GetText(), rTextAct.GetIndex(), rTextAct.GetLen() );
                 [ #  # ]
     628                 :          0 :             const long                   nLen = aString.Len();
     629                 :            : 
     630                 :            :             // #i16195# Literate copy from TextArray action, the
     631                 :            :             // semantics for the ImplLayout call are copied from the
     632                 :            :             // OutDev::DrawStretchText() code. Unfortunately, also in
     633                 :            :             // this case, public outdev methods such as GetTextWidth()
     634                 :            :             // don't provide enough info.
     635         [ #  # ]:          0 :             if( nLen )
     636                 :            :             {
     637                 :            :                 // #105987# ImplLayout takes everything in logical coordinates
     638                 :          0 :                 SalLayout* pSalLayout = rOut.ImplLayout( rTextAct.GetText(), rTextAct.GetIndex(),
     639                 :          0 :                                                          rTextAct.GetLen(), rTextAct.GetPoint(),
     640 [ #  # ][ #  # ]:          0 :                                                          rTextAct.GetWidth() );
                 [ #  # ]
     641         [ #  # ]:          0 :                 if( pSalLayout )
     642                 :            :                 {
     643         [ #  # ]:          0 :                     Rectangle aBoundRect( const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect( *pSalLayout ) );
     644         [ #  # ]:          0 :                     aActionBounds = rOut.PixelToLogic( aBoundRect );
     645         [ #  # ]:          0 :                     pSalLayout->Release();
     646                 :            :                 }
     647         [ #  # ]:          0 :             }
     648                 :            :         }
     649                 :          0 :         break;
     650                 :            : 
     651                 :            :         case META_TEXTLINE_ACTION:
     652                 :            :             OSL_FAIL("META_TEXTLINE_ACTION not supported");
     653                 :          0 :         break;
     654                 :            : 
     655                 :            :         case( META_RENDERGRAPHIC_ACTION ):
     656                 :            :         {
     657                 :          0 :             const MetaRenderGraphicAction& rRenderAct = static_cast<const MetaRenderGraphicAction&>(rAct);
     658         [ #  # ]:          0 :             aActionBounds = Rectangle( rRenderAct.GetPoint(), rRenderAct.GetSize() );
     659                 :            :         }
     660                 :          0 :         break;
     661                 :            : 
     662                 :            :         default:
     663                 :          0 :             break;
     664                 :            :     }
     665                 :            : 
     666 [ #  # ][ #  # ]:          0 :     if( !aActionBounds.IsEmpty() )
     667         [ #  # ]:          0 :         return rOut.LogicToPixel( aActionBounds );
     668                 :            :     else
     669         [ #  # ]:          0 :         return Rectangle();
     670                 :            : }
     671                 :            : 
     672                 :          0 : static bool ImplIsActionHandlingTransparency( const MetaAction& rAct )
     673                 :            : {
     674                 :            :     // META_FLOATTRANSPARENT_ACTION can contain a whole metafile,
     675                 :            :     // which is to be rendered with the given transparent gradient. We
     676                 :            :     // currently cannot emulate transparent painting on a white
     677                 :            :     // background reliably.
     678                 :            : 
     679                 :            :     // the remainder can handle printing itself correctly on a uniform
     680                 :            :     // white background.
     681         [ #  # ]:          0 :     switch( rAct.GetType() )
     682                 :            :     {
     683                 :            :         case META_TRANSPARENT_ACTION:
     684                 :            :         case META_BMPEX_ACTION:
     685                 :            :         case META_BMPEXSCALE_ACTION:
     686                 :            :         case META_BMPEXSCALEPART_ACTION:
     687                 :            :         case META_RENDERGRAPHIC_ACTION:
     688                 :          0 :             return true;
     689                 :            : 
     690                 :            :         default:
     691                 :          0 :             return false;
     692                 :            :     }
     693                 :            : }
     694                 :            : 
     695                 :            : // remove comment to enable highlighting of generated output
     696                 :          0 : bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf, GDIMetaFile& rOutMtf,
     697                 :            :                                                      long nMaxBmpDPIX, long nMaxBmpDPIY,
     698                 :            :                                                      bool bReduceTransparency, bool bTransparencyAutoMode,
     699                 :            :                                                      bool bDownsampleBitmaps,
     700                 :            :                                                      const Color& rBackground
     701                 :            :                                                      )
     702                 :            : {
     703                 :            :     MetaAction*             pCurrAct;
     704                 :          0 :     bool                    bTransparent( false );
     705                 :            : 
     706         [ #  # ]:          0 :     rOutMtf.Clear();
     707                 :            : 
     708 [ #  # ][ #  # ]:          0 :     if( ! bReduceTransparency || bTransparencyAutoMode )
     709                 :            :     {
     710                 :            :         // watch for transparent drawing actions
     711 [ #  # ][ #  # ]:          0 :         for( pCurrAct = ( (GDIMetaFile&) rInMtf ).FirstAction();
         [ #  # ][ #  # ]
     712                 :          0 :              pCurrAct && !bTransparent;
     713         [ #  # ]:          0 :              pCurrAct = ( (GDIMetaFile&) rInMtf ).NextAction() )
     714                 :            :         {
     715                 :            :             // #i10613# Extracted "specialness" predicate into extra method
     716                 :            : 
     717                 :            :             // #107169# Also examine metafiles with masked bitmaps in
     718                 :            :             // detail. Further down, this is optimized in such a way
     719                 :            :             // that there's no unnecessary painting of masked bitmaps
     720                 :            :             // (which are _always_ subdivided into rectangular regions
     721                 :            :             // of uniform opacity): if a masked bitmap is printed over
     722                 :            :             // empty background, we convert to a plain bitmap with
     723                 :            :             // white background.
     724 [ #  # ][ #  # ]:          0 :             if( ImplIsActionSpecial( *pCurrAct ) )
     725                 :            :             {
     726                 :          0 :                 bTransparent = true;
     727                 :            :             }
     728                 :            :         }
     729                 :            :     }
     730                 :            : 
     731                 :            :     // #i10613# Determine set of connected components containing transparent objects. These are
     732                 :            :     // then processed as bitmaps, the original actions are removed from the metafile.
     733         [ #  # ]:          0 :     if( !bTransparent )
     734                 :            :     {
     735                 :            :         // nothing transparent -> just copy
     736         [ #  # ]:          0 :         rOutMtf = rInMtf;
     737                 :            :     }
     738                 :            :     else
     739                 :            :     {
     740                 :            :         // #i10613#
     741                 :            :         // This works as follows: we want a number of distinct sets of
     742                 :            :         // connected components, where each set contains metafile
     743                 :            :         // actions that are intersecting (note: there are possibly
     744                 :            :         // more actions contained as are directly intersecting,
     745                 :            :         // because we can only produce rectangular bitmaps later
     746                 :            :         // on. Thus, each set of connected components is the smallest
     747                 :            :         // enclosing, axis-aligned rectangle that completely bounds a
     748                 :            :         // number of intersecting metafile actions, plus any action
     749                 :            :         // that would otherwise be cut in two). Therefore, we
     750                 :            :         // iteratively add metafile actions from the original metafile
     751                 :            :         // to this connected components list (aCCList), by checking
     752                 :            :         // each element's bounding box against intersection with the
     753                 :            :         // metaaction at hand.
     754                 :            :         // All those intersecting elements are removed from aCCList
     755                 :            :         // and collected in a temporary list (aCCMergeList). After all
     756                 :            :         // elements have been checked, the aCCMergeList elements are
     757                 :            :         // merged with the metaaction at hand into one resulting
     758                 :            :         // connected component, with one big bounding box, and
     759                 :            :         // inserted into aCCList again.
     760                 :            :         // The time complexity of this algorithm is O(n^3), where n is
     761                 :            :         // the number of metafile actions, and it finds all distinct
     762                 :            :         // regions of rectangle-bounded connected components. This
     763                 :            :         // algorithm was designed by AF.
     764                 :            :         //
     765                 :            : 
     766                 :            :         //
     767                 :            :         //  STAGE 1: Detect background
     768                 :            :         //  ==========================
     769                 :            :         //
     770                 :            : 
     771                 :            :         // Receives uniform background content, and is _not_ merged
     772                 :            :         // nor checked for intersection against other aCCList elements
     773         [ #  # ]:          0 :         ConnectedComponents aBackgroundComponent;
     774                 :            : 
     775                 :            :         // create an OutputDevice to record mapmode changes and the like
     776         [ #  # ]:          0 :         VirtualDevice aMapModeVDev;
     777                 :          0 :         aMapModeVDev.mnDPIX = mnDPIX;
     778                 :          0 :         aMapModeVDev.mnDPIY = mnDPIY;
     779         [ #  # ]:          0 :         aMapModeVDev.EnableOutput(sal_False);
     780                 :            : 
     781                 :            :         int nLastBgAction, nActionNum;
     782                 :            : 
     783                 :            :         // weed out page-filling background objects (if they are
     784                 :            :         // uniformly coloured). Keeping them outside the other
     785                 :            :         // connected components often prevents whole-page bitmap
     786                 :            :         // generation.
     787                 :          0 :         bool bStillBackground=true; // true until first non-bg action
     788                 :          0 :         nActionNum=0; nLastBgAction=-1;
     789         [ #  # ]:          0 :         pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction();
     790         [ #  # ]:          0 :         if( rBackground != Color( COL_TRANSPARENT ) )
     791                 :            :         {
     792                 :          0 :             aBackgroundComponent.aBgColor = rBackground;
     793         [ #  # ]:          0 :             if( meOutDevType == OUTDEV_PRINTER )
     794                 :            :             {
     795         [ #  # ]:          0 :                 Printer* pThis = dynamic_cast<Printer*>(this);
     796                 :          0 :                 Point aPageOffset = pThis->GetPageOffsetPixel();
     797                 :          0 :                 aPageOffset = Point( 0, 0 ) - aPageOffset;
     798                 :          0 :                 Size aSize  = pThis->GetPaperSizePixel();
     799         [ #  # ]:          0 :                 aBackgroundComponent.aBounds = Rectangle( aPageOffset, aSize );
     800                 :            :             }
     801                 :            :             else
     802         [ #  # ]:          0 :                 aBackgroundComponent.aBounds = Rectangle( Point( 0, 0 ), GetOutputSizePixel() );
     803                 :            :         }
     804 [ #  # ][ #  # ]:          0 :         while( pCurrAct && bStillBackground )
                 [ #  # ]
     805                 :            :         {
     806   [ #  #  #  #  :          0 :             switch( pCurrAct->GetType() )
                      # ]
     807                 :            :             {
     808                 :            :                 case META_RECT_ACTION:
     809                 :            :                 {
     810         [ #  # ]:          0 :                     if( !checkRect(
     811                 :            :                             aBackgroundComponent.aBounds,
     812                 :            :                             aBackgroundComponent.aBgColor,
     813                 :          0 :                             static_cast<const MetaRectAction*>(pCurrAct)->GetRect(),
     814         [ #  # ]:          0 :                             aMapModeVDev) )
     815                 :          0 :                         bStillBackground=false; // incomplete occlusion of background
     816                 :            :                     else
     817                 :          0 :                         nLastBgAction=nActionNum; // this _is_ background
     818                 :          0 :                     break;
     819                 :            :                 }
     820                 :            :                 case META_POLYGON_ACTION:
     821                 :            :                 {
     822                 :            :                     const Polygon aPoly(
     823         [ #  # ]:          0 :                         static_cast<const MetaPolygonAction*>(pCurrAct)->GetPolygon());
     824 [ #  # ][ #  # ]:          0 :                     if( !basegfx::tools::isRectangle(
                 [ #  # ]
     825 [ #  # ][ #  # ]:          0 :                             aPoly.getB2DPolygon()) ||
         [ #  # ][ #  # ]
                 [ #  # ]
     826                 :            :                         !checkRect(
     827                 :            :                             aBackgroundComponent.aBounds,
     828                 :            :                             aBackgroundComponent.aBgColor,
     829                 :            :                             aPoly.GetBoundRect(),
     830 [ #  # ][ #  # ]:          0 :                             aMapModeVDev) )
         [ #  # ][ #  # ]
     831                 :          0 :                         bStillBackground=false; // incomplete occlusion of background
     832                 :            :                     else
     833                 :          0 :                         nLastBgAction=nActionNum; // this _is_ background
     834         [ #  # ]:          0 :                     break;
     835                 :            :                 }
     836                 :            :                 case META_POLYPOLYGON_ACTION:
     837                 :            :                 {
     838                 :            :                     const PolyPolygon aPoly(
     839         [ #  # ]:          0 :                         static_cast<const MetaPolyPolygonAction*>(pCurrAct)->GetPolyPolygon());
     840 [ #  # ][ #  # ]:          0 :                     if( aPoly.Count() != 1 ||
         [ #  # ][ #  # ]
                 [ #  # ]
     841                 :            :                         !basegfx::tools::isRectangle(
     842 [ #  # ][ #  # ]:          0 :                             aPoly[0].getB2DPolygon()) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     843                 :            :                         !checkRect(
     844                 :            :                             aBackgroundComponent.aBounds,
     845                 :            :                             aBackgroundComponent.aBgColor,
     846                 :            :                             aPoly.GetBoundRect(),
     847 [ #  # ][ #  # ]:          0 :                             aMapModeVDev) )
         [ #  # ][ #  # ]
     848                 :          0 :                         bStillBackground=false; // incomplete occlusion of background
     849                 :            :                     else
     850                 :          0 :                         nLastBgAction=nActionNum; // this _is_ background
     851         [ #  # ]:          0 :                     break;
     852                 :            :                 }
     853                 :            :                 case META_WALLPAPER_ACTION:
     854                 :            :                 {
     855         [ #  # ]:          0 :                     if( !checkRect(
     856                 :            :                             aBackgroundComponent.aBounds,
     857                 :            :                             aBackgroundComponent.aBgColor,
     858                 :          0 :                             static_cast<const MetaWallpaperAction*>(pCurrAct)->GetRect(),
     859         [ #  # ]:          0 :                             aMapModeVDev) )
     860                 :          0 :                         bStillBackground=false; // incomplete occlusion of background
     861                 :            :                     else
     862                 :          0 :                         nLastBgAction=nActionNum; // this _is_ background
     863                 :          0 :                     break;
     864                 :            :                 }
     865                 :            :                 default:
     866                 :            :                 {
     867 [ #  # ][ #  # ]:          0 :                     if( ImplIsNotTransparent( *pCurrAct,
     868                 :          0 :                                               aMapModeVDev ) )
     869                 :          0 :                         bStillBackground=false; // non-transparent action, possibly
     870                 :            :                                                 // not uniform
     871                 :            :                     else
     872                 :            :                         // extend current bounds (next uniform action
     873                 :            :                         // needs to fully cover this area)
     874                 :            :                         aBackgroundComponent.aBounds.Union(
     875 [ #  # ][ #  # ]:          0 :                             ImplCalcActionBounds(*pCurrAct, aMapModeVDev) );
     876                 :          0 :                     break;
     877                 :            :                 }
     878                 :            :             }
     879                 :            : 
     880                 :            :             // execute action to get correct MapModes etc.
     881         [ #  # ]:          0 :             pCurrAct->Execute( &aMapModeVDev );
     882                 :            : 
     883         [ #  # ]:          0 :             pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction();
     884                 :          0 :             ++nActionNum;
     885                 :            :         }
     886                 :            : 
     887                 :            :         // clean up aMapModeVDev
     888         [ #  # ]:          0 :         sal_uInt32 nCount = aMapModeVDev.GetGCStackDepth();
     889         [ #  # ]:          0 :         while( nCount-- )
     890         [ #  # ]:          0 :             aMapModeVDev.Pop();
     891                 :            : 
     892         [ #  # ]:          0 :         ConnectedComponentsList aCCList; // list containing distinct sets of connected components as elements.
     893                 :            : 
     894                 :            :         // fast-forward until one after the last background action
     895                 :            :         // (need to reconstruct map mode vdev state)
     896                 :          0 :         nActionNum=0;
     897         [ #  # ]:          0 :         pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction();
     898 [ #  # ][ #  # ]:          0 :         while( pCurrAct && nActionNum<=nLastBgAction )
                 [ #  # ]
     899                 :            :         {
     900                 :            :             // up to and including last ink-generating background
     901                 :            :             // action go to background component
     902                 :            :             aBackgroundComponent.aComponentList.push_back(
     903                 :            :                 ::std::make_pair(
     904 [ #  # ][ #  # ]:          0 :                     pCurrAct, nActionNum) );
     905                 :            : 
     906                 :            :             // execute action to get correct MapModes etc.
     907         [ #  # ]:          0 :             pCurrAct->Execute( &aMapModeVDev );
     908         [ #  # ]:          0 :             pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction();
     909                 :          0 :             ++nActionNum;
     910                 :            :         }
     911                 :            : 
     912                 :            :         //
     913                 :            :         //  STAGE 2: Generate connected components list
     914                 :            :         //  ===========================================
     915                 :            :         //
     916                 :            : 
     917                 :            :         // iterate over all actions (start where background action
     918                 :            :         // search left off)
     919         [ #  # ]:          0 :         for( ;
     920                 :            :              pCurrAct;
     921         [ #  # ]:          0 :              pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(), ++nActionNum )
     922                 :            :         {
     923                 :            :             // execute action to get correct MapModes etc.
     924         [ #  # ]:          0 :             pCurrAct->Execute( &aMapModeVDev );
     925                 :            : 
     926                 :            :             // cache bounds of current action
     927         [ #  # ]:          0 :             const Rectangle aBBCurrAct( ImplCalcActionBounds(*pCurrAct, aMapModeVDev) );
     928                 :            : 
     929                 :            :             // accumulate collected bounds here, initialize with current action
     930                 :          0 :             Rectangle                               aTotalBounds( aBBCurrAct ); // thus,
     931                 :            :                                                                                 // aTotalComponents.aBounds
     932                 :            :                                                                                 // is
     933                 :            :                                                                                 // empty
     934                 :            :                                                                                 // for
     935                 :            :                                                                                 // non-output-generating
     936                 :            :                                                                                 // actions
     937                 :          0 :             bool                                    bTreatSpecial( false );
     938         [ #  # ]:          0 :             ConnectedComponents                     aTotalComponents;
     939                 :            : 
     940                 :            :             //
     941                 :            :             //  STAGE 2.1: Search for intersecting cc entries
     942                 :            :             //  =============================================
     943                 :            :             //
     944                 :            : 
     945                 :            :             // if aBBCurrAct is empty, it will intersect with no
     946                 :            :             // aCCList member. Thus, we can save the check.
     947                 :            :             // Furthermore, this ensures that non-output-generating
     948                 :            :             // actions get their own aCCList entry, which is necessary
     949                 :            :             // when copying them to the output metafile (see stage 4
     950                 :            :             // below).
     951                 :            : 
     952                 :            :             // #107169# Wholly transparent objects need
     953                 :            :             // not be considered for connected components,
     954                 :            :             // too. Just put each of them into a separate
     955                 :            :             // component.
     956         [ #  # ]:          0 :             aTotalComponents.bIsFullyTransparent = !ImplIsNotTransparent(*pCurrAct, aMapModeVDev);
     957                 :            : 
     958 [ #  # ][ #  # ]:          0 :             if( !aBBCurrAct.IsEmpty() &&
         [ #  # ][ #  # ]
     959                 :          0 :                 !aTotalComponents.bIsFullyTransparent )
     960                 :            :             {
     961 [ #  # ][ #  # ]:          0 :                 if( !aBackgroundComponent.aComponentList.empty() &&
                 [ #  # ]
     962         [ #  # ]:          0 :                     !aBackgroundComponent.aBounds.IsInside(aTotalBounds) )
     963                 :            :                 {
     964                 :            :                     // it seems the background is not large enough. to
     965                 :            :                     // be on the safe side, combine with this component.
     966         [ #  # ]:          0 :                     aTotalBounds.Union( aBackgroundComponent.aBounds );
     967                 :            : 
     968                 :            :                     // extract all aCurr actions to aTotalComponents
     969                 :            :                     aTotalComponents.aComponentList.splice( aTotalComponents.aComponentList.end(),
     970         [ #  # ]:          0 :                                                             aBackgroundComponent.aComponentList );
     971                 :            : 
     972         [ #  # ]:          0 :                     if( aBackgroundComponent.bIsSpecial )
     973                 :          0 :                         bTreatSpecial = true;
     974                 :            :                 }
     975                 :            : 
     976                 :          0 :                 ConnectedComponentsList::iterator       aCurrCC;
     977                 :          0 :                 const ConnectedComponentsList::iterator aLastCC( aCCList.end() );
     978                 :            :                 bool                                    bSomeComponentsChanged;
     979                 :            : 
     980                 :            :                 // now, this is unfortunate: since changing anyone of
     981                 :            :                 // the aCCList elements (e.g. by merging or addition
     982                 :            :                 // of an action) might generate new intersection with
     983                 :            :                 // other aCCList elements, have to repeat the whole
     984                 :            :                 // element scanning, until nothing changes anymore.
     985                 :            :                 // Thus, this loop here makes us O(n^3) in the worst
     986                 :            :                 // case.
     987         [ #  # ]:          0 :                 do
     988                 :            :                 {
     989                 :            :                     // only loop here if 'intersects' branch below was hit
     990                 :          0 :                     bSomeComponentsChanged = false;
     991                 :            : 
     992                 :            :                     // iterate over all current members of aCCList
     993         [ #  # ]:          0 :                     for( aCurrCC=aCCList.begin(); aCurrCC != aLastCC; )
     994                 :            :                     {
     995                 :            :                         // first check if current element's bounds are
     996                 :            :                         // empty. This ensures that empty actions are not
     997                 :            :                         // merged into one component, as a matter of fact,
     998                 :            :                         // they have no position.
     999                 :            : 
    1000                 :            :                         // #107169# Wholly transparent objects need
    1001                 :            :                         // not be considered for connected components,
    1002                 :            :                         // too. Just put each of them into a separate
    1003                 :            :                         // component.
    1004         [ #  # ]:          0 :                         if( !aCurrCC->aBounds.IsEmpty() &&
           [ #  #  #  # ]
         [ #  # ][ #  # ]
    1005                 :          0 :                             !aCurrCC->bIsFullyTransparent &&
    1006         [ #  # ]:          0 :                             aCurrCC->aBounds.IsOver( aTotalBounds ) )
    1007                 :            :                         {
    1008                 :            :                             // union the intersecting aCCList element into aTotalComponents
    1009                 :            : 
    1010                 :            :                             // calc union bounding box
    1011         [ #  # ]:          0 :                             aTotalBounds.Union( aCurrCC->aBounds );
    1012                 :            : 
    1013                 :            :                             // extract all aCurr actions to aTotalComponents
    1014                 :            :                             aTotalComponents.aComponentList.splice( aTotalComponents.aComponentList.end(),
    1015         [ #  # ]:          0 :                                                                     aCurrCC->aComponentList );
    1016                 :            : 
    1017         [ #  # ]:          0 :                             if( aCurrCC->bIsSpecial )
    1018                 :          0 :                                 bTreatSpecial = true;
    1019                 :            : 
    1020                 :            :                             // remove and delete aCurrCC element from list (we've now merged its content)
    1021         [ #  # ]:          0 :                             aCurrCC = aCCList.erase( aCurrCC );
    1022                 :            : 
    1023                 :            :                             // at least one component changed, need to rescan everything
    1024                 :          0 :                             bSomeComponentsChanged = true;
    1025                 :            :                         }
    1026                 :            :                         else
    1027                 :            :                         {
    1028                 :          0 :                             ++aCurrCC;
    1029                 :            :                         }
    1030                 :            :                     }
    1031                 :            :                 }
    1032                 :            :                 while( bSomeComponentsChanged );
    1033                 :            :             }
    1034                 :            : 
    1035                 :            :             //
    1036                 :            :             //  STAGE 2.2: Determine special state for cc element
    1037                 :            :             //  =================================================
    1038                 :            :             //
    1039                 :            : 
    1040                 :            :             // now test whether the whole connected component must be
    1041                 :            :             // treated specially (i.e. rendered as a bitmap): if the
    1042                 :            :             // added action is the very first action, or all actions
    1043                 :            :             // before it are completely transparent, the connected
    1044                 :            :             // component need not be treated specially, not even if
    1045                 :            :             // the added action contains transparency. This is because
    1046                 :            :             // painting of transparent objects on _white background_
    1047                 :            :             // works without alpha compositing (you just calculate the
    1048                 :            :             // color). Note that for the test "all objects before me
    1049                 :            :             // are transparent" no sorting is necessary, since the
    1050                 :            :             // added metaaction pCurrAct is always in the order the
    1051                 :            :             // metafile is painted. Generally, the order of the
    1052                 :            :             // metaactions in the ConnectedComponents are not
    1053                 :            :             // guaranteed to be the same as in the metafile.
    1054         [ #  # ]:          0 :             if( bTreatSpecial )
    1055                 :            :             {
    1056                 :            :                 // prev component(s) special -> this one, too
    1057                 :          0 :                 aTotalComponents.bIsSpecial = true;
    1058                 :            :             }
    1059 [ #  # ][ #  # ]:          0 :             else if( !ImplIsActionSpecial( *pCurrAct ) )
    1060                 :            :             {
    1061                 :            :                 // added action and none of prev components special ->
    1062                 :            :                 // this one normal, too
    1063                 :          0 :                 aTotalComponents.bIsSpecial = false;
    1064                 :            :             }
    1065                 :            :             else
    1066                 :            :             {
    1067                 :            :                 // added action is special and none of prev components
    1068                 :            :                 // special -> do the detailed tests
    1069                 :            : 
    1070                 :            :                 // can the action handle transparency correctly
    1071                 :            :                 // (i.e. when painted on white background, does the
    1072                 :            :                 // action still look correct)?
    1073         [ #  # ]:          0 :                 if( !ImplIsActionHandlingTransparency( *pCurrAct ) )
    1074                 :            :                 {
    1075                 :            :                     // no, action cannot handle its transparency on
    1076                 :            :                     // a printer device, render to bitmap
    1077                 :          0 :                     aTotalComponents.bIsSpecial = true;
    1078                 :            :                 }
    1079                 :            :                 else
    1080                 :            :                 {
    1081                 :            :                     // yes, action can handle its transparency, so
    1082                 :            :                     // check whether we're on white background
    1083         [ #  # ]:          0 :                     if( aTotalComponents.aComponentList.empty() )
    1084                 :            :                     {
    1085                 :            :                         // nothing between pCurrAct and page
    1086                 :            :                         // background -> don't be special
    1087                 :          0 :                         aTotalComponents.bIsSpecial = false;
    1088                 :            :                     }
    1089                 :            :                     else
    1090                 :            :                     {
    1091                 :            :                         // #107169# Fixes abnove now ensure that _no_
    1092                 :            :                         // object in the list is fully transparent. Thus,
    1093                 :            :                         // if the component list is not empty above, we
    1094                 :            :                         // must assume that we have to treat this
    1095                 :            :                         // component special.
    1096                 :            : 
    1097                 :            :                         // there are non-transparent objects between
    1098                 :            :                         // pCurrAct and the empty sheet of paper -> be
    1099                 :            :                         // special, then
    1100                 :          0 :                         aTotalComponents.bIsSpecial = true;
    1101                 :            :                     }
    1102                 :            :                 }
    1103                 :            :             }
    1104                 :            : 
    1105                 :            : 
    1106                 :            :             //
    1107                 :            :             //  STAGE 2.3: Add newly generated CC list element
    1108                 :            :             //  ==============================================
    1109                 :            :             //
    1110                 :            : 
    1111                 :            :             // set new bounds and add action to list
    1112                 :          0 :             aTotalComponents.aBounds = aTotalBounds;
    1113                 :            :             aTotalComponents.aComponentList.push_back(
    1114                 :            :                 ::std::make_pair(
    1115 [ #  # ][ #  # ]:          0 :                     pCurrAct, nActionNum) );
    1116                 :            : 
    1117                 :            :             // add aTotalComponents as a new entry to aCCList
    1118         [ #  # ]:          0 :             aCCList.push_back( aTotalComponents );
    1119                 :            : 
    1120                 :            :             DBG_ASSERT( !aTotalComponents.aComponentList.empty(),
    1121                 :            :                         "Printer::GetPreparedMetaFile empty component" );
    1122                 :            :             DBG_ASSERT( !aTotalComponents.aBounds.IsEmpty() ||
    1123                 :            :                         (aTotalComponents.aBounds.IsEmpty() && aTotalComponents.aComponentList.size() == 1),
    1124                 :            :                         "Printer::GetPreparedMetaFile non-output generating actions must be solitary");
    1125                 :            :             DBG_ASSERT( !aTotalComponents.bIsFullyTransparent ||
    1126                 :            :                         (aTotalComponents.bIsFullyTransparent && aTotalComponents.aComponentList.size() == 1),
    1127                 :            :                         "Printer::GetPreparedMetaFile fully transparent actions must be solitary");
    1128                 :          0 :         }
    1129                 :            : 
    1130                 :            :         // well now, we've got the list of disjunct connected
    1131                 :            :         // components. Now we've got to create a map, which contains
    1132                 :            :         // the corresponding aCCList element for every
    1133                 :            :         // metaaction. Later on, we always process the complete
    1134                 :            :         // metafile for each bitmap to be generated, but switch on
    1135                 :            :         // output only for actions contained in the then current
    1136                 :            :         // aCCList element. This ensures correct mapmode and attribute
    1137                 :            :         // settings for all cases.
    1138                 :            : 
    1139                 :            :         // maps mtf actions to CC list entries
    1140 [ #  # ][ #  # ]:          0 :         ::std::vector< const ConnectedComponents* > aCCList_MemberMap( rInMtf.GetActionSize() );
    1141                 :            : 
    1142                 :            :         // iterate over all aCCList members and their contained metaactions
    1143                 :          0 :         ConnectedComponentsList::iterator       aCurr( aCCList.begin() );
    1144                 :          0 :         const ConnectedComponentsList::iterator aLast( aCCList.end() );
    1145         [ #  # ]:          0 :         for( ; aCurr != aLast; ++aCurr )
    1146                 :            :         {
    1147                 :          0 :             ComponentList::iterator       aCurrentAction( aCurr->aComponentList.begin() );
    1148                 :          0 :             const ComponentList::iterator aLastAction( aCurr->aComponentList.end() );
    1149 [ #  # ][ #  # ]:          0 :             for( ; aCurrentAction != aLastAction; ++aCurrentAction )
                 [ #  # ]
    1150                 :            :             {
    1151                 :            :                 // set pointer to aCCList element for corresponding index
    1152         [ #  # ]:          0 :                 aCCList_MemberMap[ aCurrentAction->second ] = &(*aCurr);
    1153                 :            :             }
    1154                 :            :         }
    1155                 :            : 
    1156                 :            :         //
    1157                 :            :         //  STAGE 3.1: Output background mtf actions (if there are any)
    1158                 :            :         //  ===========================================================
    1159                 :            :         //
    1160                 :            : 
    1161                 :          0 :         ComponentList::iterator       aCurrAct( aBackgroundComponent.aComponentList.begin() );
    1162                 :          0 :         const ComponentList::iterator aLastAct( aBackgroundComponent.aComponentList.end() );
    1163 [ #  # ][ #  # ]:          0 :         for( ; aCurrAct != aLastAct; ++aCurrAct )
                 [ #  # ]
    1164                 :            :         {
    1165                 :            :             // simply add this action (above, we inserted the actions
    1166                 :            :             // starting at index 0 up to and including nLastBgAction)
    1167 [ #  # ][ #  # ]:          0 :             rOutMtf.AddAction( ( aCurrAct->first->Duplicate(), aCurrAct->first ) );
                 [ #  # ]
    1168                 :            :         }
    1169                 :            : 
    1170                 :            : 
    1171                 :            :         //
    1172                 :            :         //  STAGE 3.2: Generate banded bitmaps for special regions
    1173                 :            :         //  ====================================================
    1174                 :            :         //
    1175                 :            : 
    1176                 :          0 :         Point aPageOffset;
    1177                 :          0 :         Size aTmpSize( GetOutputSizePixel() );
    1178         [ #  # ]:          0 :         if( mpPDFWriter )
    1179                 :            :         {
    1180         [ #  # ]:          0 :             aTmpSize = mpPDFWriter->getCurPageSize();
    1181 [ #  # ][ #  # ]:          0 :             aTmpSize = LogicToPixel( aTmpSize, MapMode( MAP_POINT ) );
                 [ #  # ]
    1182                 :            : 
    1183                 :            :             // also add error code to PDFWriter
    1184         [ #  # ]:          0 :             mpPDFWriter->insertError( vcl::PDFWriter::Warning_Transparency_Converted );
    1185                 :            :         }
    1186         [ #  # ]:          0 :         else if( meOutDevType == OUTDEV_PRINTER )
    1187                 :            :         {
    1188         [ #  # ]:          0 :             Printer* pThis = dynamic_cast<Printer*>(this);
    1189                 :          0 :             aPageOffset = pThis->GetPageOffsetPixel();
    1190                 :          0 :             aPageOffset = Point( 0, 0 ) - aPageOffset;
    1191                 :          0 :             aTmpSize  = pThis->GetPaperSizePixel();
    1192                 :            :         }
    1193         [ #  # ]:          0 :         const Rectangle aOutputRect( aPageOffset, aTmpSize );
    1194 [ #  # ][ #  # ]:          0 :         bool bTiling = dynamic_cast<Printer*>(this) != NULL;
    1195                 :            : 
    1196                 :            :         // iterate over all aCCList members and generate bitmaps for the special ones
    1197         [ #  # ]:          0 :         for( aCurr = aCCList.begin(); aCurr != aLast; ++aCurr )
    1198                 :            :         {
    1199         [ #  # ]:          0 :             if( aCurr->bIsSpecial )
    1200                 :            :             {
    1201                 :          0 :                 Rectangle aBoundRect( aCurr->aBounds );
    1202         [ #  # ]:          0 :                 aBoundRect.Intersection( aOutputRect );
    1203                 :            : 
    1204 [ #  # ][ #  # ]:          0 :                 const double fBmpArea( (double) aBoundRect.GetWidth() * aBoundRect.GetHeight() );
    1205 [ #  # ][ #  # ]:          0 :                 const double fOutArea( (double) aOutputRect.GetWidth() * aOutputRect.GetHeight() );
    1206                 :            : 
    1207                 :            :                 // check if output doesn't exceed given size
    1208 [ #  # ][ #  # ]:          0 :                 if( bReduceTransparency && bTransparencyAutoMode && ( fBmpArea > ( 0.25 * fOutArea ) ) )
                 [ #  # ]
    1209                 :            :                 {
    1210                 :            :                     // output normally. Therefore, we simply clear the
    1211                 :            :                     // special attribute, as everything non-special is
    1212                 :            :                     // copied to rOutMtf further below.
    1213                 :          0 :                     aCurr->bIsSpecial = false;
    1214                 :            :                 }
    1215                 :            :                 else
    1216                 :            :                 {
    1217                 :            :                     // create new bitmap action first
    1218 [ #  # ][ #  # ]:          0 :                     if( aBoundRect.GetWidth() && aBoundRect.GetHeight() )
         [ #  # ][ #  # ]
                 [ #  # ]
    1219                 :            :                     {
    1220                 :          0 :                         Point           aDstPtPix( aBoundRect.TopLeft() );
    1221                 :          0 :                         Size            aDstSzPix;
    1222                 :            : 
    1223         [ #  # ]:          0 :                         VirtualDevice   aMapVDev;   // here, we record only mapmode information
    1224         [ #  # ]:          0 :                         aMapVDev.EnableOutput(sal_False);
    1225                 :            : 
    1226         [ #  # ]:          0 :                         VirtualDevice   aPaintVDev; // into this one, we render.
    1227 [ #  # ][ #  # ]:          0 :                         aPaintVDev.SetBackground( aBackgroundComponent.aBgColor );
                 [ #  # ]
    1228                 :            : 
    1229 [ #  # ][ #  # ]:          0 :                         rOutMtf.AddAction( new MetaPushAction( PUSH_MAPMODE ) );
                 [ #  # ]
    1230 [ #  # ][ #  # ]:          0 :                         rOutMtf.AddAction( new MetaMapModeAction() );
                 [ #  # ]
    1231                 :            : 
    1232         [ #  # ]:          0 :                         aPaintVDev.SetDrawMode( GetDrawMode() );
    1233                 :            : 
    1234         [ #  # ]:          0 :                         while( aDstPtPix.Y() <= aBoundRect.Bottom() )
    1235                 :            :                         {
    1236                 :          0 :                             aDstPtPix.X() = aBoundRect.Left();
    1237 [ #  # ][ #  # ]:          0 :                             aDstSzPix = bTiling ? Size( MAX_TILE_WIDTH, MAX_TILE_HEIGHT ) : aBoundRect.GetSize();
         [ #  # ][ #  # ]
    1238                 :            : 
    1239         [ #  # ]:          0 :                             if( ( aDstPtPix.Y() + aDstSzPix.Height() - 1L ) > aBoundRect.Bottom() )
    1240                 :          0 :                                 aDstSzPix.Height() = aBoundRect.Bottom() - aDstPtPix.Y() + 1L;
    1241                 :            : 
    1242         [ #  # ]:          0 :                             while( aDstPtPix.X() <= aBoundRect.Right() )
    1243                 :            :                             {
    1244         [ #  # ]:          0 :                                 if( ( aDstPtPix.X() + aDstSzPix.Width() - 1L ) > aBoundRect.Right() )
    1245                 :          0 :                                     aDstSzPix.Width() = aBoundRect.Right() - aDstPtPix.X() + 1L;
    1246                 :            : 
    1247 [ #  # ][ #  # ]:          0 :                                 if( !Rectangle( aDstPtPix, aDstSzPix ).Intersection( aBoundRect ).IsEmpty() &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    1248         [ #  # ]:          0 :                                     aPaintVDev.SetOutputSizePixel( aDstSzPix ) )
    1249                 :            :                                 {
    1250         [ #  # ]:          0 :                                     aPaintVDev.Push();
    1251         [ #  # ]:          0 :                                     aMapVDev.Push();
    1252                 :            : 
    1253                 :          0 :                                     aMapVDev.mnDPIX = aPaintVDev.mnDPIX = mnDPIX;
    1254                 :          0 :                                     aMapVDev.mnDPIY = aPaintVDev.mnDPIY = mnDPIY;
    1255                 :            : 
    1256         [ #  # ]:          0 :                                     aPaintVDev.EnableOutput(sal_False);
    1257                 :            : 
    1258                 :            :                                     // iterate over all actions
    1259 [ #  # ][ #  # ]:          0 :                                     for( pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(), nActionNum=0;
    1260                 :            :                                          pCurrAct;
    1261         [ #  # ]:          0 :                                          pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(), ++nActionNum )
    1262                 :            :                                     {
    1263                 :            :                                         // enable output only for
    1264                 :            :                                         // actions that are members of
    1265                 :            :                                         // the current aCCList element
    1266                 :            :                                         // (aCurr)
    1267         [ #  # ]:          0 :                                         if( aCCList_MemberMap[nActionNum] == &(*aCurr) )
    1268         [ #  # ]:          0 :                                             aPaintVDev.EnableOutput(sal_True);
    1269                 :            : 
    1270                 :            :                                         // but process every action
    1271                 :          0 :                                         const sal_uInt16 nType( pCurrAct->GetType() );
    1272                 :            : 
    1273         [ #  # ]:          0 :                                         if( META_MAPMODE_ACTION == nType )
    1274                 :            :                                         {
    1275         [ #  # ]:          0 :                                             pCurrAct->Execute( &aMapVDev );
    1276                 :            : 
    1277         [ #  # ]:          0 :                                             MapMode     aMtfMap( aMapVDev.GetMapMode() );
    1278         [ #  # ]:          0 :                                             const Point aNewOrg( aMapVDev.PixelToLogic( aDstPtPix ) );
    1279                 :            : 
    1280         [ #  # ]:          0 :                                             aMtfMap.SetOrigin( Point( -aNewOrg.X(), -aNewOrg.Y() ) );
    1281 [ #  # ][ #  # ]:          0 :                                             aPaintVDev.SetMapMode( aMtfMap );
    1282                 :            :                                         }
    1283 [ #  # ][ #  # ]:          0 :                                         else if( ( META_PUSH_ACTION == nType ) || ( META_POP_ACTION ) == nType )
    1284                 :            :                                         {
    1285         [ #  # ]:          0 :                                             pCurrAct->Execute( &aMapVDev );
    1286         [ #  # ]:          0 :                                             pCurrAct->Execute( &aPaintVDev );
    1287                 :            :                                         }
    1288         [ #  # ]:          0 :                                         else if( META_GRADIENT_ACTION == nType )
    1289                 :            :                                         {
    1290                 :          0 :                                             MetaGradientAction* pGradientAction = static_cast<MetaGradientAction*>(pCurrAct);
    1291         [ #  # ]:          0 :                                             Printer* pPrinter = dynamic_cast< Printer* >(this);
    1292         [ #  # ]:          0 :                                             if( pPrinter )
    1293         [ #  # ]:          0 :                                                 pPrinter->DrawGradientEx( &aPaintVDev, pGradientAction->GetRect(), pGradientAction->GetGradient() );
    1294                 :            :                                             else
    1295         [ #  # ]:          0 :                                                 DrawGradient( pGradientAction->GetRect(), pGradientAction->GetGradient() );
    1296                 :            :                                         }
    1297                 :            :                                         else
    1298                 :            :                                         {
    1299         [ #  # ]:          0 :                                             pCurrAct->Execute( &aPaintVDev );
    1300                 :            :                                         }
    1301                 :            : 
    1302         [ #  # ]:          0 :                                         if( !( nActionNum % 8 ) )
    1303         [ #  # ]:          0 :                                             Application::Reschedule();
    1304                 :            :                                     }
    1305                 :            : 
    1306                 :          0 :                                     const sal_Bool bOldMap = mbMap;
    1307                 :          0 :                                     mbMap = aPaintVDev.mbMap = sal_False;
    1308                 :            : 
    1309         [ #  # ]:          0 :                                     Bitmap aBandBmp( aPaintVDev.GetBitmap( Point(), aDstSzPix ) );
    1310                 :            : 
    1311                 :            :                                     // scale down bitmap, if requested
    1312         [ #  # ]:          0 :                                     if( bDownsampleBitmaps )
    1313                 :            :                                     {
    1314                 :            :                                         aBandBmp = GetDownsampledBitmap( aDstSzPix,
    1315                 :            :                                                                          Point(), aBandBmp.GetSizePixel(),
    1316 [ #  # ][ #  # ]:          0 :                                                                          aBandBmp, nMaxBmpDPIX, nMaxBmpDPIY );
         [ #  # ][ #  # ]
    1317                 :            :                                     }
    1318                 :            : 
    1319 [ #  # ][ #  # ]:          0 :                                     rOutMtf.AddAction( new MetaCommentAction( "PRNSPOOL_TRANSPARENTBITMAP_BEGIN" ) );
                 [ #  # ]
    1320 [ #  # ][ #  # ]:          0 :                                     rOutMtf.AddAction( new MetaBmpScaleAction( aDstPtPix, aDstSzPix, aBandBmp ) );
                 [ #  # ]
    1321 [ #  # ][ #  # ]:          0 :                                     rOutMtf.AddAction( new MetaCommentAction( "PRNSPOOL_TRANSPARENTBITMAP_END" ) );
                 [ #  # ]
    1322                 :            : 
    1323                 :          0 :                                     aPaintVDev.mbMap = sal_True;
    1324                 :          0 :                                     mbMap = bOldMap;
    1325         [ #  # ]:          0 :                                     aMapVDev.Pop();
    1326 [ #  # ][ #  # ]:          0 :                                     aPaintVDev.Pop();
    1327                 :            :                                 }
    1328                 :            : 
    1329                 :            :                                 // overlapping bands to avoid missing lines (e.g. PostScript)
    1330                 :          0 :                                 aDstPtPix.X() += aDstSzPix.Width();
    1331                 :            :                             }
    1332                 :            : 
    1333                 :            :                             // overlapping bands to avoid missing lines (e.g. PostScript)
    1334                 :          0 :                             aDstPtPix.Y() += aDstSzPix.Height();
    1335                 :            :                         }
    1336                 :            : 
    1337 [ #  # ][ #  # ]:          0 :                         rOutMtf.AddAction( new MetaPopAction() );
         [ #  # ][ #  # ]
                 [ #  # ]
    1338                 :            :                     }
    1339                 :            :                 }
    1340                 :            :             }
    1341                 :            :         }
    1342                 :            : 
    1343                 :            :         // clean up aMapModeVDev
    1344         [ #  # ]:          0 :         nCount = aMapModeVDev.GetGCStackDepth();
    1345         [ #  # ]:          0 :         while( nCount-- )
    1346         [ #  # ]:          0 :             aMapModeVDev.Pop();
    1347                 :            : 
    1348                 :            :         //
    1349                 :            :         //  STAGE 4: Copy actions to output metafile
    1350                 :            :         //  ========================================
    1351                 :            :         //
    1352                 :            : 
    1353                 :            :         // iterate over all actions and duplicate the ones not in a
    1354                 :            :         // special aCCList member into rOutMtf
    1355 [ #  # ][ #  # ]:          0 :         for( pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(), nActionNum=0;
    1356                 :            :              pCurrAct;
    1357         [ #  # ]:          0 :              pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(), ++nActionNum )
    1358                 :            :         {
    1359                 :          0 :             const ConnectedComponents* pCurrAssociatedComponent = aCCList_MemberMap[nActionNum];
    1360                 :            : 
    1361                 :            :             // NOTE: This relies on the fact that map-mode or draw
    1362                 :            :             // mode changing actions are solitary aCCList elements and
    1363                 :            :             // have empty bounding boxes, see comment on stage 2.1
    1364                 :            :             // above
    1365 [ #  # ][ #  # ]:          0 :             if( pCurrAssociatedComponent &&
         [ #  # ][ #  # ]
    1366         [ #  # ]:          0 :                 (pCurrAssociatedComponent->aBounds.IsEmpty() ||
    1367                 :          0 :                  !pCurrAssociatedComponent->bIsSpecial) )
    1368                 :            :             {
    1369                 :            :                 // #107169# Treat transparent bitmaps special, if they
    1370                 :            :                 // are the first (or sole) action in their bounds
    1371                 :            :                 // list. Note that we previously ensured that no
    1372                 :            :                 // fully-transparent objects are before us here.
    1373 [ #  # ][ #  # ]:          0 :                 if( ImplIsActionHandlingTransparency( *pCurrAct ) &&
                 [ #  # ]
    1374 [ #  # ][ #  # ]:          0 :                     pCurrAssociatedComponent->aComponentList.begin()->first == pCurrAct )
                 [ #  # ]
    1375                 :            :                 {
    1376                 :            :                     // convert actions, where masked-out parts are of
    1377                 :            :                     // given background color
    1378                 :            :                     ImplConvertTransparentAction(rOutMtf,
    1379                 :            :                                                  *pCurrAct,
    1380                 :            :                                                  aMapModeVDev,
    1381         [ #  # ]:          0 :                                                  aBackgroundComponent.aBgColor);
    1382                 :            :                 }
    1383                 :            :                 else
    1384                 :            :                 {
    1385                 :            :                     // simply add this action
    1386         [ #  # ]:          0 :                     rOutMtf.AddAction( ( pCurrAct->Duplicate(), pCurrAct ) );
    1387                 :            :                 }
    1388                 :            : 
    1389         [ #  # ]:          0 :                 pCurrAct->Execute(&aMapModeVDev);
    1390                 :            :             }
    1391                 :            :         }
    1392                 :            : 
    1393         [ #  # ]:          0 :         rOutMtf.SetPrefMapMode( rInMtf.GetPrefMapMode() );
    1394         [ #  # ]:          0 :         rOutMtf.SetPrefSize( rInMtf.GetPrefSize() );
    1395                 :            :     }
    1396                 :          0 :     return bTransparent;
    1397                 :            : }
    1398                 :            : 
    1399                 :            : // -----------------------------------------------------------------------------
    1400                 :            : 
    1401                 :          0 : Bitmap OutputDevice::GetDownsampledBitmap( const Size& rDstSz,
    1402                 :            :                                            const Point& rSrcPt, const Size& rSrcSz,
    1403                 :            :                                            const Bitmap& rBmp, long nMaxBmpDPIX, long nMaxBmpDPIY )
    1404                 :            : {
    1405                 :          0 :     Bitmap aBmp( rBmp );
    1406                 :            : 
    1407         [ #  # ]:          0 :     if( !aBmp.IsEmpty() )
    1408                 :            :     {
    1409                 :          0 :         Point           aPoint;
    1410 [ #  # ][ #  # ]:          0 :         const Rectangle aBmpRect( aPoint, aBmp.GetSizePixel() );
    1411         [ #  # ]:          0 :         Rectangle       aSrcRect( rSrcPt, rSrcSz );
    1412                 :            : 
    1413                 :            :         // do cropping if neccessary
    1414 [ #  # ][ #  # ]:          0 :         if( aSrcRect.Intersection( aBmpRect ) != aBmpRect )
                 [ #  # ]
    1415                 :            :         {
    1416 [ #  # ][ #  # ]:          0 :             if( !aSrcRect.IsEmpty() )
    1417         [ #  # ]:          0 :                 aBmp.Crop( aSrcRect );
    1418                 :            :             else
    1419         [ #  # ]:          0 :                 aBmp.SetEmpty();
    1420                 :            :         }
    1421                 :            : 
    1422         [ #  # ]:          0 :         if( !aBmp.IsEmpty() )
    1423                 :            :         {
    1424                 :            :             // do downsampling if neccessary
    1425 [ #  # ][ #  # ]:          0 :             Size aDstSizeTwip( PixelToLogic( LogicToPixel( rDstSz ), MAP_TWIP ) );
         [ #  # ][ #  # ]
    1426                 :            : 
    1427                 :            :             // #103209# Normalize size (mirroring has to happen outside of this method)
    1428                 :          0 :             aDstSizeTwip = Size( labs(aDstSizeTwip.Width()), labs(aDstSizeTwip.Height()) );
    1429                 :            : 
    1430         [ #  # ]:          0 :             const Size      aBmpSize( aBmp.GetSizePixel() );
    1431                 :          0 :             const double    fBmpPixelX = aBmpSize.Width();
    1432                 :          0 :             const double    fBmpPixelY = aBmpSize.Height();
    1433                 :          0 :             const double    fMaxPixelX = aDstSizeTwip.Width() * nMaxBmpDPIX / 1440.0;
    1434                 :          0 :             const double    fMaxPixelY = aDstSizeTwip.Height() * nMaxBmpDPIY / 1440.0;
    1435                 :            : 
    1436                 :            :             // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
    1437 [ #  # ][ #  # ]:          0 :             if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
         [ #  # ][ #  # ]
    1438                 :            :                   ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
    1439                 :            :                 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
    1440                 :            :             {
    1441                 :            :                 // do scaling
    1442                 :          0 :                 Size            aNewBmpSize;
    1443                 :          0 :                 const double    fBmpWH = fBmpPixelX / fBmpPixelY;
    1444                 :          0 :                 const double    fMaxWH = fMaxPixelX / fMaxPixelY;
    1445                 :            : 
    1446         [ #  # ]:          0 :                 if( fBmpWH < fMaxWH )
    1447                 :            :                 {
    1448                 :          0 :                     aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
    1449                 :          0 :                     aNewBmpSize.Height() = FRound( fMaxPixelY );
    1450                 :            :                 }
    1451         [ #  # ]:          0 :                 else if( fBmpWH > 0.0 )
    1452                 :            :                 {
    1453                 :          0 :                     aNewBmpSize.Width() = FRound( fMaxPixelX );
    1454                 :          0 :                     aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
    1455                 :            :                 }
    1456                 :            : 
    1457 [ #  # ][ #  # ]:          0 :                 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
                 [ #  # ]
    1458         [ #  # ]:          0 :                     aBmp.Scale( aNewBmpSize );
    1459                 :            :                 else
    1460         [ #  # ]:          0 :                     aBmp.SetEmpty();
    1461                 :            :             }
    1462                 :            :         }
    1463                 :            :     }
    1464                 :            : 
    1465                 :          0 :     return aBmp;
    1466                 :            : }
    1467                 :            : 
    1468                 :            : // -----------------------------------------------------------------------------
    1469                 :            : 
    1470                 :          0 : void Printer::DrawGradientEx( OutputDevice* pOut, const Rectangle& rRect, const Gradient& rGradient )
    1471                 :            : {
    1472                 :          0 :     const PrinterOptions& rPrinterOptions = GetPrinterOptions();
    1473                 :            : 
    1474         [ #  # ]:          0 :     if( rPrinterOptions.IsReduceGradients() )
    1475                 :            :     {
    1476         [ #  # ]:          0 :         if( PRINTER_GRADIENT_STRIPES == rPrinterOptions.GetReducedGradientMode() )
    1477                 :            :         {
    1478 [ #  # ][ #  # ]:          0 :             if( !rGradient.GetSteps() || ( rGradient.GetSteps() > rPrinterOptions.GetReducedGradientStepCount() ) )
                 [ #  # ]
    1479                 :            :             {
    1480         [ #  # ]:          0 :                 Gradient aNewGradient( rGradient );
    1481                 :            : 
    1482         [ #  # ]:          0 :                 aNewGradient.SetSteps( rPrinterOptions.GetReducedGradientStepCount() );
    1483 [ #  # ][ #  # ]:          0 :                 pOut->DrawGradient( rRect, aNewGradient );
    1484                 :            :             }
    1485                 :            :             else
    1486                 :          0 :                 pOut->DrawGradient( rRect, rGradient );
    1487                 :            :         }
    1488                 :            :         else
    1489                 :            :         {
    1490                 :          0 :             const Color&    rStartColor = rGradient.GetStartColor();
    1491                 :          0 :             const Color&    rEndColor = rGradient.GetEndColor();
    1492                 :          0 :             const long      nR = ( ( (long) rStartColor.GetRed() * rGradient.GetStartIntensity() ) / 100L +
    1493                 :          0 :                                    ( (long) rEndColor.GetRed() * rGradient.GetEndIntensity() ) / 100L ) >> 1;
    1494                 :          0 :             const long      nG = ( ( (long) rStartColor.GetGreen() * rGradient.GetStartIntensity() ) / 100L +
    1495                 :          0 :                                    ( (long) rEndColor.GetGreen() * rGradient.GetEndIntensity() ) / 100L ) >> 1;
    1496                 :          0 :             const long      nB = ( ( (long) rStartColor.GetBlue() * rGradient.GetStartIntensity() ) / 100L +
    1497                 :          0 :                                    ( (long) rEndColor.GetBlue() * rGradient.GetEndIntensity() ) / 100L ) >> 1;
    1498                 :          0 :             const Color     aColor( (sal_uInt8) nR, (sal_uInt8) nG, (sal_uInt8) nB );
    1499                 :            : 
    1500         [ #  # ]:          0 :             pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
    1501         [ #  # ]:          0 :             pOut->SetLineColor( aColor );
    1502         [ #  # ]:          0 :             pOut->SetFillColor( aColor );
    1503         [ #  # ]:          0 :             pOut->DrawRect( rRect );
    1504         [ #  # ]:          0 :             pOut->Pop();
    1505                 :            :         }
    1506                 :            :     }
    1507                 :            :     else
    1508                 :          0 :         pOut->DrawGradient( rRect, rGradient );
    1509                 :          0 : }
    1510                 :            : 
    1511                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10