LCOV - code coverage report
Current view: top level - vcl/source/gdi - pdfwriter_impl2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 2 821 0.2 %
Date: 2012-08-25 Functions: 2 31 6.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 1300 0.2 %

           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 "pdfwriter_impl.hxx"
      31                 :            : 
      32                 :            : #include "vcl/pdfextoutdevdata.hxx"
      33                 :            : #include "vcl/virdev.hxx"
      34                 :            : #include "vcl/gdimtf.hxx"
      35                 :            : #include "vcl/metaact.hxx"
      36                 :            : #include "vcl/bmpacc.hxx"
      37                 :            : #include "vcl/graph.hxx"
      38                 :            : #include "vcl/rendergraphicrasterizer.hxx"
      39                 :            : 
      40                 :            : #include "svdata.hxx"
      41                 :            : 
      42                 :            : #include "unotools/streamwrap.hxx"
      43                 :            : 
      44                 :            : #include "comphelper/processfactory.hxx"
      45                 :            : #include "comphelper/componentcontext.hxx"
      46                 :            : 
      47                 :            : #include "com/sun/star/beans/PropertyValue.hpp"
      48                 :            : #include "com/sun/star/io/XSeekable.hpp"
      49                 :            : #include "com/sun/star/graphic/GraphicProvider.hpp"
      50                 :            : #include "com/sun/star/graphic/XGraphicProvider.hpp"
      51                 :            : 
      52                 :            : #include "cppuhelper/implbase1.hxx"
      53                 :            : 
      54                 :            : #include <rtl/digest.h>
      55                 :            : 
      56                 :            : #undef USE_PDFGRADIENTS
      57                 :            : 
      58                 :            : using namespace vcl;
      59                 :            : using namespace rtl;
      60                 :            : using namespace com::sun::star;
      61                 :            : using namespace com::sun::star::uno;
      62                 :            : using namespace com::sun::star::beans;
      63                 :            : 
      64                 :            : // -----------------------------------------------------------------------------
      65                 :            : 
      66                 :          0 : void PDFWriterImpl::implWriteGradient( const PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient,
      67                 :            :                                        VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
      68                 :            : {
      69         [ #  # ]:          0 :     GDIMetaFile        aTmpMtf;
      70                 :            : 
      71 [ #  # ][ #  # ]:          0 :     i_pDummyVDev->AddGradientActions( i_rPolyPoly.GetBoundRect(), i_rGradient, aTmpMtf );
      72                 :            : 
      73         [ #  # ]:          0 :     m_rOuterFace.Push();
      74 [ #  # ][ #  # ]:          0 :     m_rOuterFace.IntersectClipRegion( i_rPolyPoly.getB2DPolyPolygon() );
                 [ #  # ]
      75         [ #  # ]:          0 :     playMetafile( aTmpMtf, NULL, i_rContext, i_pDummyVDev );
      76 [ #  # ][ #  # ]:          0 :     m_rOuterFace.Pop();
      77                 :          0 : }
      78                 :            : 
      79                 :            : // -----------------------------------------------------------------------------
      80                 :            : 
      81                 :          0 : void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSize, const BitmapEx& i_rBitmapEx,
      82                 :            :                                        VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
      83                 :            : {
      84 [ #  # ][ #  # ]:          0 :     if ( !i_rBitmapEx.IsEmpty() && i_rSize.Width() && i_rSize.Height() )
         [ #  # ][ #  # ]
      85                 :            :     {
      86         [ #  # ]:          0 :         BitmapEx        aBitmapEx( i_rBitmapEx );
      87                 :          0 :         Point           aPoint( i_rPoint );
      88                 :          0 :         Size            aSize( i_rSize );
      89                 :            : 
      90                 :            :         // #i19065# Negative sizes have mirror semantics on
      91                 :            :         // OutputDevice. BitmapEx and co. have no idea about that, so
      92                 :            :         // perform that _before_ doing anything with aBitmapEx.
      93                 :          0 :         sal_uLong nMirrorFlags(BMP_MIRROR_NONE);
      94         [ #  # ]:          0 :         if( aSize.Width() < 0 )
      95                 :            :         {
      96                 :          0 :             aSize.Width() *= -1;
      97                 :          0 :             aPoint.X() -= aSize.Width();
      98                 :          0 :             nMirrorFlags |= BMP_MIRROR_HORZ;
      99                 :            :         }
     100         [ #  # ]:          0 :         if( aSize.Height() < 0 )
     101                 :            :         {
     102                 :          0 :             aSize.Height() *= -1;
     103                 :          0 :             aPoint.Y() -= aSize.Height();
     104                 :          0 :             nMirrorFlags |= BMP_MIRROR_VERT;
     105                 :            :         }
     106                 :            : 
     107         [ #  # ]:          0 :         if( nMirrorFlags != BMP_MIRROR_NONE )
     108                 :            :         {
     109         [ #  # ]:          0 :             aBitmapEx.Mirror( nMirrorFlags );
     110                 :            :         }
     111         [ #  # ]:          0 :         if( i_rContext.m_nMaxImageResolution > 50 )
     112                 :            :         {
     113                 :            :             // do downsampling if neccessary
     114 [ #  # ][ #  # ]:          0 :             const Size      aDstSizeTwip( i_pDummyVDev->PixelToLogic( i_pDummyVDev->LogicToPixel( aSize ), MAP_TWIP ) );
         [ #  # ][ #  # ]
     115                 :          0 :             const Size      aBmpSize( aBitmapEx.GetSizePixel() );
     116                 :          0 :             const double    fBmpPixelX = aBmpSize.Width();
     117                 :          0 :             const double    fBmpPixelY = aBmpSize.Height();
     118                 :          0 :             const double    fMaxPixelX = aDstSizeTwip.Width() * i_rContext.m_nMaxImageResolution / 1440.0;
     119                 :          0 :             const double    fMaxPixelY = aDstSizeTwip.Height() * i_rContext.m_nMaxImageResolution / 1440.0;
     120                 :            : 
     121                 :            :             // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
     122 [ #  # ][ #  # ]:          0 :             if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
         [ #  # ][ #  # ]
     123                 :            :                 ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
     124                 :            :                 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
     125                 :            :             {
     126                 :            :                 // do scaling
     127                 :          0 :                 Size            aNewBmpSize;
     128                 :          0 :                 const double    fBmpWH = fBmpPixelX / fBmpPixelY;
     129                 :          0 :                 const double    fMaxWH = fMaxPixelX / fMaxPixelY;
     130                 :            : 
     131         [ #  # ]:          0 :                 if( fBmpWH < fMaxWH )
     132                 :            :                 {
     133                 :          0 :                     aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
     134                 :          0 :                     aNewBmpSize.Height() = FRound( fMaxPixelY );
     135                 :            :                 }
     136         [ #  # ]:          0 :                 else if( fBmpWH > 0.0 )
     137                 :            :                 {
     138                 :          0 :                     aNewBmpSize.Width() = FRound( fMaxPixelX );
     139                 :          0 :                     aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
     140                 :            :                 }
     141 [ #  # ][ #  # ]:          0 :                 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
                 [ #  # ]
     142         [ #  # ]:          0 :                     aBitmapEx.Scale( aNewBmpSize, BMP_SCALE_BEST );
     143                 :            :                 else
     144         [ #  # ]:          0 :                     aBitmapEx.SetEmpty();
     145                 :            :             }
     146                 :            :         }
     147                 :            : 
     148                 :          0 :         const Size aSizePixel( aBitmapEx.GetSizePixel() );
     149 [ #  # ][ #  # ]:          0 :         if ( aSizePixel.Width() && aSizePixel.Height() )
                 [ #  # ]
     150                 :            :         {
     151         [ #  # ]:          0 :             if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
     152                 :            :             {
     153                 :          0 :                 BmpConversion eConv = BMP_CONVERSION_8BIT_GREYS;
     154 [ #  # ][ #  # ]:          0 :                 int nDepth = aBitmapEx.GetBitmap().GetBitCount();
                 [ #  # ]
     155         [ #  # ]:          0 :                 if( nDepth <= 4 )
     156                 :          0 :                     eConv = BMP_CONVERSION_4BIT_GREYS;
     157         [ #  # ]:          0 :                 if( nDepth > 1 )
     158         [ #  # ]:          0 :                     aBitmapEx.Convert( eConv );
     159                 :            :             }
     160                 :          0 :             sal_Bool bUseJPGCompression = !i_rContext.m_bOnlyLosslessCompression;
     161 [ #  # ][ #  # ]:          0 :             if ( ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
                 [ #  # ]
     162                 :          0 :                 bUseJPGCompression = sal_False;
     163                 :            : 
     164         [ #  # ]:          0 :             SvMemoryStream  aStrm;
     165         [ #  # ]:          0 :             Bitmap          aMask;
     166                 :            : 
     167                 :          0 :             bool bTrueColorJPG = true;
     168         [ #  # ]:          0 :             if ( bUseJPGCompression )
     169                 :            :             {
     170                 :            :                 sal_uInt32 nZippedFileSize;     // sj: we will calculate the filesize of a zipped bitmap
     171                 :            :                 {                               // to determine if jpeg compression is usefull
     172         [ #  # ]:          0 :                     SvMemoryStream aTemp;
     173                 :          0 :                     aTemp.SetCompressMode( aTemp.GetCompressMode() | COMPRESSMODE_ZBITMAP );
     174                 :          0 :                     aTemp.SetVersion( SOFFICE_FILEFORMAT_40 );  // sj: up from version 40 our bitmap stream operator
     175         [ #  # ]:          0 :                     aTemp << aBitmapEx;                         // is capable of zlib stream compression
     176         [ #  # ]:          0 :                     aTemp.Seek( STREAM_SEEK_TO_END );
     177         [ #  # ]:          0 :                     nZippedFileSize = aTemp.Tell();
     178                 :            :                 }
     179 [ #  # ][ #  # ]:          0 :                 if ( aBitmapEx.IsTransparent() )
     180                 :            :                 {
     181 [ #  # ][ #  # ]:          0 :                     if ( aBitmapEx.IsAlpha() )
     182 [ #  # ][ #  # ]:          0 :                         aMask = aBitmapEx.GetAlpha().GetBitmap();
         [ #  # ][ #  # ]
                 [ #  # ]
     183                 :            :                     else
     184 [ #  # ][ #  # ]:          0 :                         aMask = aBitmapEx.GetMask();
                 [ #  # ]
     185                 :            :                 }
     186 [ #  # ][ #  # ]:          0 :                 Graphic         aGraphic( aBitmapEx.GetBitmap() );
                 [ #  # ]
     187                 :          0 :                 sal_Int32       nColorMode = 0;
     188                 :            : 
     189         [ #  # ]:          0 :                 Sequence< PropertyValue > aFilterData( 2 );
     190 [ #  # ][ #  # ]:          0 :                 aFilterData[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) );
     191 [ #  # ][ #  # ]:          0 :                 aFilterData[ 0 ].Value <<= sal_Int32(i_rContext.m_nJPEGQuality);
     192 [ #  # ][ #  # ]:          0 :                 aFilterData[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) );
     193 [ #  # ][ #  # ]:          0 :                 aFilterData[ 1 ].Value <<= nColorMode;
     194                 :            : 
     195                 :            :                 try
     196                 :            :                 {
     197 [ #  # ][ #  # ]:          0 :                     uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( aStrm );
                 [ #  # ]
     198         [ #  # ]:          0 :                     uno::Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
     199 [ #  # ][ #  # ]:          0 :                     uno::Reference< uno::XComponentContext > xContext( comphelper::ComponentContext(ImplGetSVData()->maAppData.mxMSF).getUNOContext() );
         [ #  # ][ #  # ]
     200         [ #  # ]:          0 :                     uno::Reference< graphic::XGraphicProvider > xGraphicProvider( graphic::GraphicProvider::create(xContext) );
     201         [ #  # ]:          0 :                     uno::Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
     202 [ #  # ][ #  # ]:          0 :                     uno::Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
     203         [ #  # ]:          0 :                     rtl::OUString aMimeType(RTL_CONSTASCII_USTRINGPARAM("image/jpeg"));
     204         [ #  # ]:          0 :                     uno::Sequence< beans::PropertyValue > aOutMediaProperties( 3 );
     205 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OutputStream"));
     206 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[0].Value <<= xOut;
     207 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MimeType"));
     208 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[1].Value <<= aMimeType;
     209 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FilterData"));
     210 [ #  # ][ #  # ]:          0 :                     aOutMediaProperties[2].Value <<= aFilterData;
     211 [ #  # ][ #  # ]:          0 :                     xGraphicProvider->storeGraphic( xGraphic, aOutMediaProperties );
     212 [ #  # ][ #  # ]:          0 :                     xOut->flush();
     213 [ #  # ][ #  # ]:          0 :                     if ( xSeekable->getLength() > nZippedFileSize )
                 [ #  # ]
     214                 :            :                     {
     215                 :          0 :                         bUseJPGCompression = sal_False;
     216                 :            :                     }
     217                 :            :                     else
     218                 :            :                     {
     219         [ #  # ]:          0 :                         aStrm.Seek( STREAM_SEEK_TO_END );
     220                 :            : 
     221 [ #  # ][ #  # ]:          0 :                         xSeekable->seek( 0 );
     222         [ #  # ]:          0 :                         Sequence< PropertyValue > aArgs( 1 );
     223 [ #  # ][ #  # ]:          0 :                         aArgs[ 0 ].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream"));
     224 [ #  # ][ #  # ]:          0 :                         aArgs[ 0 ].Value <<= xStream;
     225 [ #  # ][ #  # ]:          0 :                         uno::Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
     226         [ #  # ]:          0 :                         if ( xPropSet.is() )
     227                 :            :                         {
     228                 :          0 :                             sal_Int16 nBitsPerPixel = 24;
     229 [ #  # ][ #  # ]:          0 :                             if ( xPropSet->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BitsPerPixel")) ) >>= nBitsPerPixel )
         [ #  # ][ #  # ]
     230                 :            :                             {
     231                 :          0 :                                 bTrueColorJPG = nBitsPerPixel != 8;
     232                 :            :                             }
     233         [ #  # ]:          0 :                         }
     234 [ #  # ][ #  # ]:          0 :                     }
     235                 :            :                 }
     236         [ #  # ]:          0 :                 catch( uno::Exception& )
     237                 :            :                 {
     238                 :          0 :                     bUseJPGCompression = sal_False;
     239 [ #  # ][ #  # ]:          0 :                 }
     240                 :            :             }
     241         [ #  # ]:          0 :             if ( bUseJPGCompression )
     242 [ #  # ][ #  # ]:          0 :                 m_rOuterFace.DrawJPGBitmap( aStrm, bTrueColorJPG, aSizePixel, Rectangle( aPoint, aSize ), aMask );
     243 [ #  # ][ #  # ]:          0 :             else if ( aBitmapEx.IsTransparent() )
     244         [ #  # ]:          0 :                 m_rOuterFace.DrawBitmapEx( aPoint, aSize, aBitmapEx );
     245                 :            :             else
     246 [ #  # ][ #  # ]:          0 :                 m_rOuterFace.DrawBitmap( aPoint, aSize, aBitmapEx.GetBitmap() );
         [ #  # ][ #  # ]
                 [ #  # ]
     247         [ #  # ]:          0 :         }
     248                 :            :     }
     249                 :          0 : }
     250                 :            : 
     251                 :            : 
     252                 :            : // -----------------------------------------------------------------------------
     253                 :            : 
     254                 :          0 : void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevData* i_pOutDevData, const vcl::PDFWriter::PlayMetafileContext& i_rContext, VirtualDevice* pDummyVDev )
     255                 :            : {
     256                 :          0 :     bool bAssertionFired( false );
     257                 :            : 
     258                 :          0 :     VirtualDevice* pPrivateDevice = NULL;
     259         [ #  # ]:          0 :     if( ! pDummyVDev )
     260                 :            :     {
     261 [ #  # ][ #  # ]:          0 :         pPrivateDevice = pDummyVDev = new VirtualDevice();
     262         [ #  # ]:          0 :         pDummyVDev->EnableOutput( sal_False );
     263         [ #  # ]:          0 :         pDummyVDev->SetMapMode( i_rMtf.GetPrefMapMode() );
     264                 :            :     }
     265         [ #  # ]:          0 :     GDIMetaFile aMtf( i_rMtf );
     266                 :            : 
     267 [ #  # ][ #  # ]:          0 :     for( sal_uInt32 i = 0, nCount = aMtf.GetActionSize(); i < (sal_uInt32)nCount; )
     268                 :            :     {
     269 [ #  # ][ #  # ]:          0 :         if ( !i_pOutDevData || !i_pOutDevData->PlaySyncPageAct( m_rOuterFace, i ) )
         [ #  # ][ #  # ]
     270                 :            :         {
     271         [ #  # ]:          0 :             const MetaAction*   pAction = aMtf.GetAction( i );
     272                 :          0 :             const sal_uInt16        nType = pAction->GetType();
     273                 :            : 
     274   [ #  #  #  #  :          0 :             switch( nType )
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     275                 :            :             {
     276                 :            :                 case( META_PIXEL_ACTION ):
     277                 :            :                 {
     278                 :          0 :                     const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
     279         [ #  # ]:          0 :                     m_rOuterFace.DrawPixel( pA->GetPoint(), pA->GetColor() );
     280                 :            :                 }
     281                 :          0 :                 break;
     282                 :            : 
     283                 :            :                 case( META_POINT_ACTION ):
     284                 :            :                 {
     285                 :          0 :                     const MetaPointAction* pA = (const MetaPointAction*) pAction;
     286         [ #  # ]:          0 :                     m_rOuterFace.DrawPixel( pA->GetPoint() );
     287                 :            :                 }
     288                 :          0 :                 break;
     289                 :            : 
     290                 :            :                 case( META_LINE_ACTION ):
     291                 :            :                 {
     292                 :          0 :                     const MetaLineAction* pA = (const MetaLineAction*) pAction;
     293         [ #  # ]:          0 :                     if ( pA->GetLineInfo().IsDefault() )
     294         [ #  # ]:          0 :                         m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint() );
     295                 :            :                     else
     296         [ #  # ]:          0 :                         m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint(), pA->GetLineInfo() );
     297                 :            :                 }
     298                 :          0 :                 break;
     299                 :            : 
     300                 :            :                 case( META_RECT_ACTION ):
     301                 :            :                 {
     302                 :          0 :                     const MetaRectAction* pA = (const MetaRectAction*) pAction;
     303         [ #  # ]:          0 :                     m_rOuterFace.DrawRect( pA->GetRect() );
     304                 :            :                 }
     305                 :          0 :                 break;
     306                 :            : 
     307                 :            :                 case( META_ROUNDRECT_ACTION ):
     308                 :            :                 {
     309                 :          0 :                     const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
     310         [ #  # ]:          0 :                     m_rOuterFace.DrawRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
     311                 :            :                 }
     312                 :          0 :                 break;
     313                 :            : 
     314                 :            :                 case( META_ELLIPSE_ACTION ):
     315                 :            :                 {
     316                 :          0 :                     const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
     317         [ #  # ]:          0 :                     m_rOuterFace.DrawEllipse( pA->GetRect() );
     318                 :            :                 }
     319                 :          0 :                 break;
     320                 :            : 
     321                 :            :                 case( META_ARC_ACTION ):
     322                 :            :                 {
     323                 :          0 :                     const MetaArcAction* pA = (const MetaArcAction*) pAction;
     324         [ #  # ]:          0 :                     m_rOuterFace.DrawArc( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
     325                 :            :                 }
     326                 :          0 :                 break;
     327                 :            : 
     328                 :            :                 case( META_PIE_ACTION ):
     329                 :            :                 {
     330                 :          0 :                     const MetaArcAction* pA = (const MetaArcAction*) pAction;
     331         [ #  # ]:          0 :                     m_rOuterFace.DrawPie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
     332                 :            :                 }
     333                 :          0 :                 break;
     334                 :            : 
     335                 :            :                 case( META_CHORD_ACTION ):
     336                 :            :                 {
     337                 :          0 :                     const MetaChordAction* pA = (const MetaChordAction*) pAction;
     338         [ #  # ]:          0 :                     m_rOuterFace.DrawChord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
     339                 :            :                 }
     340                 :          0 :                 break;
     341                 :            : 
     342                 :            :                 case( META_POLYGON_ACTION ):
     343                 :            :                 {
     344                 :          0 :                     const MetaPolygonAction* pA = (const MetaPolygonAction*) pAction;
     345         [ #  # ]:          0 :                     m_rOuterFace.DrawPolygon( pA->GetPolygon() );
     346                 :            :                 }
     347                 :          0 :                 break;
     348                 :            : 
     349                 :            :                 case( META_POLYLINE_ACTION ):
     350                 :            :                 {
     351                 :          0 :                     const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
     352         [ #  # ]:          0 :                     if ( pA->GetLineInfo().IsDefault() )
     353         [ #  # ]:          0 :                         m_rOuterFace.DrawPolyLine( pA->GetPolygon() );
     354                 :            :                     else
     355         [ #  # ]:          0 :                         m_rOuterFace.DrawPolyLine( pA->GetPolygon(), pA->GetLineInfo() );
     356                 :            :                 }
     357                 :          0 :                 break;
     358                 :            : 
     359                 :            :                 case( META_POLYPOLYGON_ACTION ):
     360                 :            :                 {
     361                 :          0 :                     const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
     362         [ #  # ]:          0 :                     m_rOuterFace.DrawPolyPolygon( pA->GetPolyPolygon() );
     363                 :            :                 }
     364                 :          0 :                 break;
     365                 :            : 
     366                 :            :                 case( META_GRADIENT_ACTION ):
     367                 :            :                 {
     368                 :          0 :                     const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
     369                 :            :                     #ifdef USE_PDFGRADIENTS
     370                 :            :                     m_rOuterFace.DrawGradient( pA->GetRect(), pA->GetGradient() );
     371                 :            :                     #else
     372 [ #  # ][ #  # ]:          0 :                     const PolyPolygon         aPolyPoly( pA->GetRect() );
                 [ #  # ]
     373 [ #  # ][ #  # ]:          0 :                     implWriteGradient( aPolyPoly, pA->GetGradient(), pDummyVDev, i_rContext );
     374                 :            :                     #endif
     375                 :            :                 }
     376                 :          0 :                 break;
     377                 :            : 
     378                 :            :                 case( META_GRADIENTEX_ACTION ):
     379                 :            :                 {
     380                 :          0 :                     const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
     381                 :            :                     #ifdef USE_PDFGRADIENTS
     382                 :            :                     m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), pA->GetGradient() );
     383                 :            :                     #else
     384         [ #  # ]:          0 :                     implWriteGradient( pA->GetPolyPolygon(), pA->GetGradient(), pDummyVDev, i_rContext );
     385                 :            :                     #endif
     386                 :            :                 }
     387                 :          0 :                 break;
     388                 :            : 
     389                 :            :                 case META_HATCH_ACTION:
     390                 :            :                 {
     391                 :          0 :                     const MetaHatchAction*  pA = (const MetaHatchAction*) pAction;
     392         [ #  # ]:          0 :                     m_rOuterFace.DrawHatch( pA->GetPolyPolygon(), pA->GetHatch() );
     393                 :            :                 }
     394                 :          0 :                 break;
     395                 :            : 
     396                 :            :                 case( META_TRANSPARENT_ACTION ):
     397                 :            :                 {
     398                 :          0 :                     const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
     399         [ #  # ]:          0 :                     m_rOuterFace.DrawTransparent( pA->GetPolyPolygon(), pA->GetTransparence() );
     400                 :            :                 }
     401                 :          0 :                 break;
     402                 :            : 
     403                 :            :                 case( META_FLOATTRANSPARENT_ACTION ):
     404                 :            :                 {
     405                 :          0 :                     const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
     406                 :            : 
     407         [ #  # ]:          0 :                     GDIMetaFile     aTmpMtf( pA->GetGDIMetaFile() );
     408                 :          0 :                     const Point&    rPos = pA->GetPoint();
     409                 :          0 :                     const Size&     rSize= pA->GetSize();
     410                 :          0 :                     const Gradient& rTransparenceGradient = pA->GetGradient();
     411                 :            : 
     412                 :            :                     // special case constant alpha value
     413         [ #  # ]:          0 :                     if( rTransparenceGradient.GetStartColor() == rTransparenceGradient.GetEndColor() )
     414                 :            :                     {
     415                 :          0 :                         const Color aTransCol( rTransparenceGradient.GetStartColor() );
     416         [ #  # ]:          0 :                         const sal_uInt16 nTransPercent = aTransCol.GetLuminance() * 100 / 255;
     417         [ #  # ]:          0 :                         m_rOuterFace.BeginTransparencyGroup();
     418         [ #  # ]:          0 :                         playMetafile( aTmpMtf, NULL, i_rContext, pDummyVDev );
     419 [ #  # ][ #  # ]:          0 :                         m_rOuterFace.EndTransparencyGroup( Rectangle( rPos, rSize ), nTransPercent );
     420                 :            :                     }
     421                 :            :                     else
     422                 :            :                     {
     423 [ #  # ][ #  # ]:          0 :                         const Size  aDstSizeTwip( pDummyVDev->PixelToLogic( pDummyVDev->LogicToPixel( rSize ), MAP_TWIP ) );
         [ #  # ][ #  # ]
     424         [ #  # ]:          0 :                         sal_Int32   nMaxBmpDPI = i_rContext.m_bOnlyLosslessCompression ? 300 : 72;
     425         [ #  # ]:          0 :                         if( i_rContext.m_nMaxImageResolution > 50 )
     426                 :            :                         {
     427         [ #  # ]:          0 :                             if ( nMaxBmpDPI > i_rContext.m_nMaxImageResolution )
     428                 :          0 :                                 nMaxBmpDPI = i_rContext.m_nMaxImageResolution;
     429                 :            :                         }
     430                 :          0 :                         const sal_Int32 nPixelX = (sal_Int32)((double)aDstSizeTwip.Width() * (double)nMaxBmpDPI / 1440.0);
     431                 :          0 :                         const sal_Int32 nPixelY = (sal_Int32)((double)aDstSizeTwip.Height() * (double)nMaxBmpDPI / 1440.0);
     432 [ #  # ][ #  # ]:          0 :                         if ( nPixelX && nPixelY )
     433                 :            :                         {
     434                 :          0 :                             Size aDstSizePixel( nPixelX, nPixelY );
     435 [ #  # ][ #  # ]:          0 :                             VirtualDevice* pVDev = new VirtualDevice;
     436 [ #  # ][ #  # ]:          0 :                             if( pVDev->SetOutputSizePixel( aDstSizePixel ) )
     437                 :            :                             {
     438 [ #  # ][ #  # ]:          0 :                                 Bitmap          aPaint, aMask;
     439         [ #  # ]:          0 :                                 AlphaMask       aAlpha;
     440                 :          0 :                                 Point           aPoint;
     441                 :            : 
     442         [ #  # ]:          0 :                                 MapMode aMapMode( pDummyVDev->GetMapMode() );
     443         [ #  # ]:          0 :                                 aMapMode.SetOrigin( aPoint );
     444         [ #  # ]:          0 :                                 pVDev->SetMapMode( aMapMode );
     445         [ #  # ]:          0 :                                 Size aDstSize( pVDev->PixelToLogic( aDstSizePixel ) );
     446                 :            : 
     447                 :          0 :                                 Point   aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
     448 [ #  # ][ #  # ]:          0 :                                 if ( aMtfOrigin.X() || aMtfOrigin.Y() )
                 [ #  # ]
     449         [ #  # ]:          0 :                                     aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
     450                 :          0 :                                 double  fScaleX = (double)aDstSize.Width() / (double)aTmpMtf.GetPrefSize().Width();
     451                 :          0 :                                 double  fScaleY = (double)aDstSize.Height() / (double)aTmpMtf.GetPrefSize().Height();
     452 [ #  # ][ #  # ]:          0 :                                 if( fScaleX != 1.0 || fScaleY != 1.0 )
     453         [ #  # ]:          0 :                                     aTmpMtf.Scale( fScaleX, fScaleY );
     454         [ #  # ]:          0 :                                 aTmpMtf.SetPrefMapMode( aMapMode );
     455                 :            : 
     456                 :            :                                 // create paint bitmap
     457         [ #  # ]:          0 :                                 aTmpMtf.WindStart();
     458         [ #  # ]:          0 :                                 aTmpMtf.Play( pVDev, aPoint, aDstSize );
     459         [ #  # ]:          0 :                                 aTmpMtf.WindStart();
     460                 :            : 
     461         [ #  # ]:          0 :                                 pVDev->EnableMapMode( sal_False );
     462 [ #  # ][ #  # ]:          0 :                                 aPaint = pVDev->GetBitmap( aPoint, aDstSizePixel );
                 [ #  # ]
     463         [ #  # ]:          0 :                                 pVDev->EnableMapMode( sal_True );
     464                 :            : 
     465                 :            :                                 // create mask bitmap
     466         [ #  # ]:          0 :                                 pVDev->SetLineColor( COL_BLACK );
     467         [ #  # ]:          0 :                                 pVDev->SetFillColor( COL_BLACK );
     468 [ #  # ][ #  # ]:          0 :                                 pVDev->DrawRect( Rectangle( aPoint, aDstSize ) );
     469                 :            :                                 pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
     470         [ #  # ]:          0 :                                                     DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
     471         [ #  # ]:          0 :                                 aTmpMtf.WindStart();
     472         [ #  # ]:          0 :                                 aTmpMtf.Play( pVDev, aPoint, aDstSize );
     473         [ #  # ]:          0 :                                 aTmpMtf.WindStart();
     474         [ #  # ]:          0 :                                 pVDev->EnableMapMode( sal_False );
     475 [ #  # ][ #  # ]:          0 :                                 aMask = pVDev->GetBitmap( aPoint, aDstSizePixel );
                 [ #  # ]
     476         [ #  # ]:          0 :                                 pVDev->EnableMapMode( sal_True );
     477                 :            : 
     478                 :            :                                 // create alpha mask from gradient
     479         [ #  # ]:          0 :                                 pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
     480 [ #  # ][ #  # ]:          0 :                                 pVDev->DrawGradient( Rectangle( aPoint, aDstSize ), rTransparenceGradient );
     481         [ #  # ]:          0 :                                 pVDev->SetDrawMode( DRAWMODE_DEFAULT );
     482         [ #  # ]:          0 :                                 pVDev->EnableMapMode( sal_False );
     483         [ #  # ]:          0 :                                 pVDev->DrawMask( aPoint, aDstSizePixel, aMask, Color( COL_WHITE ) );
     484 [ #  # ][ #  # ]:          0 :                                 aAlpha = pVDev->GetBitmap( aPoint, aDstSizePixel );
                 [ #  # ]
     485 [ #  # ][ #  # ]:          0 :                                 implWriteBitmapEx( rPos, rSize, BitmapEx( aPaint, aAlpha ), pDummyVDev, i_rContext );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     486                 :            :                             }
     487 [ #  # ][ #  # ]:          0 :                             delete pVDev;
     488                 :            :                         }
     489         [ #  # ]:          0 :                     }
     490                 :            :                 }
     491                 :          0 :                 break;
     492                 :            : 
     493                 :            :                 case( META_EPS_ACTION ):
     494                 :            :                 {
     495                 :          0 :                     const MetaEPSAction*    pA = (const MetaEPSAction*) pAction;
     496         [ #  # ]:          0 :                     const GDIMetaFile       aSubstitute( pA->GetSubstitute() );
     497                 :            : 
     498         [ #  # ]:          0 :                     m_rOuterFace.Push();
     499         [ #  # ]:          0 :                     pDummyVDev->Push();
     500                 :            : 
     501         [ #  # ]:          0 :                     MapMode aMapMode( aSubstitute.GetPrefMapMode() );
     502         [ #  # ]:          0 :                     Size aOutSize( pDummyVDev->LogicToLogic( pA->GetSize(), pDummyVDev->GetMapMode(), aMapMode ) );
     503 [ #  # ][ #  # ]:          0 :                     aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
     504 [ #  # ][ #  # ]:          0 :                     aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
     505 [ #  # ][ #  # ]:          0 :                     aMapMode.SetOrigin( pDummyVDev->LogicToLogic( pA->GetPoint(), pDummyVDev->GetMapMode(), aMapMode ) );
     506                 :            : 
     507         [ #  # ]:          0 :                     m_rOuterFace.SetMapMode( aMapMode );
     508         [ #  # ]:          0 :                     pDummyVDev->SetMapMode( aMapMode );
     509         [ #  # ]:          0 :                     playMetafile( aSubstitute, NULL, i_rContext, pDummyVDev );
     510         [ #  # ]:          0 :                     pDummyVDev->Pop();
     511 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.Pop();
                 [ #  # ]
     512                 :            :                 }
     513                 :          0 :                 break;
     514                 :            : 
     515                 :            :                 case( META_COMMENT_ACTION ):
     516         [ #  # ]:          0 :                 if( ! i_rContext.m_bTransparenciesWereRemoved )
     517                 :            :                 {
     518                 :          0 :                     const MetaCommentAction*    pA = (const MetaCommentAction*) pAction;
     519         [ #  # ]:          0 :                     String                      aSkipComment;
     520                 :            : 
     521         [ #  # ]:          0 :                     if( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XGRAD_SEQ_BEGIN")))
     522                 :            :                     {
     523                 :          0 :                         const MetaGradientExAction* pGradAction = NULL;
     524                 :          0 :                         sal_Bool                    bDone = sal_False;
     525                 :            : 
     526 [ #  # ][ #  # ]:          0 :                         while( !bDone && ( ++i < nCount ) )
                 [ #  # ]
     527                 :            :                         {
     528         [ #  # ]:          0 :                             pAction = aMtf.GetAction( i );
     529                 :            : 
     530         [ #  # ]:          0 :                             if( pAction->GetType() == META_GRADIENTEX_ACTION )
     531                 :          0 :                                 pGradAction = (const MetaGradientExAction*) pAction;
     532   [ #  #  #  # ]:          0 :                             else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
                 [ #  # ]
     533                 :          0 :                                     ( ( (const MetaCommentAction*) pAction )->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XGRAD_SEQ_END"))) )
     534                 :            :                             {
     535                 :          0 :                                 bDone = sal_True;
     536                 :            :                             }
     537                 :            :                         }
     538                 :            : 
     539         [ #  # ]:          0 :                         if( pGradAction )
     540                 :            :                         {
     541                 :            :                             #if USE_PDFGRADIENTS
     542                 :            :                             m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() );
     543                 :            :                             #else
     544         [ #  # ]:          0 :                             implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext );
     545                 :            :                             #endif
     546                 :            :                         }
     547                 :            :                     }
     548                 :            :                     else
     549                 :            :                     {
     550                 :          0 :                         const sal_uInt8* pData = pA->GetData();
     551         [ #  # ]:          0 :                         if ( pData )
     552                 :            :                         {
     553         [ #  # ]:          0 :                             SvMemoryStream  aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
     554                 :          0 :                             sal_Bool        bSkipSequence = sal_False;
     555                 :          0 :                             rtl::OString sSeqEnd;
     556                 :            : 
     557         [ #  # ]:          0 :                             if( pA->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("XPATHSTROKE_SEQ_BEGIN")) )
     558                 :            :                             {
     559                 :          0 :                                 sSeqEnd = rtl::OString(RTL_CONSTASCII_STRINGPARAM("XPATHSTROKE_SEQ_END"));
     560         [ #  # ]:          0 :                                 SvtGraphicStroke aStroke;
     561         [ #  # ]:          0 :                                 aMemStm >> aStroke;
     562                 :            : 
     563         [ #  # ]:          0 :                                 Polygon aPath;
     564         [ #  # ]:          0 :                                 aStroke.getPath( aPath );
     565                 :            : 
     566         [ #  # ]:          0 :                                 PolyPolygon aStartArrow;
     567         [ #  # ]:          0 :                                 PolyPolygon aEndArrow;
     568         [ #  # ]:          0 :                                 double fTransparency( aStroke.getTransparency() );
     569         [ #  # ]:          0 :                                 double fStrokeWidth( aStroke.getStrokeWidth() );
     570         [ #  # ]:          0 :                                 SvtGraphicStroke::DashArray aDashArray;
     571                 :            : 
     572         [ #  # ]:          0 :                                 aStroke.getStartArrow( aStartArrow );
     573         [ #  # ]:          0 :                                 aStroke.getEndArrow( aEndArrow );
     574         [ #  # ]:          0 :                                 aStroke.getDashArray( aDashArray );
     575                 :            : 
     576                 :          0 :                                 bSkipSequence = sal_True;
     577 [ #  # ][ #  # ]:          0 :                                 if ( aStartArrow.Count() || aEndArrow.Count() )
         [ #  # ][ #  # ]
                 [ #  # ]
     578                 :          0 :                                     bSkipSequence = sal_False;
     579 [ #  # ][ #  # ]:          0 :                                 if ( aDashArray.size() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
         [ #  # ][ #  # ]
     580                 :          0 :                                     bSkipSequence = sal_False;
     581         [ #  # ]:          0 :                                 if ( bSkipSequence )
     582                 :            :                                 {
     583         [ #  # ]:          0 :                                     PDFWriter::ExtLineInfo aInfo;
     584                 :          0 :                                     aInfo.m_fLineWidth      = fStrokeWidth;
     585                 :          0 :                                     aInfo.m_fTransparency   = fTransparency;
     586         [ #  # ]:          0 :                                     aInfo.m_fMiterLimit     = aStroke.getMiterLimit();
     587         [ #  # ]:          0 :                                     switch( aStroke.getCapType() )
              [ #  #  # ]
     588                 :            :                                     {
     589                 :            :                                         default:
     590                 :          0 :                                         case SvtGraphicStroke::capButt:   aInfo.m_eCap = PDFWriter::capButt;break;
     591                 :          0 :                                         case SvtGraphicStroke::capRound:  aInfo.m_eCap = PDFWriter::capRound;break;
     592                 :          0 :                                         case SvtGraphicStroke::capSquare: aInfo.m_eCap = PDFWriter::capSquare;break;
     593                 :            :                                     }
     594         [ #  # ]:          0 :                                     switch( aStroke.getJoinType() )
           [ #  #  #  # ]
     595                 :            :                                     {
     596                 :            :                                         default:
     597                 :          0 :                                         case SvtGraphicStroke::joinMiter: aInfo.m_eJoin = PDFWriter::joinMiter;break;
     598                 :          0 :                                         case SvtGraphicStroke::joinRound: aInfo.m_eJoin = PDFWriter::joinRound;break;
     599                 :          0 :                                         case SvtGraphicStroke::joinBevel: aInfo.m_eJoin = PDFWriter::joinBevel;break;
     600                 :            :                                         case SvtGraphicStroke::joinNone:
     601                 :          0 :                                             aInfo.m_eJoin = PDFWriter::joinMiter;
     602                 :          0 :                                             aInfo.m_fMiterLimit = 0.0;
     603                 :          0 :                                             break;
     604                 :            :                                     }
     605         [ #  # ]:          0 :                                     aInfo.m_aDashArray = aDashArray;
     606                 :            : 
     607 [ #  # ][ #  # ]:          0 :                                     if(SvtGraphicStroke::joinNone == aStroke.getJoinType()
         [ #  # ][ #  # ]
     608                 :            :                                         && fStrokeWidth > 0.0)
     609                 :            :                                     {
     610                 :            :                                         // emulate no edge rounding by handling single edges
     611         [ #  # ]:          0 :                                         const sal_uInt16 nPoints(aPath.GetSize());
     612         [ #  # ]:          0 :                                         const bool bCurve(aPath.HasFlags());
     613                 :            : 
     614         [ #  # ]:          0 :                                         for(sal_uInt16 a(0); a + 1 < nPoints; a++)
     615                 :            :                                         {
     616 [ #  # ][ #  # ]:          0 :                                             if(bCurve
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     617         [ #  # ]:          0 :                                                 && POLY_NORMAL != aPath.GetFlags(a + 1)
     618                 :            :                                                 && a + 2 < nPoints
     619         [ #  # ]:          0 :                                                 && POLY_NORMAL != aPath.GetFlags(a + 2)
     620                 :            :                                                 && a + 3 < nPoints)
     621                 :            :                                             {
     622                 :            :                                                 const Polygon aSnippet(4,
     623         [ #  # ]:          0 :                                                     aPath.GetConstPointAry() + a,
     624 [ #  # ][ #  # ]:          0 :                                                     aPath.GetConstFlagAry() + a);
     625         [ #  # ]:          0 :                                                 m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
     626         [ #  # ]:          0 :                                                 a += 2;
     627                 :            :                                             }
     628                 :            :                                             else
     629                 :            :                                             {
     630                 :            :                                                 const Polygon aSnippet(2,
     631 [ #  # ][ #  # ]:          0 :                                                     aPath.GetConstPointAry() + a);
     632 [ #  # ][ #  # ]:          0 :                                                 m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
     633                 :            :                                             }
     634                 :            :                                         }
     635                 :            :                                     }
     636                 :            :                                     else
     637                 :            :                                     {
     638         [ #  # ]:          0 :                                         m_rOuterFace.DrawPolyLine( aPath, aInfo );
     639                 :          0 :                                     }
     640 [ #  # ][ #  # ]:          0 :                                 }
         [ #  # ][ #  # ]
     641                 :            :                             }
     642         [ #  # ]:          0 :                             else if ( pA->GetComment().equalsL(RTL_CONSTASCII_STRINGPARAM("XPATHFILL_SEQ_BEGIN")) )
     643                 :            :                             {
     644                 :          0 :                                 sSeqEnd = rtl::OString(RTL_CONSTASCII_STRINGPARAM("XPATHFILL_SEQ_END"));
     645         [ #  # ]:          0 :                                 SvtGraphicFill aFill;
     646         [ #  # ]:          0 :                                 aMemStm >> aFill;
     647                 :            : 
     648 [ #  # ][ #  # ]:          0 :                                 if ( ( aFill.getFillType() == SvtGraphicFill::fillSolid ) && ( aFill.getFillRule() == SvtGraphicFill::fillEvenOdd ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     649                 :            :                                 {
     650         [ #  # ]:          0 :                                     double fTransparency = aFill.getTransparency();
     651         [ #  # ]:          0 :                                     if ( fTransparency == 0.0 )
     652                 :            :                                     {
     653         [ #  # ]:          0 :                                         PolyPolygon aPath;
     654         [ #  # ]:          0 :                                         aFill.getPath( aPath );
     655                 :            : 
     656                 :          0 :                                         bSkipSequence = sal_True;
     657 [ #  # ][ #  # ]:          0 :                                         m_rOuterFace.DrawPolyPolygon( aPath );
     658                 :            :                                     }
     659         [ #  # ]:          0 :                                     else if ( fTransparency == 1.0 )
     660                 :          0 :                                         bSkipSequence = sal_True;
     661         [ #  # ]:          0 :                                 }
     662                 :            : /* #i81548# removing optimization for fill textures, because most of the texture settings are not
     663                 :            :    exported properly. In OpenOffice 3.1 the drawing layer will support graphic primitives, then it
     664                 :            :    will not be a problem to optimize the filltexture export. But for wysiwyg is more important than
     665                 :            :    filesize.
     666                 :            :                                 else if( aFill.getFillType() == SvtGraphicFill::fillTexture && aFill.isTiling() )
     667                 :            :                                 {
     668                 :            :                                     sal_Int32 nPattern = mnCachePatternId;
     669                 :            :                                     Graphic aPatternGraphic;
     670                 :            :                                     aFill.getGraphic( aPatternGraphic );
     671                 :            :                                     bool bUseCache = false;
     672                 :            :                                     SvtGraphicFill::Transform aPatTransform;
     673                 :            :                                     aFill.getTransform( aPatTransform );
     674                 :            : 
     675                 :            :                                     if(  mnCachePatternId >= 0 )
     676                 :            :                                     {
     677                 :            :                                         SvtGraphicFill::Transform aCacheTransform;
     678                 :            :                                         maCacheFill.getTransform( aCacheTransform );
     679                 :            :                                         if( aCacheTransform.matrix[0] == aPatTransform.matrix[0] &&
     680                 :            :                                             aCacheTransform.matrix[1] == aPatTransform.matrix[1] &&
     681                 :            :                                             aCacheTransform.matrix[2] == aPatTransform.matrix[2] &&
     682                 :            :                                             aCacheTransform.matrix[3] == aPatTransform.matrix[3] &&
     683                 :            :                                             aCacheTransform.matrix[4] == aPatTransform.matrix[4] &&
     684                 :            :                                             aCacheTransform.matrix[5] == aPatTransform.matrix[5]
     685                 :            :                                             )
     686                 :            :                                         {
     687                 :            :                                             Graphic aCacheGraphic;
     688                 :            :                                             maCacheFill.getGraphic( aCacheGraphic );
     689                 :            :                                             if( aCacheGraphic == aPatternGraphic )
     690                 :            :                                                 bUseCache = true;
     691                 :            :                                         }
     692                 :            :                                     }
     693                 :            : 
     694                 :            :                                     if( ! bUseCache )
     695                 :            :                                     {
     696                 :            : 
     697                 :            :                                         // paint graphic to metafile
     698                 :            :                                         GDIMetaFile aPattern;
     699                 :            :                                         pDummyVDev->SetConnectMetaFile( &aPattern );
     700                 :            :                                         pDummyVDev->Push();
     701                 :            :                                         pDummyVDev->SetMapMode( aPatternGraphic.GetPrefMapMode() );
     702                 :            : 
     703                 :            :                                         aPatternGraphic.Draw( &rDummyVDev, Point( 0, 0 ) );
     704                 :            :                                         pDummyVDev->Pop();
     705                 :            :                                         pDummyVDev->SetConnectMetaFile( NULL );
     706                 :            :                                         aPattern.WindStart();
     707                 :            : 
     708                 :            :                                         MapMode aPatternMapMode( aPatternGraphic.GetPrefMapMode() );
     709                 :            :                                         // prepare pattern from metafile
     710                 :            :                                         Size aPrefSize( aPatternGraphic.GetPrefSize() );
     711                 :            :                                         // FIXME: this magic -1 shouldn't be necessary
     712                 :            :                                         aPrefSize.Width() -= 1;
     713                 :            :                                         aPrefSize.Height() -= 1;
     714                 :            :                                         aPrefSize = m_rOuterFace.GetReferenceDevice()->
     715                 :            :                                             LogicToLogic( aPrefSize,
     716                 :            :                                                           &aPatternMapMode,
     717                 :            :                                                           &m_rOuterFace.GetReferenceDevice()->GetMapMode() );
     718                 :            :                                         // build bounding rectangle of pattern
     719                 :            :                                         Rectangle aBound( Point( 0, 0 ), aPrefSize );
     720                 :            :                                         m_rOuterFace.BeginPattern( aBound );
     721                 :            :                                         m_rOuterFace.Push();
     722                 :            :                                         pDummyVDev->Push();
     723                 :            :                                         m_rOuterFace.SetMapMode( aPatternMapMode );
     724                 :            :                                         pDummyVDev->SetMapMode( aPatternMapMode );
     725                 :            :                                         ImplWriteActions( m_rOuterFace, NULL, aPattern, rDummyVDev );
     726                 :            :                                         pDummyVDev->Pop();
     727                 :            :                                         m_rOuterFace.Pop();
     728                 :            : 
     729                 :            :                                         nPattern = m_rOuterFace.EndPattern( aPatTransform );
     730                 :            : 
     731                 :            :                                         // try some caching and reuse pattern
     732                 :            :                                         mnCachePatternId = nPattern;
     733                 :            :                                         maCacheFill = aFill;
     734                 :            :                                     }
     735                 :            : 
     736                 :            :                                     // draw polypolygon with pattern fill
     737                 :            :                                     PolyPolygon aPath;
     738                 :            :                                     aFill.getPath( aPath );
     739                 :            :                                     m_rOuterFace.DrawPolyPolygon( aPath, nPattern, aFill.getFillRule() == SvtGraphicFill::fillEvenOdd );
     740                 :            : 
     741                 :            :                                     bSkipSequence = sal_True;
     742                 :            :                                 }
     743                 :            : */
     744                 :            :                             }
     745         [ #  # ]:          0 :                             if ( bSkipSequence )
     746                 :            :                             {
     747         [ #  # ]:          0 :                                 while( ++i < nCount )
     748                 :            :                                 {
     749         [ #  # ]:          0 :                                     pAction = aMtf.GetAction( i );
     750         [ #  # ]:          0 :                                     if ( pAction->GetType() == META_COMMENT_ACTION )
     751                 :            :                                     {
     752                 :          0 :                                         rtl::OString sComment( ((MetaCommentAction*)pAction)->GetComment() );
     753         [ #  # ]:          0 :                                         if (sComment == sSeqEnd)
     754         [ #  # ]:          0 :                                             break;
     755                 :            :                                     }
     756                 :            :                                     // #i44496#
     757                 :            :                                     // the replacement action for stroke is a filled rectangle
     758                 :            :                                     // the set fillcolor of the replacement is part of the graphics
     759                 :            :                                     // state and must not be skipped
     760         [ #  # ]:          0 :                                     else if( pAction->GetType() == META_FILLCOLOR_ACTION )
     761                 :            :                                     {
     762                 :          0 :                                         const MetaFillColorAction* pMA = (const MetaFillColorAction*) pAction;
     763         [ #  # ]:          0 :                                         if( pMA->IsSetting() )
     764         [ #  # ]:          0 :                                             m_rOuterFace.SetFillColor( pMA->GetColor() );
     765                 :            :                                         else
     766         [ #  # ]:          0 :                                             m_rOuterFace.SetFillColor();
     767                 :            :                                     }
     768                 :            :                                 }
     769         [ #  # ]:          0 :                             }
     770                 :            :                         }
     771         [ #  # ]:          0 :                     }
     772                 :            :                 }
     773                 :          0 :                 break;
     774                 :            : 
     775                 :            :                 case( META_BMP_ACTION ):
     776                 :            :                 {
     777                 :          0 :                     const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
     778         [ #  # ]:          0 :                     BitmapEx aBitmapEx( pA->GetBitmap() );
     779                 :          0 :                     Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
     780         [ #  # ]:          0 :                             aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
     781 [ #  # ][ #  # ]:          0 :                     if( ! ( aSize.Width() && aSize.Height() ) )
                 [ #  # ]
     782         [ #  # ]:          0 :                         aSize = pDummyVDev->PixelToLogic( aBitmapEx.GetSizePixel() );
     783 [ #  # ][ #  # ]:          0 :                     implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, pDummyVDev, i_rContext );
     784                 :            :                 }
     785                 :          0 :                 break;
     786                 :            : 
     787                 :            :                 case( META_BMPSCALE_ACTION ):
     788                 :            :                 {
     789                 :          0 :                     const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
     790 [ #  # ][ #  # ]:          0 :                     implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), BitmapEx( pA->GetBitmap() ), pDummyVDev, i_rContext );
                 [ #  # ]
     791                 :            :                 }
     792                 :          0 :                 break;
     793                 :            : 
     794                 :            :                 case( META_BMPSCALEPART_ACTION ):
     795                 :            :                 {
     796                 :          0 :                     const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
     797         [ #  # ]:          0 :                     BitmapEx aBitmapEx( pA->GetBitmap() );
     798 [ #  # ][ #  # ]:          0 :                     aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
     799 [ #  # ][ #  # ]:          0 :                     implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, pDummyVDev, i_rContext );
     800                 :            :                 }
     801                 :          0 :                 break;
     802                 :            : 
     803                 :            :                 case( META_BMPEX_ACTION ):
     804                 :            :                 {
     805                 :          0 :                     const MetaBmpExAction*  pA = (const MetaBmpExAction*) pAction;
     806         [ #  # ]:          0 :                     BitmapEx aBitmapEx( pA->GetBitmapEx() );
     807                 :          0 :                     Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
     808         [ #  # ]:          0 :                             aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
     809 [ #  # ][ #  # ]:          0 :                     implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, pDummyVDev, i_rContext );
     810                 :            :                 }
     811                 :          0 :                 break;
     812                 :            : 
     813                 :            :                 case( META_BMPEXSCALE_ACTION ):
     814                 :            :                 {
     815                 :          0 :                     const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
     816         [ #  # ]:          0 :                     implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), pA->GetBitmapEx(), pDummyVDev, i_rContext );
     817                 :            :                 }
     818                 :          0 :                 break;
     819                 :            : 
     820                 :            :                 case( META_BMPEXSCALEPART_ACTION ):
     821                 :            :                 {
     822                 :          0 :                     const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
     823         [ #  # ]:          0 :                     BitmapEx aBitmapEx( pA->GetBitmapEx() );
     824 [ #  # ][ #  # ]:          0 :                     aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
     825 [ #  # ][ #  # ]:          0 :                     implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, pDummyVDev, i_rContext );
     826                 :            :                 }
     827                 :          0 :                 break;
     828                 :            : 
     829                 :            :                 case( META_MASK_ACTION ):
     830                 :            :                 case( META_MASKSCALE_ACTION ):
     831                 :            :                 case( META_MASKSCALEPART_ACTION ):
     832                 :            :                 {
     833                 :            :                     OSL_TRACE( "MetaMask...Action not supported yet" );
     834                 :            :                 }
     835                 :          0 :                 break;
     836                 :            : 
     837                 :            :                 case( META_TEXT_ACTION ):
     838                 :            :                 {
     839                 :          0 :                     const MetaTextAction* pA = (const MetaTextAction*) pAction;
     840 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.DrawText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     841                 :            :                 }
     842                 :          0 :                 break;
     843                 :            : 
     844                 :            :                 case( META_TEXTRECT_ACTION ):
     845                 :            :                 {
     846                 :          0 :                     const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
     847 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.DrawText( pA->GetRect(), String( pA->GetText() ), pA->GetStyle() );
                 [ #  # ]
     848                 :            :                 }
     849                 :          0 :                 break;
     850                 :            : 
     851                 :            :                 case( META_TEXTARRAY_ACTION ):
     852                 :            :                 {
     853                 :          0 :                     const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
     854 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetIndex(), pA->GetLen() );
                 [ #  # ]
     855                 :            :                 }
     856                 :          0 :                 break;
     857                 :            : 
     858                 :            :                 case( META_STRETCHTEXT_ACTION ):
     859                 :            :                 {
     860                 :          0 :                     const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
     861 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
                 [ #  # ]
     862                 :            :                 }
     863                 :          0 :                 break;
     864                 :            : 
     865                 :            : 
     866                 :            :                 case( META_TEXTLINE_ACTION ):
     867                 :            :                 {
     868                 :          0 :                     const MetaTextLineAction* pA = (const MetaTextLineAction*) pAction;
     869         [ #  # ]:          0 :                     m_rOuterFace.DrawTextLine( pA->GetStartPoint(), pA->GetWidth(), pA->GetStrikeout(), pA->GetUnderline(), pA->GetOverline() );
     870                 :            : 
     871                 :            :                 }
     872                 :          0 :                 break;
     873                 :            : 
     874                 :            :                 case( META_CLIPREGION_ACTION ):
     875                 :            :                 {
     876                 :          0 :                     const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pAction;
     877                 :            : 
     878         [ #  # ]:          0 :                     if( pA->IsClipping() )
     879                 :            :                     {
     880 [ #  # ][ #  # ]:          0 :                         if( pA->GetRegion().IsEmpty() )
     881 [ #  # ][ #  # ]:          0 :                             m_rOuterFace.SetClipRegion( basegfx::B2DPolyPolygon() );
                 [ #  # ]
     882                 :            :                         else
     883                 :            :                         {
     884         [ #  # ]:          0 :                             Region aReg( pA->GetRegion() );
     885 [ #  # ][ #  # ]:          0 :                             m_rOuterFace.SetClipRegion( aReg.ConvertToB2DPolyPolygon() );
         [ #  # ][ #  # ]
     886                 :            :                         }
     887                 :            :                     }
     888                 :            :                     else
     889         [ #  # ]:          0 :                         m_rOuterFace.SetClipRegion();
     890                 :            :                 }
     891                 :          0 :                 break;
     892                 :            : 
     893                 :            :                 case( META_ISECTRECTCLIPREGION_ACTION ):
     894                 :            :                 {
     895                 :          0 :                     const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
     896         [ #  # ]:          0 :                     m_rOuterFace.IntersectClipRegion( pA->GetRect() );
     897                 :            :                 }
     898                 :          0 :                 break;
     899                 :            : 
     900                 :            :                 case( META_ISECTREGIONCLIPREGION_ACTION ):
     901                 :            :                 {
     902                 :          0 :                     const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pAction;
     903         [ #  # ]:          0 :                     Region aReg( pA->GetRegion() );
     904 [ #  # ][ #  # ]:          0 :                     m_rOuterFace.IntersectClipRegion( aReg.ConvertToB2DPolyPolygon() );
         [ #  # ][ #  # ]
     905                 :            :                 }
     906                 :          0 :                 break;
     907                 :            : 
     908                 :            :                 case( META_MOVECLIPREGION_ACTION ):
     909                 :            :                 {
     910                 :          0 :                     const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pAction;
     911         [ #  # ]:          0 :                     m_rOuterFace.MoveClipRegion( pA->GetHorzMove(), pA->GetVertMove() );
     912                 :            :                 }
     913                 :          0 :                 break;
     914                 :            : 
     915                 :            :                 case( META_MAPMODE_ACTION ):
     916                 :            :                 {
     917         [ #  # ]:          0 :                     const_cast< MetaAction* >( pAction )->Execute( pDummyVDev );
     918         [ #  # ]:          0 :                     m_rOuterFace.SetMapMode( pDummyVDev->GetMapMode() );
     919                 :            :                 }
     920                 :          0 :                 break;
     921                 :            : 
     922                 :            :                 case( META_LINECOLOR_ACTION ):
     923                 :            :                 {
     924                 :          0 :                     const MetaLineColorAction* pA = (const MetaLineColorAction*) pAction;
     925                 :            : 
     926         [ #  # ]:          0 :                     if( pA->IsSetting() )
     927         [ #  # ]:          0 :                         m_rOuterFace.SetLineColor( pA->GetColor() );
     928                 :            :                     else
     929         [ #  # ]:          0 :                         m_rOuterFace.SetLineColor();
     930                 :            :                 }
     931                 :          0 :                 break;
     932                 :            : 
     933                 :            :                 case( META_FILLCOLOR_ACTION ):
     934                 :            :                 {
     935                 :          0 :                     const MetaFillColorAction* pA = (const MetaFillColorAction*) pAction;
     936                 :            : 
     937         [ #  # ]:          0 :                     if( pA->IsSetting() )
     938         [ #  # ]:          0 :                         m_rOuterFace.SetFillColor( pA->GetColor() );
     939                 :            :                     else
     940         [ #  # ]:          0 :                         m_rOuterFace.SetFillColor();
     941                 :            :                 }
     942                 :          0 :                 break;
     943                 :            : 
     944                 :            :                 case( META_TEXTLINECOLOR_ACTION ):
     945                 :            :                 {
     946                 :          0 :                     const MetaTextLineColorAction* pA = (const MetaTextLineColorAction*) pAction;
     947                 :            : 
     948         [ #  # ]:          0 :                     if( pA->IsSetting() )
     949         [ #  # ]:          0 :                         m_rOuterFace.SetTextLineColor( pA->GetColor() );
     950                 :            :                     else
     951         [ #  # ]:          0 :                         m_rOuterFace.SetTextLineColor();
     952                 :            :                 }
     953                 :          0 :                 break;
     954                 :            : 
     955                 :            :                 case( META_OVERLINECOLOR_ACTION ):
     956                 :            :                 {
     957                 :          0 :                     const MetaOverlineColorAction* pA = (const MetaOverlineColorAction*) pAction;
     958                 :            : 
     959         [ #  # ]:          0 :                     if( pA->IsSetting() )
     960         [ #  # ]:          0 :                         m_rOuterFace.SetOverlineColor( pA->GetColor() );
     961                 :            :                     else
     962         [ #  # ]:          0 :                         m_rOuterFace.SetOverlineColor();
     963                 :            :                 }
     964                 :          0 :                 break;
     965                 :            : 
     966                 :            :                 case( META_TEXTFILLCOLOR_ACTION ):
     967                 :            :                 {
     968                 :          0 :                     const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pAction;
     969                 :            : 
     970         [ #  # ]:          0 :                     if( pA->IsSetting() )
     971         [ #  # ]:          0 :                         m_rOuterFace.SetTextFillColor( pA->GetColor() );
     972                 :            :                     else
     973         [ #  # ]:          0 :                         m_rOuterFace.SetTextFillColor();
     974                 :            :                 }
     975                 :          0 :                 break;
     976                 :            : 
     977                 :            :                 case( META_TEXTCOLOR_ACTION ):
     978                 :            :                 {
     979                 :          0 :                     const MetaTextColorAction* pA = (const MetaTextColorAction*) pAction;
     980         [ #  # ]:          0 :                     m_rOuterFace.SetTextColor( pA->GetColor() );
     981                 :            :                 }
     982                 :          0 :                 break;
     983                 :            : 
     984                 :            :                 case( META_TEXTALIGN_ACTION ):
     985                 :            :                 {
     986                 :          0 :                     const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pAction;
     987         [ #  # ]:          0 :                     m_rOuterFace.SetTextAlign( pA->GetTextAlign() );
     988                 :            :                 }
     989                 :          0 :                 break;
     990                 :            : 
     991                 :            :                 case( META_FONT_ACTION ):
     992                 :            :                 {
     993                 :          0 :                     const MetaFontAction* pA = (const MetaFontAction*) pAction;
     994         [ #  # ]:          0 :                     m_rOuterFace.SetFont( pA->GetFont() );
     995                 :            :                 }
     996                 :          0 :                 break;
     997                 :            : 
     998                 :            :                 case( META_PUSH_ACTION ):
     999                 :            :                 {
    1000                 :          0 :                     const MetaPushAction* pA = (const MetaPushAction*) pAction;
    1001                 :            : 
    1002         [ #  # ]:          0 :                     pDummyVDev->Push( pA->GetFlags() );
    1003         [ #  # ]:          0 :                     m_rOuterFace.Push( pA->GetFlags() );
    1004                 :            :                 }
    1005                 :          0 :                 break;
    1006                 :            : 
    1007                 :            :                 case( META_POP_ACTION ):
    1008                 :            :                 {
    1009         [ #  # ]:          0 :                     pDummyVDev->Pop();
    1010         [ #  # ]:          0 :                     m_rOuterFace.Pop();
    1011                 :            :                 }
    1012                 :          0 :                 break;
    1013                 :            : 
    1014                 :            :                 case( META_LAYOUTMODE_ACTION ):
    1015                 :            :                 {
    1016                 :          0 :                     const MetaLayoutModeAction* pA = (const MetaLayoutModeAction*) pAction;
    1017         [ #  # ]:          0 :                     m_rOuterFace.SetLayoutMode( pA->GetLayoutMode() );
    1018                 :            :                 }
    1019                 :          0 :                 break;
    1020                 :            : 
    1021                 :            :                 case META_TEXTLANGUAGE_ACTION:
    1022                 :            :                 {
    1023                 :          0 :                     const  MetaTextLanguageAction* pA = (const MetaTextLanguageAction*) pAction;
    1024         [ #  # ]:          0 :                     m_rOuterFace.SetDigitLanguage( pA->GetTextLanguage() );
    1025                 :            :                 }
    1026                 :          0 :                 break;
    1027                 :            : 
    1028                 :            :                 case( META_WALLPAPER_ACTION ):
    1029                 :            :                 {
    1030                 :          0 :                     const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pAction;
    1031         [ #  # ]:          0 :                     m_rOuterFace.DrawWallpaper( pA->GetRect(), pA->GetWallpaper() );
    1032                 :            :                 }
    1033                 :          0 :                 break;
    1034                 :            : 
    1035                 :            :                 case( META_RASTEROP_ACTION ):
    1036                 :            :                 {
    1037                 :            :                     // !!! >>> we don't want to support this actions
    1038                 :            :                 }
    1039                 :          0 :                 break;
    1040                 :            : 
    1041                 :            :                 case( META_REFPOINT_ACTION ):
    1042                 :            :                 {
    1043                 :            :                     // !!! >>> we don't want to support this actions
    1044                 :            :                 }
    1045                 :          0 :                 break;
    1046                 :            : 
    1047                 :            :                 case( META_RENDERGRAPHIC_ACTION ):
    1048                 :            :                 {
    1049                 :          0 :                     const MetaRenderGraphicAction* pA = static_cast< const MetaRenderGraphicAction* >( pAction );
    1050         [ #  # ]:          0 :                     const ::vcl::RenderGraphicRasterizer aRasterizer( pA->GetRenderGraphic() );
    1051                 :            : 
    1052                 :          0 :                     implWriteBitmapEx( pA->GetPoint(), pA->GetSize(),
    1053 [ #  # ][ #  # ]:          0 :                                        aRasterizer.Rasterize( pDummyVDev->LogicToPixel( pA->GetSize() ) ),
    1054 [ #  # ][ #  # ]:          0 :                                        pDummyVDev, i_rContext );
    1055                 :            :                 }
    1056                 :          0 :                 break;
    1057                 :            : 
    1058                 :            :                 default:
    1059                 :            :                     // #i24604# Made assertion fire only once per
    1060                 :            :                     // metafile. The asserted actions here are all
    1061                 :            :                     // deprecated
    1062         [ #  # ]:          0 :                     if( !bAssertionFired )
    1063                 :            :                     {
    1064                 :          0 :                         bAssertionFired = true;
    1065                 :            :                         OSL_TRACE( "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered" );
    1066                 :            :                     }
    1067                 :          0 :                 break;
    1068                 :            :             }
    1069                 :          0 :             i++;
    1070                 :            :         }
    1071                 :            :     }
    1072                 :            : 
    1073 [ #  # ][ #  # ]:          0 :     delete pPrivateDevice;
                 [ #  # ]
    1074                 :          0 : }
    1075                 :            : 
    1076                 :            : // Encryption methods
    1077                 :            : 
    1078                 :            : /* a crutch to transport an rtlDigest safely though UNO API
    1079                 :            :    this is needed for the PDF export dialog, which otherwise would have to pass
    1080                 :            :    clear text passwords down till they can be used in PDFWriter. Unfortunately
    1081                 :            :    the MD5 sum of the password (which is needed to create the PDF encryption key)
    1082                 :            :    is not sufficient, since an rtl MD5 digest cannot be created in an arbitrary state
    1083                 :            :    which would be needed in PDFWriterImpl::computeEncryptionKey.
    1084                 :            : */
    1085                 :            : class EncHashTransporter : public cppu::WeakImplHelper1 < com::sun::star::beans::XMaterialHolder >
    1086                 :            : {
    1087                 :            :     rtlDigest                   maUDigest;
    1088                 :            :     sal_IntPtr                  maID;
    1089                 :            :     std::vector< sal_uInt8 >    maOValue;
    1090                 :            : 
    1091                 :            :     static std::map< sal_IntPtr, EncHashTransporter* >      sTransporters;
    1092                 :            : public:
    1093                 :          0 :     EncHashTransporter()
    1094         [ #  # ]:          0 :     : maUDigest( rtl_digest_createMD5() )
    1095                 :            :     {
    1096                 :          0 :         maID = reinterpret_cast< sal_IntPtr >(this);
    1097 [ #  # ][ #  # ]:          0 :         while( sTransporters.find( maID ) != sTransporters.end() ) // paranoia mode
    1098                 :          0 :             maID++;
    1099         [ #  # ]:          0 :         sTransporters[ maID ] = this;
    1100                 :          0 :     }
    1101                 :            : 
    1102                 :          0 :     virtual ~EncHashTransporter()
    1103                 :          0 :     {
    1104         [ #  # ]:          0 :         sTransporters.erase( maID );
    1105         [ #  # ]:          0 :         if( maUDigest )
    1106                 :          0 :             rtl_digest_destroyMD5( maUDigest );
    1107                 :            :         OSL_TRACE( "EncHashTransporter freed" );
    1108         [ #  # ]:          0 :     }
    1109                 :            : 
    1110                 :          0 :     rtlDigest getUDigest() const { return maUDigest; };
    1111                 :          0 :     std::vector< sal_uInt8 >& getOValue() { return maOValue; }
    1112                 :          0 :     void invalidate()
    1113                 :            :     {
    1114         [ #  # ]:          0 :         if( maUDigest )
    1115                 :            :         {
    1116                 :          0 :             rtl_digest_destroyMD5( maUDigest );
    1117                 :          0 :             maUDigest = NULL;
    1118                 :            :         }
    1119                 :          0 :     }
    1120                 :            : 
    1121                 :            :     // XMaterialHolder
    1122                 :          0 :     virtual uno::Any SAL_CALL getMaterial() throw()
    1123                 :            :     {
    1124         [ #  # ]:          0 :         return uno::makeAny( sal_Int64(maID) );
    1125                 :            :     }
    1126                 :            : 
    1127                 :            :     static EncHashTransporter* getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& );
    1128                 :            : 
    1129                 :            : };
    1130                 :            : 
    1131                 :        281 : std::map< sal_IntPtr, EncHashTransporter* > EncHashTransporter::sTransporters;
    1132                 :            : 
    1133                 :          0 : EncHashTransporter* EncHashTransporter::getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& xRef )
    1134                 :            : {
    1135                 :          0 :     EncHashTransporter* pResult = NULL;
    1136         [ #  # ]:          0 :     if( xRef.is() )
    1137                 :            :     {
    1138 [ #  # ][ #  # ]:          0 :         uno::Any aMat( xRef->getMaterial() );
    1139                 :          0 :         sal_Int64 nMat = 0;
    1140         [ #  # ]:          0 :         if( aMat >>= nMat )
    1141                 :            :         {
    1142         [ #  # ]:          0 :             std::map< sal_IntPtr, EncHashTransporter* >::iterator it = sTransporters.find( static_cast<sal_IntPtr>(nMat) );
    1143         [ #  # ]:          0 :             if( it != sTransporters.end() )
    1144                 :          0 :                 pResult = it->second;
    1145                 :          0 :         }
    1146                 :            :     }
    1147                 :          0 :     return pResult;
    1148                 :            : }
    1149                 :            : 
    1150                 :          0 : sal_Bool PDFWriterImpl::checkEncryptionBufferSize( register sal_Int32 newSize )
    1151                 :            : {
    1152         [ #  # ]:          0 :     if( m_nEncryptionBufferSize < newSize )
    1153                 :            :     {
    1154                 :            :         /* reallocate the buffer, the used function allocate as rtl_allocateMemory
    1155                 :            :         if the pointer parameter is NULL */
    1156                 :          0 :         m_pEncryptionBuffer = (sal_uInt8*)rtl_reallocateMemory( m_pEncryptionBuffer, newSize );
    1157         [ #  # ]:          0 :         if( m_pEncryptionBuffer )
    1158                 :          0 :             m_nEncryptionBufferSize = newSize;
    1159                 :            :         else
    1160                 :          0 :             m_nEncryptionBufferSize = 0;
    1161                 :            :     }
    1162                 :          0 :     return ( m_nEncryptionBufferSize != 0 );
    1163                 :            : }
    1164                 :            : 
    1165                 :          0 : void PDFWriterImpl::checkAndEnableStreamEncryption( register sal_Int32 nObject )
    1166                 :            : {
    1167         [ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() )
    1168                 :            :     {
    1169                 :          0 :         m_bEncryptThisStream = true;
    1170                 :          0 :         sal_Int32 i = m_nKeyLength;
    1171         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
    1172         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
    1173         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
    1174                 :            :         //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
    1175                 :            :         // do the MD5 hash
    1176                 :            :         sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    1177                 :            :         // the i+2 to take into account the generation number, always zero
    1178         [ #  # ]:          0 :         rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
    1179                 :            :         // initialize the RC4 with the key
    1180                 :            :         // key legth: see algoritm 3.1, step 4: (N+5) max 16
    1181                 :          0 :         rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
    1182                 :            :     }
    1183                 :          0 : }
    1184                 :            : 
    1185                 :          0 : void PDFWriterImpl::enableStringEncryption( register sal_Int32 nObject )
    1186                 :            : {
    1187         [ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() )
    1188                 :            :     {
    1189                 :          0 :         sal_Int32 i = m_nKeyLength;
    1190         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
    1191         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
    1192         [ #  # ]:          0 :         m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
    1193                 :            :         //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
    1194                 :            :         // do the MD5 hash
    1195                 :            :         sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    1196                 :            :         // the i+2 to take into account the generation number, always zero
    1197         [ #  # ]:          0 :         rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
    1198                 :            :         // initialize the RC4 with the key
    1199                 :            :         // key legth: see algoritm 3.1, step 4: (N+5) max 16
    1200                 :          0 :         rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
    1201                 :            :     }
    1202                 :          0 : }
    1203                 :            : 
    1204                 :            : /* init the encryption engine
    1205                 :            : 1. init the document id, used both for building the document id and for building the encryption key(s)
    1206                 :            : 2. build the encryption key following algorithms described in the PDF specification
    1207                 :            :  */
    1208                 :          0 : uno::Reference< beans::XMaterialHolder > PDFWriterImpl::initEncryption( const rtl::OUString& i_rOwnerPassword,
    1209                 :            :                                                                         const rtl::OUString& i_rUserPassword,
    1210                 :            :                                                                         bool b128Bit
    1211                 :            :                                                                         )
    1212                 :            : {
    1213                 :          0 :     uno::Reference< beans::XMaterialHolder > xResult;
    1214 [ #  # ][ #  # ]:          0 :     if( !i_rOwnerPassword.isEmpty() || !i_rUserPassword.isEmpty() )
                 [ #  # ]
    1215                 :            :     {
    1216         [ #  # ]:          0 :         EncHashTransporter* pTransporter = new EncHashTransporter;
    1217 [ #  # ][ #  # ]:          0 :         xResult = pTransporter;
    1218                 :            : 
    1219                 :            :         // get padded passwords
    1220                 :            :         sal_uInt8 aPadUPW[ENCRYPTED_PWD_SIZE], aPadOPW[ENCRYPTED_PWD_SIZE];
    1221 [ #  # ][ #  # ]:          0 :         padPassword( i_rOwnerPassword.isEmpty() ? i_rUserPassword : i_rOwnerPassword, aPadOPW );
    1222         [ #  # ]:          0 :         padPassword( i_rUserPassword, aPadUPW );
    1223                 :          0 :         sal_Int32 nKeyLength = SECUR_40BIT_KEY;
    1224         [ #  # ]:          0 :         if( b128Bit )
    1225                 :          0 :             nKeyLength = SECUR_128BIT_KEY;
    1226                 :            : 
    1227 [ #  # ][ #  # ]:          0 :         if( computeODictionaryValue( aPadOPW, aPadUPW, pTransporter->getOValue(), nKeyLength ) )
    1228                 :            :         {
    1229                 :          0 :             rtlDigest aDig = pTransporter->getUDigest();
    1230         [ #  # ]:          0 :             if( rtl_digest_updateMD5( aDig, aPadUPW, ENCRYPTED_PWD_SIZE ) != rtl_Digest_E_None )
    1231                 :          0 :                 xResult.clear();
    1232                 :            :         }
    1233                 :            :         else
    1234                 :          0 :             xResult.clear();
    1235                 :            : 
    1236                 :            :         // trash temporary padded cleartext PWDs
    1237                 :          0 :         memset( aPadOPW, 0, sizeof(aPadOPW) );
    1238                 :          0 :         memset( aPadUPW, 0, sizeof(aPadUPW) );
    1239                 :            : 
    1240                 :            :     }
    1241                 :          0 :     return xResult;
    1242                 :            : }
    1243                 :            : 
    1244                 :          0 : bool PDFWriterImpl::prepareEncryption( const uno::Reference< beans::XMaterialHolder >& xEnc )
    1245                 :            : {
    1246                 :          0 :     bool bSuccess = false;
    1247                 :          0 :     EncHashTransporter* pTransporter = EncHashTransporter::getEncHashTransporter( xEnc );
    1248         [ #  # ]:          0 :     if( pTransporter )
    1249                 :            :     {
    1250                 :          0 :         sal_Int32 nKeyLength = 0, nRC4KeyLength = 0;
    1251                 :          0 :         sal_Int32 nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, nKeyLength, nRC4KeyLength );
    1252         [ #  # ]:          0 :         m_aContext.Encryption.OValue = pTransporter->getOValue();
    1253         [ #  # ]:          0 :         bSuccess = computeUDictionaryValue( pTransporter, m_aContext.Encryption, nKeyLength, nAccessPermissions );
    1254                 :            :     }
    1255         [ #  # ]:          0 :     if( ! bSuccess )
    1256                 :            :     {
    1257                 :          0 :         m_aContext.Encryption.OValue.clear();
    1258                 :          0 :         m_aContext.Encryption.UValue.clear();
    1259                 :          0 :         m_aContext.Encryption.EncryptionKey.clear();
    1260                 :            :     }
    1261                 :          0 :     return bSuccess;
    1262                 :            : }
    1263                 :            : 
    1264                 :          0 : sal_Int32 PDFWriterImpl::computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
    1265                 :            :                                                    sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength )
    1266                 :            : {
    1267                 :            :     /*
    1268                 :            :     2) compute the access permissions, in numerical form
    1269                 :            : 
    1270                 :            :     the default value depends on the revision 2 (40 bit) or 3 (128 bit security):
    1271                 :            :     - for 40 bit security the unused bit must be set to 1, since they are not used
    1272                 :            :     - for 128 bit security the same bit must be preset to 0 and set later if needed
    1273                 :            :     according to the table 3.15, pdf v 1.4 */
    1274         [ #  # ]:          0 :     sal_Int32 nAccessPermissions = ( i_rProperties.Security128bit ) ? 0xfffff0c0 : 0xffffffc0 ;
    1275                 :            : 
    1276                 :            :     /* check permissions for 40 bit security case */
    1277         [ #  # ]:          0 :     nAccessPermissions |= ( i_rProperties.CanPrintTheDocument ) ?  1 << 2 : 0;
    1278         [ #  # ]:          0 :     nAccessPermissions |= ( i_rProperties.CanModifyTheContent ) ? 1 << 3 : 0;
    1279         [ #  # ]:          0 :     nAccessPermissions |= ( i_rProperties.CanCopyOrExtract ) ?   1 << 4 : 0;
    1280         [ #  # ]:          0 :     nAccessPermissions |= ( i_rProperties.CanAddOrModify ) ? 1 << 5 : 0;
    1281                 :          0 :     o_rKeyLength = SECUR_40BIT_KEY;
    1282                 :          0 :     o_rRC4KeyLength = SECUR_40BIT_KEY+5; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 5
    1283                 :            : 
    1284         [ #  # ]:          0 :     if( i_rProperties.Security128bit )
    1285                 :            :     {
    1286                 :          0 :         o_rKeyLength = SECUR_128BIT_KEY;
    1287                 :          0 :         o_rRC4KeyLength = 16; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 16, thus maximum
    1288                 :            :         // permitted value is 16
    1289         [ #  # ]:          0 :         nAccessPermissions |= ( i_rProperties.CanFillInteractive ) ?         1 << 8 : 0;
    1290         [ #  # ]:          0 :         nAccessPermissions |= ( i_rProperties.CanExtractForAccessibility ) ? 1 << 9 : 0;
    1291         [ #  # ]:          0 :         nAccessPermissions |= ( i_rProperties.CanAssemble ) ?                1 << 10 : 0;
    1292         [ #  # ]:          0 :         nAccessPermissions |= ( i_rProperties.CanPrintFull ) ?               1 << 11 : 0;
    1293                 :            :     }
    1294                 :          0 :     return nAccessPermissions;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : /*************************************************************
    1298                 :            : begin i12626 methods
    1299                 :            : 
    1300                 :            : Implements Algorithm 3.2, step 1 only
    1301                 :            : */
    1302                 :          0 : void PDFWriterImpl::padPassword( const rtl::OUString& i_rPassword, sal_uInt8* o_pPaddedPW )
    1303                 :            : {
    1304                 :            :     // get ansi-1252 version of the password string CHECKIT ! i12626
    1305         [ #  # ]:          0 :     rtl::OString aString( rtl::OUStringToOString( i_rPassword, RTL_TEXTENCODING_MS_1252 ) );
    1306                 :            : 
    1307                 :            :     //copy the string to the target
    1308         [ #  # ]:          0 :     sal_Int32 nToCopy = ( aString.getLength() < ENCRYPTED_PWD_SIZE ) ? aString.getLength() : ENCRYPTED_PWD_SIZE;
    1309                 :            :     sal_Int32 nCurrentChar;
    1310                 :            : 
    1311         [ #  # ]:          0 :     for( nCurrentChar = 0; nCurrentChar < nToCopy; nCurrentChar++ )
    1312                 :          0 :         o_pPaddedPW[nCurrentChar] = (sal_uInt8)( aString.getStr()[nCurrentChar] );
    1313                 :            : 
    1314                 :            :     //pad it with standard byte string
    1315                 :            :     sal_Int32 i,y;
    1316         [ #  # ]:          0 :     for( i = nCurrentChar, y = 0 ; i < ENCRYPTED_PWD_SIZE; i++, y++ )
    1317                 :          0 :         o_pPaddedPW[i] = s_nPadString[y];
    1318                 :            : 
    1319                 :            :     // trash memory of temporary clear text password
    1320                 :          0 :     memset( (sal_Char*)aString.getStr(), 0, aString.getLength() );
    1321                 :          0 : }
    1322                 :            : 
    1323                 :            : /**********************************
    1324                 :            : Algorithm 3.2  Compute the encryption key used
    1325                 :            : 
    1326                 :            : step 1 should already be done before calling, the paThePaddedPassword parameter should contain
    1327                 :            : the padded password and must be 32 byte long, the encryption key is returned into the paEncryptionKey parameter,
    1328                 :            : it will be 16 byte long for 128 bit security; for 40 bit security only the first 5 bytes are used
    1329                 :            : 
    1330                 :            : TODO: in pdf ver 1.5 and 1.6 the step 6 is different, should be implemented. See spec.
    1331                 :            : 
    1332                 :            : */
    1333                 :          0 : bool PDFWriterImpl::computeEncryptionKey( EncHashTransporter* i_pTransporter, vcl::PDFWriter::PDFEncryptionProperties& io_rProperties, sal_Int32 i_nAccessPermissions )
    1334                 :            : {
    1335                 :          0 :     bool bSuccess = true;
    1336                 :            :     sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    1337                 :            : 
    1338                 :            :     // transporter contains an MD5 digest with the padded user password already
    1339                 :          0 :     rtlDigest aDigest = i_pTransporter->getUDigest();
    1340                 :          0 :     rtlDigestError nError = rtl_Digest_E_None;
    1341         [ #  # ]:          0 :     if( aDigest )
    1342                 :            :     {
    1343                 :            :         //step 3
    1344         [ #  # ]:          0 :         if( ! io_rProperties.OValue.empty() )
    1345         [ #  # ]:          0 :             nError = rtl_digest_updateMD5( aDigest, &io_rProperties.OValue[0] , sal_Int32(io_rProperties.OValue.size()) );
    1346                 :            :         else
    1347                 :          0 :             bSuccess = false;
    1348                 :            :         //Step 4
    1349                 :            :         sal_uInt8 nPerm[4];
    1350                 :            : 
    1351                 :          0 :         nPerm[0] = (sal_uInt8)i_nAccessPermissions;
    1352                 :          0 :         nPerm[1] = (sal_uInt8)( i_nAccessPermissions >> 8 );
    1353                 :          0 :         nPerm[2] = (sal_uInt8)( i_nAccessPermissions >> 16 );
    1354                 :          0 :         nPerm[3] = (sal_uInt8)( i_nAccessPermissions >> 24 );
    1355                 :            : 
    1356         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    1357                 :          0 :             nError = rtl_digest_updateMD5( aDigest, nPerm , sizeof( nPerm ) );
    1358                 :            : 
    1359                 :            :         //step 5, get the document ID, binary form
    1360         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    1361         [ #  # ]:          0 :             nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
    1362                 :            :         //get the digest
    1363         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    1364                 :            :         {
    1365                 :          0 :             rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
    1366                 :            : 
    1367                 :            :             //step 6, only if 128 bit
    1368         [ #  # ]:          0 :             if( io_rProperties.Security128bit )
    1369                 :            :             {
    1370         [ #  # ]:          0 :                 for( sal_Int32 i = 0; i < 50; i++ )
    1371                 :            :                 {
    1372                 :          0 :                     nError = rtl_digest_updateMD5( aDigest, &nMD5Sum, sizeof( nMD5Sum ) );
    1373         [ #  # ]:          0 :                     if( nError != rtl_Digest_E_None )
    1374                 :            :                     {
    1375                 :          0 :                         bSuccess =  false;
    1376                 :          0 :                         break;
    1377                 :            :                     }
    1378                 :          0 :                     rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
    1379                 :            :                 }
    1380                 :            :             }
    1381                 :            :         }
    1382                 :            :     }
    1383                 :            :     else
    1384                 :          0 :         bSuccess = false;
    1385                 :            : 
    1386                 :          0 :     i_pTransporter->invalidate();
    1387                 :            : 
    1388                 :            :     //Step 7
    1389         [ #  # ]:          0 :     if( bSuccess )
    1390                 :            :     {
    1391         [ #  # ]:          0 :         io_rProperties.EncryptionKey.resize( MAXIMUM_RC4_KEY_LENGTH );
    1392         [ #  # ]:          0 :         for( sal_Int32 i = 0; i < MD5_DIGEST_SIZE; i++ )
    1393         [ #  # ]:          0 :             io_rProperties.EncryptionKey[i] = nMD5Sum[i];
    1394                 :            :     }
    1395                 :            :     else
    1396                 :          0 :         io_rProperties.EncryptionKey.clear();
    1397                 :            : 
    1398                 :          0 :     return bSuccess;
    1399                 :            : }
    1400                 :            : 
    1401                 :            : /**********************************
    1402                 :            : Algorithm 3.3  Compute the encryption dictionary /O value, save into the class data member
    1403                 :            : the step numbers down here correspond to the ones in PDF v.1.4 specfication
    1404                 :            : */
    1405                 :          0 : bool PDFWriterImpl::computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword,
    1406                 :            :                                              const sal_uInt8* i_pPaddedUserPassword,
    1407                 :            :                                              std::vector< sal_uInt8 >& io_rOValue,
    1408                 :            :                                              sal_Int32 i_nKeyLength
    1409                 :            :                                              )
    1410                 :            : {
    1411                 :          0 :     bool bSuccess = true;
    1412                 :            : 
    1413                 :          0 :     io_rOValue.resize( ENCRYPTED_PWD_SIZE );
    1414                 :            : 
    1415                 :          0 :     rtlDigest aDigest = rtl_digest_createMD5();
    1416                 :          0 :     rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
    1417 [ #  # ][ #  # ]:          0 :     if( aDigest && aCipher)
    1418                 :            :     {
    1419                 :            :         //step 1 already done, data is in i_pPaddedOwnerPassword
    1420                 :            :         //step 2
    1421                 :            : 
    1422                 :          0 :         rtlDigestError nError = rtl_digest_updateMD5( aDigest, i_pPaddedOwnerPassword, ENCRYPTED_PWD_SIZE );
    1423         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    1424                 :            :         {
    1425                 :            :             sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    1426                 :            : 
    1427                 :          0 :             rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
    1428                 :            : //step 3, only if 128 bit
    1429         [ #  # ]:          0 :             if( i_nKeyLength == SECUR_128BIT_KEY )
    1430                 :            :             {
    1431                 :            :                 sal_Int32 i;
    1432         [ #  # ]:          0 :                 for( i = 0; i < 50; i++ )
    1433                 :            :                 {
    1434                 :          0 :                     nError = rtl_digest_updateMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
    1435         [ #  # ]:          0 :                     if( nError != rtl_Digest_E_None )
    1436                 :            :                     {
    1437                 :          0 :                         bSuccess = false;
    1438                 :          0 :                         break;
    1439                 :            :                     }
    1440                 :          0 :                     rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
    1441                 :            :                 }
    1442                 :            :             }
    1443                 :            :             //Step 4, the key is in nMD5Sum
    1444                 :            :             //step 5 already done, data is in i_pPaddedUserPassword
    1445                 :            :             //step 6
    1446                 :            :             rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
    1447                 :          0 :                                      nMD5Sum, i_nKeyLength , NULL, 0 );
    1448                 :            :             // encrypt the user password using the key set above
    1449                 :            :             rtl_cipher_encodeARCFOUR( aCipher, i_pPaddedUserPassword, ENCRYPTED_PWD_SIZE, // the data to be encrypted
    1450         [ #  # ]:          0 :                                       &io_rOValue[0], sal_Int32(io_rOValue.size()) ); //encrypted data
    1451                 :            :             //Step 7, only if 128 bit
    1452         [ #  # ]:          0 :             if( i_nKeyLength == SECUR_128BIT_KEY )
    1453                 :            :             {
    1454                 :            :                 sal_uInt32 i, y;
    1455                 :            :                 sal_uInt8 nLocalKey[ SECUR_128BIT_KEY ]; // 16 = 128 bit key
    1456                 :            : 
    1457         [ #  # ]:          0 :                 for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
    1458                 :            :                 {
    1459         [ #  # ]:          0 :                     for( y = 0; y < sizeof( nLocalKey ); y++ )
    1460                 :          0 :                         nLocalKey[y] = (sal_uInt8)( nMD5Sum[y] ^ i );
    1461                 :            : 
    1462                 :            :                     rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
    1463                 :          0 :                                             nLocalKey, SECUR_128BIT_KEY, NULL, 0 ); //destination data area, on init can be NULL
    1464         [ #  # ]:          0 :                     rtl_cipher_encodeARCFOUR( aCipher, &io_rOValue[0], sal_Int32(io_rOValue.size()), // the data to be encrypted
    1465         [ #  # ]:          0 :                                               &io_rOValue[0], sal_Int32(io_rOValue.size()) ); // encrypted data, can be the same as the input, encrypt "in place"
    1466                 :            :                     //step 8, store in class data member
    1467                 :            :                 }
    1468                 :            :             }
    1469                 :            :         }
    1470                 :            :         else
    1471                 :          0 :             bSuccess = false;
    1472                 :            :     }
    1473                 :            :     else
    1474                 :          0 :         bSuccess = false;
    1475                 :            : 
    1476         [ #  # ]:          0 :     if( aDigest )
    1477                 :          0 :         rtl_digest_destroyMD5( aDigest );
    1478         [ #  # ]:          0 :     if( aCipher )
    1479                 :          0 :         rtl_cipher_destroyARCFOUR( aCipher );
    1480                 :            : 
    1481         [ #  # ]:          0 :     if( ! bSuccess )
    1482                 :          0 :         io_rOValue.clear();
    1483                 :          0 :     return bSuccess;
    1484                 :            : }
    1485                 :            : 
    1486                 :            : /**********************************
    1487                 :            : Algorithms 3.4 and 3.5  Compute the encryption dictionary /U value, save into the class data member, revision 2 (40 bit) or 3 (128 bit)
    1488                 :            : */
    1489                 :          0 : bool PDFWriterImpl::computeUDictionaryValue( EncHashTransporter* i_pTransporter,
    1490                 :            :                                              vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
    1491                 :            :                                              sal_Int32 i_nKeyLength,
    1492                 :            :                                              sal_Int32 i_nAccessPermissions
    1493                 :            :                                              )
    1494                 :            : {
    1495                 :          0 :     bool bSuccess = true;
    1496                 :            : 
    1497                 :          0 :     io_rProperties.UValue.resize( ENCRYPTED_PWD_SIZE );
    1498                 :            : 
    1499                 :          0 :     rtlDigest aDigest = rtl_digest_createMD5();
    1500                 :          0 :     rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
    1501 [ #  # ][ #  # ]:          0 :     if( aDigest && aCipher )
    1502                 :            :     {
    1503                 :            :         //step 1, common to both 3.4 and 3.5
    1504         [ #  # ]:          0 :         if( computeEncryptionKey( i_pTransporter, io_rProperties, i_nAccessPermissions ) )
    1505                 :            :         {
    1506                 :            :             // prepare encryption key for object
    1507         [ #  # ]:          0 :             for( sal_Int32 i = i_nKeyLength, y = 0; y < 5 ; y++ )
    1508                 :          0 :                 io_rProperties.EncryptionKey[i++] = 0;
    1509                 :            : 
    1510         [ #  # ]:          0 :             if( io_rProperties.Security128bit == false )
    1511                 :            :             {
    1512                 :            :                 //3.4
    1513                 :            :                 //step 2 and 3
    1514                 :            :                 rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
    1515                 :          0 :                                         &io_rProperties.EncryptionKey[0], 5 , // key and key length
    1516                 :          0 :                                         NULL, 0 ); //destination data area
    1517                 :            :                 // encrypt the user password using the key set above, save for later use
    1518                 :            :                 rtl_cipher_encodeARCFOUR( aCipher, s_nPadString, sizeof( s_nPadString ), // the data to be encrypted
    1519                 :          0 :                                           &io_rProperties.UValue[0], sal_Int32(io_rProperties.UValue.size()) ); //encrypted data, stored in class data member
    1520                 :            :             }
    1521                 :            :             else
    1522                 :            :             {
    1523                 :            :                 //or 3.5, for 128 bit security
    1524                 :            :                 //step6, initilize the last 16 bytes of the encrypted user password to 0
    1525         [ #  # ]:          0 :                 for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sal_uInt32(io_rProperties.UValue.size()); i++)
    1526         [ #  # ]:          0 :                     io_rProperties.UValue[i] = 0;
    1527                 :            :                 //step 2
    1528                 :          0 :                 rtlDigestError nError = rtl_digest_updateMD5( aDigest, s_nPadString, sizeof( s_nPadString ) );
    1529                 :            :                 //step 3
    1530         [ #  # ]:          0 :                 if( nError == rtl_Digest_E_None )
    1531         [ #  # ]:          0 :                     nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
    1532                 :            :                 else
    1533                 :          0 :                     bSuccess = false;
    1534                 :            : 
    1535                 :            :                 sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    1536                 :          0 :                 rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
    1537                 :            :                 //Step 4
    1538                 :            :                 rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
    1539         [ #  # ]:          0 :                                         &io_rProperties.EncryptionKey[0], SECUR_128BIT_KEY, NULL, 0 ); //destination data area
    1540                 :            :                 rtl_cipher_encodeARCFOUR( aCipher, nMD5Sum, sizeof( nMD5Sum ), // the data to be encrypted
    1541         [ #  # ]:          0 :                                           &io_rProperties.UValue[0], sizeof( nMD5Sum ) ); //encrypted data, stored in class data member
    1542                 :            :                 //step 5
    1543                 :            :                 sal_uInt32 i, y;
    1544                 :            :                 sal_uInt8 nLocalKey[SECUR_128BIT_KEY];
    1545                 :            : 
    1546         [ #  # ]:          0 :                 for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
    1547                 :            :                 {
    1548         [ #  # ]:          0 :                     for( y = 0; y < sizeof( nLocalKey ) ; y++ )
    1549         [ #  # ]:          0 :                         nLocalKey[y] = (sal_uInt8)( io_rProperties.EncryptionKey[y] ^ i );
    1550                 :            : 
    1551                 :            :                     rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
    1552                 :            :                                             nLocalKey, SECUR_128BIT_KEY, // key and key length
    1553                 :          0 :                                             NULL, 0 ); //destination data area, on init can be NULL
    1554         [ #  # ]:          0 :                     rtl_cipher_encodeARCFOUR( aCipher, &io_rProperties.UValue[0], SECUR_128BIT_KEY, // the data to be encrypted
    1555         [ #  # ]:          0 :                                               &io_rProperties.UValue[0], SECUR_128BIT_KEY ); // encrypted data, can be the same as the input, encrypt "in place"
    1556                 :            :                 }
    1557                 :            :             }
    1558                 :            :         }
    1559                 :            :         else
    1560                 :          0 :             bSuccess = false;
    1561                 :            :     }
    1562                 :            :     else
    1563                 :          0 :         bSuccess = false;
    1564                 :            : 
    1565         [ #  # ]:          0 :     if( aDigest )
    1566                 :          0 :         rtl_digest_destroyMD5( aDigest );
    1567         [ #  # ]:          0 :     if( aCipher )
    1568                 :          0 :         rtl_cipher_destroyARCFOUR( aCipher );
    1569                 :            : 
    1570         [ #  # ]:          0 :     if( ! bSuccess )
    1571                 :          0 :         io_rProperties.UValue.clear();
    1572                 :          0 :     return bSuccess;
    1573                 :            : }
    1574                 :            : 
    1575                 :            : /* end i12626 methods */
    1576                 :            : 
    1577                 :            : static const long unsetRun[256] =
    1578                 :            : {
    1579                 :            :     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
    1580                 :            :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
    1581                 :            :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
    1582                 :            :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
    1583                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
    1584                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
    1585                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
    1586                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
    1587                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
    1588                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
    1589                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
    1590                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
    1591                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
    1592                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
    1593                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
    1594                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
    1595                 :            : };
    1596                 :            : 
    1597                 :            : static const long setRun[256] =
    1598                 :            : {
    1599                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
    1600                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
    1601                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
    1602                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
    1603                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
    1604                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
    1605                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
    1606                 :            :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
    1607                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
    1608                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
    1609                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
    1610                 :            :     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
    1611                 :            :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
    1612                 :            :     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
    1613                 :            :     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
    1614                 :            :     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
    1615                 :            : };
    1616                 :            : 
    1617                 :          0 : inline bool isSet( const Scanline i_pLine, long i_nIndex )
    1618                 :            : {
    1619                 :          0 :     return (i_pLine[ i_nIndex/8 ] & (0x80 >> (i_nIndex&7))) != 0;
    1620                 :            : }
    1621                 :            : 
    1622                 :          0 : long findBitRun( const Scanline i_pLine, long i_nStartIndex, long i_nW, bool i_bSet )
    1623                 :            : {
    1624         [ #  # ]:          0 :     if( i_nStartIndex < 0 )
    1625                 :          0 :         return i_nW;
    1626                 :            : 
    1627                 :          0 :     long nIndex = i_nStartIndex;
    1628         [ #  # ]:          0 :     if( nIndex < i_nW )
    1629                 :            :     {
    1630                 :          0 :         const sal_uInt8 * pByte = static_cast<sal_uInt8*>(i_pLine) + (nIndex/8);
    1631                 :          0 :         sal_uInt8 nByte = *pByte;
    1632                 :            : 
    1633                 :            :         // run up to byte boundary
    1634                 :          0 :         long nBitInByte = (nIndex & 7);
    1635         [ #  # ]:          0 :         if( nBitInByte )
    1636                 :            :         {
    1637                 :          0 :             sal_uInt8 nMask = 0x80 >> nBitInByte;
    1638         [ #  # ]:          0 :             while( nBitInByte != 8 )
    1639                 :            :             {
    1640 [ #  # ][ #  # ]:          0 :                 if( (nByte & nMask) != (i_bSet ? nMask : 0) )
    1641         [ #  # ]:          0 :                     return nIndex < i_nW ? nIndex : i_nW;
    1642                 :          0 :                 nMask = nMask >> 1;
    1643                 :          0 :                 nBitInByte++;
    1644                 :          0 :                 nIndex++;
    1645                 :            :             }
    1646         [ #  # ]:          0 :             if( nIndex < i_nW )
    1647                 :            :             {
    1648                 :          0 :                 pByte++;
    1649                 :          0 :                 nByte = *pByte;
    1650                 :            :             }
    1651                 :            :         }
    1652                 :            : 
    1653                 :            :         sal_uInt8 nRunByte;
    1654                 :            :         const long* pRunTable;
    1655         [ #  # ]:          0 :         if( i_bSet )
    1656                 :            :         {
    1657                 :          0 :             nRunByte = 0xff;
    1658                 :          0 :             pRunTable = setRun;
    1659                 :            :         }
    1660                 :            :         else
    1661                 :            :         {
    1662                 :          0 :             nRunByte = 0;
    1663                 :          0 :             pRunTable = unsetRun;
    1664                 :            :         }
    1665                 :            : 
    1666         [ #  # ]:          0 :         if( nIndex < i_nW )
    1667                 :            :         {
    1668         [ #  # ]:          0 :             while( nByte == nRunByte )
    1669                 :            :             {
    1670                 :          0 :                 nIndex += 8;
    1671                 :            : 
    1672         [ #  # ]:          0 :                 if (nIndex >= i_nW)
    1673                 :          0 :                     break;
    1674                 :            : 
    1675                 :          0 :                 pByte++;
    1676                 :          0 :                 nByte = *pByte;
    1677                 :            :             }
    1678                 :            :         }
    1679                 :            : 
    1680         [ #  # ]:          0 :         if( nIndex < i_nW )
    1681                 :            :         {
    1682                 :          0 :             nIndex += pRunTable[nByte];
    1683                 :            :         }
    1684                 :            :     }
    1685         [ #  # ]:          0 :     return nIndex < i_nW ? nIndex : i_nW;
    1686                 :            : }
    1687                 :            : 
    1688                 :            : struct BitStreamState
    1689                 :            : {
    1690                 :            :     sal_uInt8       mnBuffer;
    1691                 :            :     sal_uInt32      mnNextBitPos;
    1692                 :            : 
    1693                 :          0 :     BitStreamState()
    1694                 :            :     : mnBuffer( 0 )
    1695                 :          0 :     , mnNextBitPos( 8 )
    1696                 :            :     {
    1697                 :          0 :     }
    1698                 :            : 
    1699                 :          0 :     const sal_uInt8* getByte() const { return &mnBuffer; }
    1700                 :          0 :     void flush() { mnNextBitPos = 8; mnBuffer = 0; }
    1701                 :            : };
    1702                 :            : 
    1703                 :          0 : void PDFWriterImpl::putG4Bits( sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState& io_rState )
    1704                 :            : {
    1705         [ #  # ]:          0 :     while( i_nLength > io_rState.mnNextBitPos )
    1706                 :            :     {
    1707                 :          0 :         io_rState.mnBuffer |= static_cast<sal_uInt8>( i_nCode >> (i_nLength - io_rState.mnNextBitPos) );
    1708                 :          0 :         i_nLength -= io_rState.mnNextBitPos;
    1709                 :          0 :         writeBuffer( io_rState.getByte(), 1 );
    1710                 :          0 :         io_rState.flush();
    1711                 :            :     }
    1712                 :            :     OSL_ASSERT( i_nLength < 9 );
    1713                 :            :     static const unsigned int msbmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
    1714                 :          0 :     io_rState.mnBuffer |= static_cast<sal_uInt8>( (i_nCode & msbmask[i_nLength]) << (io_rState.mnNextBitPos - i_nLength) );
    1715                 :          0 :     io_rState.mnNextBitPos -= i_nLength;
    1716         [ #  # ]:          0 :     if( io_rState.mnNextBitPos == 0 )
    1717                 :            :     {
    1718                 :          0 :         writeBuffer( io_rState.getByte(), 1 );
    1719                 :          0 :         io_rState.flush();
    1720                 :            :     }
    1721                 :          0 : }
    1722                 :            : 
    1723                 :            : struct PixelCode
    1724                 :            : {
    1725                 :            :     sal_uInt32      mnEncodedPixels;
    1726                 :            :     sal_uInt32      mnCodeBits;
    1727                 :            :     sal_uInt32      mnCode;
    1728                 :            : };
    1729                 :            : 
    1730                 :            : static const PixelCode WhitePixelCodes[] =
    1731                 :            : {
    1732                 :            :     { 0, 8, 0x35 },     // 0011 0101
    1733                 :            :     { 1, 6, 0x7 },      // 0001 11
    1734                 :            :     { 2, 4, 0x7 },      // 0111
    1735                 :            :     { 3, 4, 0x8 },      // 1000
    1736                 :            :     { 4, 4, 0xB },      // 1011
    1737                 :            :     { 5, 4, 0xC },      // 1100
    1738                 :            :     { 6, 4, 0xE },      // 1110
    1739                 :            :     { 7, 4, 0xF },      // 1111
    1740                 :            :     { 8, 5, 0x13 },     // 1001 1
    1741                 :            :     { 9, 5, 0x14 },     // 1010 0
    1742                 :            :     { 10, 5, 0x7 },     // 0011 1
    1743                 :            :     { 11, 5, 0x8 },     // 0100 0
    1744                 :            :     { 12, 6, 0x8 },     // 0010 00
    1745                 :            :     { 13, 6, 0x3 },     // 0000 11
    1746                 :            :     { 14, 6, 0x34 },    // 1101 00
    1747                 :            :     { 15, 6, 0x35 },    // 1101 01
    1748                 :            :     { 16, 6, 0x2A },    // 1010 10
    1749                 :            :     { 17, 6, 0x2B },    // 1010 11
    1750                 :            :     { 18, 7, 0x27 },    // 0100 111
    1751                 :            :     { 19, 7, 0xC },     // 0001 100
    1752                 :            :     { 20, 7, 0x8 },     // 0001 000
    1753                 :            :     { 21, 7, 0x17 },    // 0010 111
    1754                 :            :     { 22, 7, 0x3 },     // 0000 011
    1755                 :            :     { 23, 7, 0x4 },     // 0000 100
    1756                 :            :     { 24, 7, 0x28 },    // 0101 000
    1757                 :            :     { 25, 7, 0x2B },    // 0101 011
    1758                 :            :     { 26, 7, 0x13 },    // 0010 011
    1759                 :            :     { 27, 7, 0x24 },    // 0100 100
    1760                 :            :     { 28, 7, 0x18 },    // 0011 000
    1761                 :            :     { 29, 8, 0x2 },     // 0000 0010
    1762                 :            :     { 30, 8, 0x3 },     // 0000 0011
    1763                 :            :     { 31, 8, 0x1A },    // 0001 1010
    1764                 :            :     { 32, 8, 0x1B },    // 0001 1011
    1765                 :            :     { 33, 8, 0x12 },    // 0001 0010
    1766                 :            :     { 34, 8, 0x13 },    // 0001 0011
    1767                 :            :     { 35, 8, 0x14 },    // 0001 0100
    1768                 :            :     { 36, 8, 0x15 },    // 0001 0101
    1769                 :            :     { 37, 8, 0x16 },    // 0001 0110
    1770                 :            :     { 38, 8, 0x17 },    // 0001 0111
    1771                 :            :     { 39, 8, 0x28 },    // 0010 1000
    1772                 :            :     { 40, 8, 0x29 },    // 0010 1001
    1773                 :            :     { 41, 8, 0x2A },    // 0010 1010
    1774                 :            :     { 42, 8, 0x2B },    // 0010 1011
    1775                 :            :     { 43, 8, 0x2C },    // 0010 1100
    1776                 :            :     { 44, 8, 0x2D },    // 0010 1101
    1777                 :            :     { 45, 8, 0x4 },     // 0000 0100
    1778                 :            :     { 46, 8, 0x5 },     // 0000 0101
    1779                 :            :     { 47, 8, 0xA },     // 0000 1010
    1780                 :            :     { 48, 8, 0xB },     // 0000 1011
    1781                 :            :     { 49, 8, 0x52 },    // 0101 0010
    1782                 :            :     { 50, 8, 0x53 },    // 0101 0011
    1783                 :            :     { 51, 8, 0x54 },    // 0101 0100
    1784                 :            :     { 52, 8, 0x55 },    // 0101 0101
    1785                 :            :     { 53, 8, 0x24 },    // 0010 0100
    1786                 :            :     { 54, 8, 0x25 },    // 0010 0101
    1787                 :            :     { 55, 8, 0x58 },    // 0101 1000
    1788                 :            :     { 56, 8, 0x59 },    // 0101 1001
    1789                 :            :     { 57, 8, 0x5A },    // 0101 1010
    1790                 :            :     { 58, 8, 0x5B },    // 0101 1011
    1791                 :            :     { 59, 8, 0x4A },    // 0100 1010
    1792                 :            :     { 60, 8, 0x4B },    // 0100 1011
    1793                 :            :     { 61, 8, 0x32 },    // 0011 0010
    1794                 :            :     { 62, 8, 0x33 },    // 0011 0011
    1795                 :            :     { 63, 8, 0x34 },    // 0011 0100
    1796                 :            :     { 64, 5, 0x1B },    // 1101 1
    1797                 :            :     { 128, 5, 0x12 },   // 1001 0
    1798                 :            :     { 192, 6, 0x17 },   // 0101 11
    1799                 :            :     { 256, 7, 0x37 },   // 0110 111
    1800                 :            :     { 320, 8, 0x36 },   // 0011 0110
    1801                 :            :     { 384, 8, 0x37 },   // 0011 0111
    1802                 :            :     { 448, 8, 0x64 },   // 0110 0100
    1803                 :            :     { 512, 8, 0x65 },   // 0110 0101
    1804                 :            :     { 576, 8, 0x68 },   // 0110 1000
    1805                 :            :     { 640, 8, 0x67 },   // 0110 0111
    1806                 :            :     { 704, 9, 0xCC },   // 0110 0110 0
    1807                 :            :     { 768, 9, 0xCD },   // 0110 0110 1
    1808                 :            :     { 832, 9, 0xD2 },   // 0110 1001 0
    1809                 :            :     { 896, 9, 0xD3 },   // 0110 1001 1
    1810                 :            :     { 960, 9, 0xD4 },   // 0110 1010 0
    1811                 :            :     { 1024, 9, 0xD5 },  // 0110 1010 1
    1812                 :            :     { 1088, 9, 0xD6 },  // 0110 1011 0
    1813                 :            :     { 1152, 9, 0xD7 },  // 0110 1011 1
    1814                 :            :     { 1216, 9, 0xD8 },  // 0110 1100 0
    1815                 :            :     { 1280, 9, 0xD9 },  // 0110 1100 1
    1816                 :            :     { 1344, 9, 0xDA },  // 0110 1101 0
    1817                 :            :     { 1408, 9, 0xDB },  // 0110 1101 1
    1818                 :            :     { 1472, 9, 0x98 },  // 0100 1100 0
    1819                 :            :     { 1536, 9, 0x99 },  // 0100 1100 1
    1820                 :            :     { 1600, 9, 0x9A },  // 0100 1101 0
    1821                 :            :     { 1664, 6, 0x18 },  // 0110 00
    1822                 :            :     { 1728, 9, 0x9B },  // 0100 1101 1
    1823                 :            :     { 1792, 11, 0x8 },  // 0000 0001 000
    1824                 :            :     { 1856, 11, 0xC },  // 0000 0001 100
    1825                 :            :     { 1920, 11, 0xD },  // 0000 0001 101
    1826                 :            :     { 1984, 12, 0x12 }, // 0000 0001 0010
    1827                 :            :     { 2048, 12, 0x13 }, // 0000 0001 0011
    1828                 :            :     { 2112, 12, 0x14 }, // 0000 0001 0100
    1829                 :            :     { 2176, 12, 0x15 }, // 0000 0001 0101
    1830                 :            :     { 2240, 12, 0x16 }, // 0000 0001 0110
    1831                 :            :     { 2304, 12, 0x17 }, // 0000 0001 0111
    1832                 :            :     { 2368, 12, 0x1C }, // 0000 0001 1100
    1833                 :            :     { 2432, 12, 0x1D }, // 0000 0001 1101
    1834                 :            :     { 2496, 12, 0x1E }, // 0000 0001 1110
    1835                 :            :     { 2560, 12, 0x1F }  // 0000 0001 1111
    1836                 :            : };
    1837                 :            : 
    1838                 :            : static const PixelCode BlackPixelCodes[] =
    1839                 :            : {
    1840                 :            :     { 0, 10, 0x37 },    // 0000 1101 11
    1841                 :            :     { 1, 3, 0x2 },      // 010
    1842                 :            :     { 2, 2, 0x3 },      // 11
    1843                 :            :     { 3, 2, 0x2 },      // 10
    1844                 :            :     { 4, 3, 0x3 },      // 011
    1845                 :            :     { 5, 4, 0x3 },      // 0011
    1846                 :            :     { 6, 4, 0x2 },      // 0010
    1847                 :            :     { 7, 5, 0x3 },      // 0001 1
    1848                 :            :     { 8, 6, 0x5 },      // 0001 01
    1849                 :            :     { 9, 6, 0x4 },      // 0001 00
    1850                 :            :     { 10, 7, 0x4 },     // 0000 100
    1851                 :            :     { 11, 7, 0x5 },     // 0000 101
    1852                 :            :     { 12, 7, 0x7 },     // 0000 111
    1853                 :            :     { 13, 8, 0x4 },     // 0000 0100
    1854                 :            :     { 14, 8, 0x7 },     // 0000 0111
    1855                 :            :     { 15, 9, 0x18 },    // 0000 1100 0
    1856                 :            :     { 16, 10, 0x17 },   // 0000 0101 11
    1857                 :            :     { 17, 10, 0x18 },   // 0000 0110 00
    1858                 :            :     { 18, 10, 0x8 },    // 0000 0010 00
    1859                 :            :     { 19, 11, 0x67 },   // 0000 1100 111
    1860                 :            :     { 20, 11, 0x68 },   // 0000 1101 000
    1861                 :            :     { 21, 11, 0x6C },   // 0000 1101 100
    1862                 :            :     { 22, 11, 0x37 },   // 0000 0110 111
    1863                 :            :     { 23, 11, 0x28 },   // 0000 0101 000
    1864                 :            :     { 24, 11, 0x17 },   // 0000 0010 111
    1865                 :            :     { 25, 11, 0x18 },   // 0000 0011 000
    1866                 :            :     { 26, 12, 0xCA },   // 0000 1100 1010
    1867                 :            :     { 27, 12, 0xCB },   // 0000 1100 1011
    1868                 :            :     { 28, 12, 0xCC },   // 0000 1100 1100
    1869                 :            :     { 29, 12, 0xCD },   // 0000 1100 1101
    1870                 :            :     { 30, 12, 0x68 },   // 0000 0110 1000
    1871                 :            :     { 31, 12, 0x69 },   // 0000 0110 1001
    1872                 :            :     { 32, 12, 0x6A },   // 0000 0110 1010
    1873                 :            :     { 33, 12, 0x6B },   // 0000 0110 1011
    1874                 :            :     { 34, 12, 0xD2 },   // 0000 1101 0010
    1875                 :            :     { 35, 12, 0xD3 },   // 0000 1101 0011
    1876                 :            :     { 36, 12, 0xD4 },   // 0000 1101 0100
    1877                 :            :     { 37, 12, 0xD5 },   // 0000 1101 0101
    1878                 :            :     { 38, 12, 0xD6 },   // 0000 1101 0110
    1879                 :            :     { 39, 12, 0xD7 },   // 0000 1101 0111
    1880                 :            :     { 40, 12, 0x6C },   // 0000 0110 1100
    1881                 :            :     { 41, 12, 0x6D },   // 0000 0110 1101
    1882                 :            :     { 42, 12, 0xDA },   // 0000 1101 1010
    1883                 :            :     { 43, 12, 0xDB },   // 0000 1101 1011
    1884                 :            :     { 44, 12, 0x54 },   // 0000 0101 0100
    1885                 :            :     { 45, 12, 0x55 },   // 0000 0101 0101
    1886                 :            :     { 46, 12, 0x56 },   // 0000 0101 0110
    1887                 :            :     { 47, 12, 0x57 },   // 0000 0101 0111
    1888                 :            :     { 48, 12, 0x64 },   // 0000 0110 0100
    1889                 :            :     { 49, 12, 0x65 },   // 0000 0110 0101
    1890                 :            :     { 50, 12, 0x52 },   // 0000 0101 0010
    1891                 :            :     { 51, 12, 0x53 },   // 0000 0101 0011
    1892                 :            :     { 52, 12, 0x24 },   // 0000 0010 0100
    1893                 :            :     { 53, 12, 0x37 },   // 0000 0011 0111
    1894                 :            :     { 54, 12, 0x38 },   // 0000 0011 1000
    1895                 :            :     { 55, 12, 0x27 },   // 0000 0010 0111
    1896                 :            :     { 56, 12, 0x28 },   // 0000 0010 1000
    1897                 :            :     { 57, 12, 0x58 },   // 0000 0101 1000
    1898                 :            :     { 58, 12, 0x59 },   // 0000 0101 1001
    1899                 :            :     { 59, 12, 0x2B },   // 0000 0010 1011
    1900                 :            :     { 60, 12, 0x2C },   // 0000 0010 1100
    1901                 :            :     { 61, 12, 0x5A },   // 0000 0101 1010
    1902                 :            :     { 62, 12, 0x66 },   // 0000 0110 0110
    1903                 :            :     { 63, 12, 0x67 },   // 0000 0110 0111
    1904                 :            :     { 64, 10, 0xF },    // 0000 0011 11
    1905                 :            :     { 128, 12, 0xC8 },  // 0000 1100 1000
    1906                 :            :     { 192, 12, 0xC9 },  // 0000 1100 1001
    1907                 :            :     { 256, 12, 0x5B },  // 0000 0101 1011
    1908                 :            :     { 320, 12, 0x33 },  // 0000 0011 0011
    1909                 :            :     { 384, 12, 0x34 },  // 0000 0011 0100
    1910                 :            :     { 448, 12, 0x35 },  // 0000 0011 0101
    1911                 :            :     { 512, 13, 0x6C },  // 0000 0011 0110 0
    1912                 :            :     { 576, 13, 0x6D },  // 0000 0011 0110 1
    1913                 :            :     { 640, 13, 0x4A },  // 0000 0010 0101 0
    1914                 :            :     { 704, 13, 0x4B },  // 0000 0010 0101 1
    1915                 :            :     { 768, 13, 0x4C },  // 0000 0010 0110 0
    1916                 :            :     { 832, 13, 0x4D },  // 0000 0010 0110 1
    1917                 :            :     { 896, 13, 0x72 },  // 0000 0011 1001 0
    1918                 :            :     { 960, 13, 0x73 },  // 0000 0011 1001 1
    1919                 :            :     { 1024, 13, 0x74 }, // 0000 0011 1010 0
    1920                 :            :     { 1088, 13, 0x75 }, // 0000 0011 1010 1
    1921                 :            :     { 1152, 13, 0x76 }, // 0000 0011 1011 0
    1922                 :            :     { 1216, 13, 0x77 }, // 0000 0011 1011 1
    1923                 :            :     { 1280, 13, 0x52 }, // 0000 0010 1001 0
    1924                 :            :     { 1344, 13, 0x53 }, // 0000 0010 1001 1
    1925                 :            :     { 1408, 13, 0x54 }, // 0000 0010 1010 0
    1926                 :            :     { 1472, 13, 0x55 }, // 0000 0010 1010 1
    1927                 :            :     { 1536, 13, 0x5A }, // 0000 0010 1101 0
    1928                 :            :     { 1600, 13, 0x5B }, // 0000 0010 1101 1
    1929                 :            :     { 1664, 13, 0x64 }, // 0000 0011 0010 0
    1930                 :            :     { 1728, 13, 0x65 }, // 0000 0011 0010 1
    1931                 :            :     { 1792, 11, 0x8 },  // 0000 0001 000
    1932                 :            :     { 1856, 11, 0xC },  // 0000 0001 100
    1933                 :            :     { 1920, 11, 0xD },  // 0000 0001 101
    1934                 :            :     { 1984, 12, 0x12 }, // 0000 0001 0010
    1935                 :            :     { 2048, 12, 0x13 }, // 0000 0001 0011
    1936                 :            :     { 2112, 12, 0x14 }, // 0000 0001 0100
    1937                 :            :     { 2176, 12, 0x15 }, // 0000 0001 0101
    1938                 :            :     { 2240, 12, 0x16 }, // 0000 0001 0110
    1939                 :            :     { 2304, 12, 0x17 }, // 0000 0001 0111
    1940                 :            :     { 2368, 12, 0x1C }, // 0000 0001 1100
    1941                 :            :     { 2432, 12, 0x1D }, // 0000 0001 1101
    1942                 :            :     { 2496, 12, 0x1E }, // 0000 0001 1110
    1943                 :            :     { 2560, 12, 0x1F }  // 0000 0001 1111
    1944                 :            : };
    1945                 :            : 
    1946                 :            : 
    1947                 :          0 : void PDFWriterImpl::putG4Span( long i_nSpan, bool i_bWhitePixel, BitStreamState& io_rState )
    1948                 :            : {
    1949         [ #  # ]:          0 :     const PixelCode* pTable = i_bWhitePixel ? WhitePixelCodes : BlackPixelCodes;
    1950                 :            :     // maximum encoded span is 2560 consecutive pixels
    1951         [ #  # ]:          0 :     while( i_nSpan > 2623 )
    1952                 :            :     {
    1953                 :            :         // write 2560 bits, that is entry (63 + (2560 >> 6)) == 103 in the appropriate table
    1954                 :          0 :         putG4Bits( pTable[103].mnCodeBits, pTable[103].mnCode, io_rState );
    1955                 :          0 :         i_nSpan -= pTable[103].mnEncodedPixels;
    1956                 :            :     }
    1957                 :            :     // write multiples of 64 pixels up to 2560
    1958         [ #  # ]:          0 :     if( i_nSpan > 63 )
    1959                 :            :     {
    1960                 :          0 :         sal_uInt32 nTabIndex = 63 + (i_nSpan >> 6);
    1961                 :            :         OSL_ASSERT( pTable[nTabIndex].mnEncodedPixels == static_cast<sal_uInt32>(64*(i_nSpan >> 6)) );
    1962                 :          0 :         putG4Bits( pTable[nTabIndex].mnCodeBits, pTable[nTabIndex].mnCode, io_rState );
    1963                 :          0 :         i_nSpan -= pTable[nTabIndex].mnEncodedPixels;
    1964                 :            :     }
    1965                 :          0 :     putG4Bits( pTable[i_nSpan].mnCodeBits, pTable[i_nSpan].mnCode, io_rState );
    1966                 :          0 : }
    1967                 :            : 
    1968                 :          0 : void PDFWriterImpl::writeG4Stream( BitmapReadAccess* i_pBitmap )
    1969                 :            : {
    1970                 :          0 :     long nW = i_pBitmap->Width();
    1971                 :          0 :     long nH = i_pBitmap->Height();
    1972 [ #  # ][ #  # ]:          0 :     if( nW <= 0 || nH <= 0 )
    1973                 :            :         return;
    1974         [ #  # ]:          0 :     if( i_pBitmap->GetBitCount() != 1 )
    1975                 :            :         return;
    1976                 :            : 
    1977                 :          0 :     BitStreamState aBitState;
    1978                 :            : 
    1979                 :            :     // the first reference line is virtual and completely empty
    1980                 :          0 :     const Scanline pFirstRefLine = (Scanline)rtl_allocateZeroMemory( nW/8 + 1 );
    1981                 :          0 :     Scanline pRefLine = pFirstRefLine;
    1982         [ #  # ]:          0 :     for( long nY = 0; nY < nH; nY++ )
    1983                 :            :     {
    1984                 :          0 :         const Scanline pCurLine = i_pBitmap->GetScanline( nY );
    1985                 :          0 :         long nLineIndex = 0;
    1986                 :          0 :         bool bRunSet = (*pCurLine & 0x80) ? true : false;
    1987                 :          0 :         bool bRefSet = (*pRefLine & 0x80) ? true : false;
    1988         [ #  # ]:          0 :         long nRunIndex1 = bRunSet ? 0 : findBitRun( pCurLine, 0, nW, bRunSet );
    1989         [ #  # ]:          0 :         long nRefIndex1 = bRefSet ? 0 : findBitRun( pRefLine, 0, nW, bRefSet );
    1990         [ #  # ]:          0 :         for( ; nLineIndex < nW; )
    1991                 :            :         {
    1992                 :          0 :             long nRefIndex2 = findBitRun( pRefLine, nRefIndex1, nW, isSet( pRefLine, nRefIndex1 ) );
    1993         [ #  # ]:          0 :             if( nRefIndex2 >= nRunIndex1 )
    1994                 :            :             {
    1995                 :          0 :                 long nDiff = nRefIndex1 - nRunIndex1;
    1996 [ #  # ][ #  # ]:          0 :                 if( -3 <= nDiff && nDiff <= 3 )
    1997                 :            :                 {   // vertical coding
    1998                 :            :                     static const struct
    1999                 :            :                     {
    2000                 :            :                         sal_uInt32 mnCodeBits;
    2001                 :            :                         sal_uInt32 mnCode;
    2002                 :            :                     } VerticalCodes[7] = {
    2003                 :            :                         { 7, 0x03 },    // 0000 011
    2004                 :            :                         { 6, 0x03 },    // 0000 11
    2005                 :            :                         { 3, 0x03 },    // 011
    2006                 :            :                         { 1, 0x1 },     // 1
    2007                 :            :                         { 3, 0x2 },     // 010
    2008                 :            :                         { 6, 0x02 },    // 0000 10
    2009                 :            :                         { 7, 0x02 }     // 0000 010
    2010                 :            :                     };
    2011                 :            :                     // convert to index
    2012                 :          0 :                     nDiff += 3;
    2013                 :            : 
    2014                 :            :                     // emit diff code
    2015         [ #  # ]:          0 :                     putG4Bits( VerticalCodes[nDiff].mnCodeBits, VerticalCodes[nDiff].mnCode, aBitState );
    2016                 :          0 :                     nLineIndex = nRunIndex1;
    2017                 :            :                 }
    2018                 :            :                 else
    2019                 :            :                 {   // difference too large, horizontal coding
    2020                 :            :                     // emit horz code 001
    2021         [ #  # ]:          0 :                     putG4Bits( 3, 0x1, aBitState );
    2022                 :          0 :                     long nRunIndex2 = findBitRun( pCurLine, nRunIndex1, nW, isSet( pCurLine, nRunIndex1 ) );
    2023 [ #  # ][ #  # ]:          0 :                     bool bWhiteFirst = ( nLineIndex + nRunIndex1 == 0 || ! isSet( pCurLine, nLineIndex ) );
    2024         [ #  # ]:          0 :                     putG4Span( nRunIndex1 - nLineIndex, bWhiteFirst, aBitState );
    2025         [ #  # ]:          0 :                     putG4Span( nRunIndex2 - nRunIndex1, ! bWhiteFirst, aBitState );
    2026                 :          0 :                     nLineIndex = nRunIndex2;
    2027                 :            :                 }
    2028                 :            :             }
    2029                 :            :             else
    2030                 :            :             {   // emit pass code 0001
    2031         [ #  # ]:          0 :                 putG4Bits( 4, 0x1, aBitState );
    2032                 :          0 :                 nLineIndex = nRefIndex2;
    2033                 :            :             }
    2034         [ #  # ]:          0 :             if( nLineIndex < nW )
    2035                 :            :             {
    2036                 :          0 :                 bool bSet = isSet( pCurLine, nLineIndex );
    2037                 :          0 :                 nRunIndex1 = findBitRun( pCurLine, nLineIndex, nW, bSet );
    2038                 :          0 :                 nRefIndex1 = findBitRun( pRefLine, nLineIndex, nW, ! bSet );
    2039                 :          0 :                 nRefIndex1 = findBitRun( pRefLine, nRefIndex1, nW, bSet );
    2040                 :            :             }
    2041                 :            :         }
    2042                 :            : 
    2043                 :            :         // the current line is the reference for the next line
    2044                 :          0 :         pRefLine = pCurLine;
    2045                 :            :     }
    2046                 :            :     // terminate strip with EOFB
    2047         [ #  # ]:          0 :     putG4Bits( 12, 1, aBitState );
    2048         [ #  # ]:          0 :     putG4Bits( 12, 1, aBitState );
    2049         [ #  # ]:          0 :     if( aBitState.mnNextBitPos != 8 )
    2050                 :            :     {
    2051         [ #  # ]:          0 :         writeBuffer( aBitState.getByte(), 1 );
    2052                 :          0 :         aBitState.flush();
    2053                 :            :     }
    2054                 :            : 
    2055                 :          0 :     rtl_freeMemory( pFirstRefLine );
    2056 [ +  - ][ +  - ]:        843 : }
    2057                 :            : 
    2058                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10