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

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #define _USE_MATH_DEFINES
      31                 :            : #include <math.h>
      32                 :            : #include <algorithm>
      33                 :            : 
      34                 :            : #include <tools/urlobj.hxx>
      35                 :            : 
      36                 :            : #include <pdfwriter_impl.hxx>
      37                 :            : 
      38                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      39                 :            : #include <basegfx/polygon/b2dpolypolygon.hxx>
      40                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      41                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      42                 :            : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
      43                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      44                 :            : 
      45                 :            : #include <osl/thread.h>
      46                 :            : #include <osl/file.h>
      47                 :            : 
      48                 :            : #include <rtl/crc.h>
      49                 :            : #include <rtl/digest.h>
      50                 :            : #include <rtl/ustrbuf.hxx>
      51                 :            : 
      52                 :            : #include <tools/debug.hxx>
      53                 :            : #include <tools/zcodec.hxx>
      54                 :            : #include <tools/stream.hxx>
      55                 :            : 
      56                 :            : #include <i18npool/mslangid.hxx>
      57                 :            : 
      58                 :            : #include <vcl/virdev.hxx>
      59                 :            : #include <vcl/bmpacc.hxx>
      60                 :            : #include <vcl/bitmapex.hxx>
      61                 :            : #include <vcl/image.hxx>
      62                 :            : #include <vcl/metric.hxx>
      63                 :            : #include <vcl/svapp.hxx>
      64                 :            : #include <vcl/lineinfo.hxx>
      65                 :            : #include "vcl/cvtgrf.hxx"
      66                 :            : #include "vcl/strhelper.hxx"
      67                 :            : 
      68                 :            : #include <fontsubset.hxx>
      69                 :            : #include <outdev.h>
      70                 :            : #include <sallayout.hxx>
      71                 :            : #include <textlayout.hxx>
      72                 :            : #include <salgdi.hxx>
      73                 :            : 
      74                 :            : #include <lcms2.h>
      75                 :            : 
      76                 :            : #include <comphelper/processfactory.hxx>
      77                 :            : #include <comphelper/string.hxx>
      78                 :            : 
      79                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      80                 :            : #include <com/sun/star/util/URLTransformer.hpp>
      81                 :            : #include <com/sun/star/util/URL.hpp>
      82                 :            : 
      83                 :            : #include "cppuhelper/implbase1.hxx"
      84                 :            : 
      85                 :            : #if !defined(ANDROID) && !defined(IOS)
      86                 :            : // NSS header files for PDF signing support
      87                 :            : #include "nss.h"
      88                 :            : #include "cert.h"
      89                 :            : #include "hasht.h"
      90                 :            : #include "sechash.h"
      91                 :            : #include "cms.h"
      92                 :            : #include "cmst.h"
      93                 :            : #endif
      94                 :            : 
      95                 :            : using namespace vcl;
      96                 :            : 
      97                 :            : using ::rtl::OUString;
      98                 :            : using ::rtl::OUStringToOString;
      99                 :            : using ::rtl::OString;
     100                 :            : using ::rtl::OStringHash;
     101                 :            : using ::rtl::OUStringHash;
     102                 :            : using ::rtl::OStringBuffer;
     103                 :            : using ::rtl::OUStringBuffer;
     104                 :            : 
     105                 :            : #if (OSL_DEBUG_LEVEL < 3)
     106                 :            : #define COMPRESS_PAGES
     107                 :            : #else
     108                 :            : #define DEBUG_DISABLE_PDFCOMPRESSION // also do not compress streams
     109                 :            : #endif
     110                 :            : 
     111                 :            : #define MAX_SIGNATURE_CONTENT_LENGTH 0x4000
     112                 :            : 
     113                 :            : #ifdef DO_TEST_PDF
     114                 :            : class PDFTestOutputStream : public PDFOutputStream
     115                 :            : {
     116                 :            :     public:
     117                 :            :     virtual ~PDFTestOutputStream();
     118                 :            :     virtual void write( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xStream );
     119                 :            : };
     120                 :            : 
     121                 :            : PDFTestOutputStream::~PDFTestOutputStream()
     122                 :            : {
     123                 :            : }
     124                 :            : 
     125                 :            : void PDFTestOutputStream::write( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xStream )
     126                 :            : {
     127                 :            :     OString aStr( "lalala\ntest\ntest\ntest" );
     128                 :            :     com::sun::star::uno::Sequence< sal_Int8 > aData( aStr.getLength() );
     129                 :            :     memcpy( aData.getArray(), aStr.getStr(), aStr.getLength() );
     130                 :            :     xStream->writeBytes( aData );
     131                 :            : }
     132                 :            : 
     133                 :            : // this test code cannot be used to test PDF/A-1 because it forces
     134                 :            : // control item (widgets) to bypass the structure controlling
     135                 :            : // the embedding of such elements in actual run
     136                 :            : void doTestCode()
     137                 :            : {
     138                 :            :     static const char* pHome = getenv( "HOME"  );
     139                 :            :     rtl::OUString aTestFile( "file://"  );
     140                 :            :     aTestFile += rtl::OUString( pHome, strlen( pHome ), RTL_TEXTENCODING_MS_1252 );
     141                 :            :     aTestFile += rtl::OUString( "/pdf_export_test.pdf"  );
     142                 :            : 
     143                 :            :     PDFWriter::PDFWriterContext aContext;
     144                 :            :     aContext.URL            = aTestFile;
     145                 :            :     aContext.Version        = PDFWriter::PDF_1_4;
     146                 :            :     aContext.Tagged         = true;
     147                 :            :     aContext.InitialPage    = 2;
     148                 :            :     aContext.DocumentInfo.Title = OUString( "PDF export test document"  );
     149                 :            :     aContext.DocumentInfo.Producer = OUString( "VCL"  );
     150                 :            : 
     151                 :            :     aContext.SignPDF        = true;
     152                 :            :     aContext.SignLocation   = OUString( "Burdur" );
     153                 :            :     aContext.SignReason     = OUString( "Some valid reason to sign" );
     154                 :            :     aContext.SignContact    = OUString( "signer@example.com" );
     155                 :            : 
     156                 :            :     com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder > xEnc;
     157                 :            :     PDFWriter aWriter( aContext, xEnc );
     158                 :            :     aWriter.NewPage( 595, 842 );
     159                 :            :     aWriter.BeginStructureElement( PDFWriter::Document );
     160                 :            :     // set duration of 3 sec for first page
     161                 :            :     aWriter.SetAutoAdvanceTime( 3 );
     162                 :            :     aWriter.SetMapMode( MapMode( MAP_100TH_MM ) );
     163                 :            : 
     164                 :            :     aWriter.SetFillColor( Color( COL_LIGHTRED ) );
     165                 :            :     aWriter.SetLineColor( Color( COL_LIGHTGREEN ) );
     166                 :            :     aWriter.DrawRect( Rectangle( Point( 2000, 200 ), Size( 8000, 3000 ) ), 5000, 2000 );
     167                 :            : 
     168                 :            :     aWriter.SetFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ), Size( 0, 500 ) ) );
     169                 :            :     aWriter.SetTextColor( Color( COL_BLACK ) );
     170                 :            :     aWriter.SetLineColor( Color( COL_BLACK ) );
     171                 :            :     aWriter.SetFillColor( Color( COL_LIGHTBLUE ) );
     172                 :            : 
     173                 :            :     Rectangle aRect( Point( 5000, 5000 ), Size( 6000, 3000 ) );
     174                 :            :     aWriter.DrawRect( aRect );
     175                 :            :     aWriter.DrawText( aRect, String( RTL_CONSTASCII_USTRINGPARAM( "Link annot 1" ) ) );
     176                 :            :     sal_Int32 nFirstLink = aWriter.CreateLink( aRect );
     177                 :            :     PDFNote aNote;
     178                 :            :     aNote.Title = String( RTL_CONSTASCII_USTRINGPARAM( "A small test note" ) );
     179                 :            :     aNote.Contents = String( RTL_CONSTASCII_USTRINGPARAM( "There is no business like show business like no business i know. Everything about it is appealing." ) );
     180                 :            :     aWriter.CreateNote( Rectangle( Point( aRect.Right(), aRect.Top() ), Size( 6000, 3000 ) ), aNote );
     181                 :            : 
     182                 :            :     Rectangle aTargetRect( Point( 3000, 23000 ), Size( 12000, 6000 ) );
     183                 :            :     aWriter.SetFillColor( Color( COL_LIGHTGREEN ) );
     184                 :            :     aWriter.DrawRect( aTargetRect );
     185                 :            :     aWriter.DrawText( aTargetRect, String( RTL_CONSTASCII_USTRINGPARAM( "Dest second link" ) ) );
     186                 :            :     sal_Int32 nSecondDest = aWriter.CreateDest( aTargetRect );
     187                 :            : 
     188                 :            :     aWriter.BeginStructureElement( PDFWriter::Section );
     189                 :            :     aWriter.BeginStructureElement( PDFWriter::Heading );
     190                 :            :     aWriter.DrawText( Point(4500, 9000), String( RTL_CONSTASCII_USTRINGPARAM( "A small structure test" ) ) );
     191                 :            :     aWriter.EndStructureElement();
     192                 :            :     aWriter.BeginStructureElement( PDFWriter::Paragraph );
     193                 :            :     aWriter.SetStructureAttribute( PDFWriter::WritingMode, PDFWriter::LrTb );
     194                 :            :     aWriter.SetStructureAttribute( PDFWriter::TextDecorationType, PDFWriter::Underline );
     195                 :            :     aWriter.DrawText( Rectangle( Point( 4500, 10000 ), Size( 12000, 6000 ) ),
     196                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "It was the best of PDF, it was the worst of PDF ... or so. This is a pretty nonsensical text to denote a paragraph. I suggest you stop reading it. Because if you read on you might get bored. So continue on your on risk. Hey, you're still here ? Why do you continue to read this as it is of no use at all ? OK, it's your time, but still... . Woah, i even get bored writing this, so let's end this here and now." ) ),
     197                 :            :                       TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK
     198                 :            :                       );
     199                 :            :     aWriter.SetActualText( String( RTL_CONSTASCII_USTRINGPARAM( "It was the best of PDF, it was the worst of PDF ... or so. This is a pretty nonsensical text to denote a paragraph. I suggest you stop reading it. Because if you read on you might get bored. So continue on your on risk. Hey, you're still here ? Why do you continue to read this as it is of no use at all ? OK, it's your time, but still... . Woah, i even get bored writing this, so let's end this here and now." ) ) );
     200                 :            :     aWriter.SetAlternateText( String( RTL_CONSTASCII_USTRINGPARAM( "This paragraph contains some lengthy nonsense to test structural element emission of PDFWriter." ) ) );
     201                 :            :     aWriter.EndStructureElement();
     202                 :            :     aWriter.BeginStructureElement( PDFWriter::Paragraph );
     203                 :            :     aWriter.SetStructureAttribute( PDFWriter::WritingMode, PDFWriter::LrTb );
     204                 :            :     aWriter.DrawText( Rectangle( Point( 4500, 19000 ), Size( 12000, 1000 ) ),
     205                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "This paragraph is nothing special either but ends on the next page structurewise" ) ),
     206                 :            :                       TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK
     207                 :            :                       );
     208                 :            : 
     209                 :            :     aWriter.NewPage( 595, 842 );
     210                 :            :     // test AddStream interface
     211                 :            :     aWriter.AddStream( String( RTL_CONSTASCII_USTRINGPARAM( "text/plain" ) ), new PDFTestOutputStream(), true );
     212                 :            :     // set transitional mode
     213                 :            :     aWriter.SetPageTransition( PDFWriter::WipeRightToLeft, 1500 );
     214                 :            :     aWriter.SetMapMode( MapMode( MAP_100TH_MM ) );
     215                 :            :     aWriter.SetTextColor( Color( COL_BLACK ) );
     216                 :            :     aWriter.SetFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ), Size( 0, 500 ) ) );
     217                 :            :     aWriter.DrawText( Rectangle( Point( 4500, 1500 ), Size( 12000, 3000 ) ),
     218                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "Here's where all things come to an end ... well at least the paragaph from the last page." ) ),
     219                 :            :                       TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK
     220                 :            :                       );
     221                 :            :     aWriter.EndStructureElement();
     222                 :            : 
     223                 :            :     aWriter.SetFillColor( Color( COL_LIGHTBLUE ) );
     224                 :            :     // disable structure
     225                 :            :     aWriter.BeginStructureElement( PDFWriter::NonStructElement );
     226                 :            :     aWriter.DrawRect( aRect );
     227                 :            :     aWriter.BeginStructureElement( PDFWriter::Paragraph );
     228                 :            :     aWriter.DrawText( aRect, String( RTL_CONSTASCII_USTRINGPARAM( "Link annot 2" ) ) );
     229                 :            :     sal_Int32 nSecondLink = aWriter.CreateLink( aRect );
     230                 :            : 
     231                 :            :     aWriter.SetFillColor( Color( COL_LIGHTGREEN ) );
     232                 :            :     aWriter.BeginStructureElement( PDFWriter::ListItem );
     233                 :            :     aWriter.DrawRect( aTargetRect );
     234                 :            :     aWriter.DrawText( aTargetRect, String( RTL_CONSTASCII_USTRINGPARAM( "Dest first link" ) ) );
     235                 :            :     sal_Int32 nFirstDest = aWriter.CreateDest( aTargetRect );
     236                 :            :     // enable structure
     237                 :            :     aWriter.EndStructureElement();
     238                 :            : 
     239                 :            :     // add something to the long paragraph as an afterthought
     240                 :            :     /* PDFWriter::aWriter.GetCurrentStructureElement removed as an unusedcode.easy item:
     241                 :            :     http://cgit.freedesktop.org/libreoffice/core/commit/?id=09279fe3dad24ab58121e4f0a9564d252b64d81a
     242                 :            : 
     243                 :            :     sal_Int32 nSaveStruct = aWriter.GetCurrentStructureElement();
     244                 :            :     aWriter.SetCurrentStructureElement( nLongPara );
     245                 :            :     aWriter.DrawText( Rectangle( Point( 4500,4500 ),  Size( 12000, 1000 ) ),
     246                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "Add something to the longish paragraph above." ) ),
     247                 :            :                       TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
     248                 :            :     aWriter.SetCurrentStructureElement( nSaveStruct );
     249                 :            :     */
     250                 :            : 
     251                 :            :     aWriter.EndStructureElement();
     252                 :            :     aWriter.EndStructureElement();
     253                 :            :     aWriter.BeginStructureElement( PDFWriter::Figure );
     254                 :            :     aWriter.BeginStructureElement( PDFWriter::Caption );
     255                 :            :     aWriter.DrawText( Point( 4500, 9000 ), String( RTL_CONSTASCII_USTRINGPARAM( "Some drawing stuff inside the structure" ) ) );
     256                 :            :     aWriter.EndStructureElement();
     257                 :            : 
     258                 :            :     // test clipping
     259                 :            :     basegfx::B2DPolyPolygon aClip;
     260                 :            :     basegfx::B2DPolygon aClipPoly;
     261                 :            :     aClipPoly.append( basegfx::B2DPoint( 8250, 9600 ) );
     262                 :            :     aClipPoly.append( basegfx::B2DPoint( 16500, 11100 ) );
     263                 :            :     aClipPoly.append( basegfx::B2DPoint( 8250, 12600 ) );
     264                 :            :     aClipPoly.append( basegfx::B2DPoint( 4500, 11100 ) );
     265                 :            :     aClipPoly.setClosed( true );
     266                 :            :     //aClipPoly.flip();
     267                 :            :     aClip.append( aClipPoly );
     268                 :            : 
     269                 :            :     aWriter.Push( PUSH_CLIPREGION | PUSH_FILLCOLOR );
     270                 :            :     aWriter.SetClipRegion( aClip );
     271                 :            :     aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) );
     272                 :            :     aWriter.MoveClipRegion( 1000, 500 );
     273                 :            :     aWriter.SetFillColor( Color( COL_RED ) );
     274                 :            :     aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) );
     275                 :            :     aWriter.Pop();
     276                 :            :     // test transparency
     277                 :            :     // draw background
     278                 :            :     Rectangle aTranspRect( Point( 7500, 13500 ), Size( 9000, 6000 ) );
     279                 :            :     aWriter.SetFillColor( Color( COL_LIGHTRED ) );
     280                 :            :     aWriter.DrawRect( aTranspRect );
     281                 :            :     aWriter.BeginTransparencyGroup();
     282                 :            : 
     283                 :            :     aWriter.SetFillColor( Color( COL_LIGHTGREEN ) );
     284                 :            :     aWriter.DrawEllipse( aTranspRect );
     285                 :            :     aWriter.SetTextColor( Color( COL_LIGHTBLUE ) );
     286                 :            :     aWriter.DrawText( aTranspRect,
     287                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "Some transparent text" ) ),
     288                 :            :                       TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
     289                 :            : 
     290                 :            :     aWriter.EndTransparencyGroup( aTranspRect, 50 );
     291                 :            : 
     292                 :            :     // prepare an alpha mask
     293                 :            :     Bitmap aTransMask( Size( 256, 256 ), 8, &Bitmap::GetGreyPalette( 256 ) );
     294                 :            :     BitmapWriteAccess* pAcc = aTransMask.AcquireWriteAccess();
     295                 :            :     for( int nX = 0; nX < 256; nX++ )
     296                 :            :         for( int nY = 0; nY < 256; nY++ )
     297                 :            :             pAcc->SetPixel( nX, nY, BitmapColor( (sal_uInt8)((nX+nY)/2) ) );
     298                 :            :     aTransMask.ReleaseAccess( pAcc );
     299                 :            :     aTransMask.SetPrefMapMode( MAP_MM );
     300                 :            :     aTransMask.SetPrefSize( Size( 10, 10 ) );
     301                 :            : 
     302                 :            :     aWriter.DrawBitmap( Point( 600, 13500 ), Size( 3000, 3000 ), aTransMask );
     303                 :            : 
     304                 :            :     aTranspRect = Rectangle( Point( 4200, 13500 ), Size( 3000, 3000 ) );
     305                 :            :     aWriter.SetFillColor( Color( COL_LIGHTRED ) );
     306                 :            :     aWriter.DrawRect( aTranspRect );
     307                 :            :     aWriter.SetFillColor( Color( COL_LIGHTGREEN ) );
     308                 :            :     aWriter.DrawEllipse( aTranspRect );
     309                 :            :     aWriter.SetTextColor( Color( COL_LIGHTBLUE ) );
     310                 :            :     aWriter.DrawText( aTranspRect,
     311                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "Some transparent text" ) ),
     312                 :            :                       TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
     313                 :            :     aTranspRect = Rectangle( Point( 1500, 16500 ), Size( 4800, 3000 ) );
     314                 :            :     aWriter.SetFillColor( Color( COL_LIGHTRED ) );
     315                 :            :     aWriter.DrawRect( aTranspRect );
     316                 :            : 
     317                 :            :     /*
     318                 :            :     EndTransparencyGroup( const Rectangle& rBoundRect, const Bitmap& rAlphaMask ) is removed as an unusedcode.easy item:
     319                 :            :     http://cgit.freedesktop.org/libreoffice/core/commit/?id=581e7d7057afa87036d84e42c0e0a8a7368e20c7
     320                 :            : 
     321                 :            :     aWriter.BeginTransparencyGroup();
     322                 :            :     aWriter.SetFillColor( Color( COL_LIGHTGREEN ) );
     323                 :            :     aWriter.DrawEllipse( aTranspRect );
     324                 :            :     aWriter.SetTextColor( Color( COL_LIGHTBLUE ) );
     325                 :            :     aWriter.DrawText( aTranspRect,
     326                 :            :                       String( RTL_CONSTASCII_USTRINGPARAM( "Some transparent text" ) ),
     327                 :            :                       TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
     328                 :            :     aWriter.EndTransparencyGroup( aTranspRect, aTransMask );
     329                 :            :     */
     330                 :            : 
     331                 :            :     Bitmap aImageBmp( Size( 256, 256 ), 24 );
     332                 :            :     pAcc = aImageBmp.AcquireWriteAccess();
     333                 :            :     pAcc->SetFillColor( Color( 0xff, 0, 0xff ) );
     334                 :            :     pAcc->FillRect( Rectangle( Point( 0, 0 ), Size( 256, 256 ) ) );
     335                 :            :     aImageBmp.ReleaseAccess( pAcc );
     336                 :            :     BitmapEx aBmpEx( aImageBmp, AlphaMask( aTransMask ) );
     337                 :            :     aWriter.DrawBitmapEx( Point( 1500, 19500 ), Size( 4800, 3000 ), aBmpEx );
     338                 :            : 
     339                 :            : 
     340                 :            :     aWriter.EndStructureElement();
     341                 :            :     aWriter.EndStructureElement();
     342                 :            : 
     343                 :            :     LineInfo aLI( LINE_DASH, 3 );
     344                 :            :     aLI.SetDashCount( 2 );
     345                 :            :     aLI.SetDashLen( 50 );
     346                 :            :     aLI.SetDotCount( 2 );
     347                 :            :     aLI.SetDotLen( 25 );
     348                 :            :     aLI.SetDistance( 15 );
     349                 :            :     Point aLIPoints[] = { Point( 4000, 10000 ),
     350                 :            :                           Point( 8000, 12000 ),
     351                 :            :                           Point( 3000, 19000 ) };
     352                 :            :     Polygon aLIPoly( 3, aLIPoints );
     353                 :            :     aWriter.SetLineColor( Color( COL_BLUE ) );
     354                 :            :     aWriter.SetFillColor();
     355                 :            :     aWriter.DrawPolyLine( aLIPoly, aLI );
     356                 :            : 
     357                 :            :     aLI.SetDashCount( 4 );
     358                 :            :     aLIPoly.Move( 1000, 1000 );
     359                 :            :     aWriter.DrawPolyLine( aLIPoly, aLI );
     360                 :            : 
     361                 :            :     aWriter.NewPage( 595, 842 );
     362                 :            :     aWriter.SetMapMode( MapMode( MAP_100TH_MM ) );
     363                 :            :     Wallpaper aWall( aTransMask );
     364                 :            :     aWall.SetStyle( WALLPAPER_TILE );
     365                 :            :     aWriter.DrawWallpaper( Rectangle( Point( 4400, 4200 ), Size( 10200, 6300 ) ), aWall );
     366                 :            : 
     367                 :            :     /*
     368                 :            :     BeginPattern/EndPattern is removed as an unusedcode.easy item:
     369                 :            :     http://cgit.freedesktop.org/libreoffice/core/commit/?id=581e7d7057afa87036d84e42c0e0a8a7368e20c7
     370                 :            : 
     371                 :            :     aWriter.Push( PUSH_ALL );
     372                 :            :     aWriter.BeginPattern(Rectangle(Point(0,0),Size(2000,1000)));
     373                 :            :     aWriter.SetFillColor( Color( COL_RED ) );
     374                 :            :     aWriter.SetLineColor( Color( COL_LIGHTBLUE ) );
     375                 :            :     Point aFillPoints[] = { Point( 1000, 0 ),
     376                 :            :                             Point( 0, 1000 ),
     377                 :            :                             Point( 2000, 1000 ) };
     378                 :            :     aWriter.DrawPolygon( Polygon( 3, aFillPoints ) );
     379                 :            :     aWriter.DrawBitmap( Point( 200, 200 ), Size( 1600, 600 ), aTransMask );
     380                 :            :     aWriter.DrawText( Rectangle( Point( 200, 200 ), Size( 1600, 600 ) ), String( RTL_CONSTASCII_USTRINGPARAM( "Pattern" ) ) );
     381                 :            :     sal_Int32 nPattern = aWriter.EndPattern( SvtGraphicFill::Transform() );
     382                 :            :     aWriter.Pop();
     383                 :            :     Rectangle aPolyRect( Point( 3800, 11200 ), Size( 10200, 6300 ) );
     384                 :            :     aWriter.DrawPolyPolygon( PolyPolygon( Polygon( aPolyRect ) ), nPattern, true );
     385                 :            :     aWriter.SetFillColor();
     386                 :            :     aWriter.SetLineColor( Color( COL_LIGHTBLUE ) );
     387                 :            :     aWriter.DrawRect( aPolyRect );
     388                 :            :     */
     389                 :            : 
     390                 :            :     aWriter.NewPage( 595, 842 );
     391                 :            :     aWriter.SetMapMode( MapMode( MAP_100TH_MM ) );
     392                 :            :     aWriter.SetFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ), Size( 0, 500 ) ) );
     393                 :            :     aWriter.SetTextColor( Color( COL_BLACK ) );
     394                 :            :     aRect = Rectangle( Point( 4500, 6000 ), Size( 6000, 1500 ) );
     395                 :            :     aWriter.DrawRect( aRect );
     396                 :            :     aWriter.DrawText( aRect, String( RTL_CONSTASCII_USTRINGPARAM( "www.heise.de" ) ) );
     397                 :            :     sal_Int32 nURILink = aWriter.CreateLink( aRect );
     398                 :            :     aWriter.SetLinkURL( nURILink, OUString( "http://www.heise.de"  ) );
     399                 :            : 
     400                 :            :     aWriter.SetLinkDest( nFirstLink, nFirstDest );
     401                 :            :     aWriter.SetLinkDest( nSecondLink, nSecondDest );
     402                 :            : 
     403                 :            :     // include a button
     404                 :            :     PDFWriter::PushButtonWidget aBtn;
     405                 :            :     aBtn.Name = OUString( "testButton"  );
     406                 :            :     aBtn.Description = OUString( "A test button"  );
     407                 :            :     aBtn.Text = OUString( "hit me"  );
     408                 :            :     aBtn.Location = Rectangle( Point( 4500, 9000 ), Size( 4500, 3000 ) );
     409                 :            :     aBtn.Border = aBtn.Background = true;
     410                 :            :     aWriter.CreateControl( aBtn );
     411                 :            : 
     412                 :            :     // include a uri button
     413                 :            :     PDFWriter::PushButtonWidget aUriBtn;
     414                 :            :     aUriBtn.Name = OUString( "wwwButton"  );
     415                 :            :     aUriBtn.Description = OUString( "A URI button"  );
     416                 :            :     aUriBtn.Text = OUString( "to www"  );
     417                 :            :     aUriBtn.Location = Rectangle( Point( 9500, 9000 ), Size( 4500, 3000 ) );
     418                 :            :     aUriBtn.Border = aUriBtn.Background = true;
     419                 :            :     aUriBtn.URL = OUString( "http://www.heise.de"  );
     420                 :            :     aWriter.CreateControl( aUriBtn );
     421                 :            : 
     422                 :            :     // include a dest button
     423                 :            :     PDFWriter::PushButtonWidget aDstBtn;
     424                 :            :     aDstBtn.Name = OUString( "destButton"  );
     425                 :            :     aDstBtn.Description = OUString( "A Dest button"  );
     426                 :            :     aDstBtn.Text = OUString( "to paragraph"  );
     427                 :            :     aDstBtn.Location = Rectangle( Point( 14500, 9000 ), Size( 4500, 3000 ) );
     428                 :            :     aDstBtn.Border = aDstBtn.Background = true;
     429                 :            :     aDstBtn.Dest = nFirstDest;
     430                 :            :     aWriter.CreateControl( aDstBtn );
     431                 :            : 
     432                 :            :     PDFWriter::CheckBoxWidget aCBox;
     433                 :            :     aCBox.Name = OUString( "textCheckBox"  );
     434                 :            :     aCBox.Description = OUString( "A test check box"  );
     435                 :            :     aCBox.Text = OUString( "check me"  );
     436                 :            :     aCBox.Location = Rectangle( Point( 4500, 13500 ), Size( 3000, 750 ) );
     437                 :            :     aCBox.Checked = true;
     438                 :            :     aCBox.Border = aCBox.Background = false;
     439                 :            :     aWriter.CreateControl( aCBox );
     440                 :            : 
     441                 :            :     PDFWriter::CheckBoxWidget aCBox2;
     442                 :            :     aCBox2.Name = OUString( "textCheckBox2"  );
     443                 :            :     aCBox2.Description = OUString( "Another test check box"  );
     444                 :            :     aCBox2.Text = OUString( "check me right"  );
     445                 :            :     aCBox2.Location = Rectangle( Point( 4500, 14250 ), Size( 3000, 750 ) );
     446                 :            :     aCBox2.Checked = true;
     447                 :            :     aCBox2.Border = aCBox2.Background = false;
     448                 :            :     aCBox2.ButtonIsLeft = false;
     449                 :            :     aWriter.CreateControl( aCBox2 );
     450                 :            : 
     451                 :            :     PDFWriter::RadioButtonWidget aRB1;
     452                 :            :     aRB1.Name = OUString( "rb1_1"  );
     453                 :            :     aRB1.Description = OUString( "radio 1 button 1"  );
     454                 :            :     aRB1.Text = OUString( "Despair"  );
     455                 :            :     aRB1.Location = Rectangle( Point( 4500, 15000 ), Size( 6000, 1000 ) );
     456                 :            :     aRB1.Selected = true;
     457                 :            :     aRB1.RadioGroup = 1;
     458                 :            :     aRB1.Border = aRB1.Background = true;
     459                 :            :     aRB1.ButtonIsLeft = false;
     460                 :            :     aRB1.BorderColor = Color( COL_LIGHTGREEN );
     461                 :            :     aRB1.BackgroundColor = Color( COL_LIGHTBLUE );
     462                 :            :     aRB1.TextColor = Color( COL_LIGHTRED );
     463                 :            :     aRB1.TextFont = Font( String( RTL_CONSTASCII_USTRINGPARAM( "Courier" ) ), Size( 0, 800 ) );
     464                 :            :     aWriter.CreateControl( aRB1 );
     465                 :            : 
     466                 :            :     PDFWriter::RadioButtonWidget aRB2;
     467                 :            :     aRB2.Name = OUString( "rb2_1"  );
     468                 :            :     aRB2.Description = OUString( "radio 2 button 1"  );
     469                 :            :     aRB2.Text = OUString( "Joy"  );
     470                 :            :     aRB2.Location = Rectangle( Point( 10500, 15000 ), Size( 3000, 1000 ) );
     471                 :            :     aRB2.Selected = true;
     472                 :            :     aRB2.RadioGroup = 2;
     473                 :            :     aWriter.CreateControl( aRB2 );
     474                 :            : 
     475                 :            :     PDFWriter::RadioButtonWidget aRB3;
     476                 :            :     aRB3.Name = OUString( "rb1_2"  );
     477                 :            :     aRB3.Description = OUString( "radio 1 button 2"  );
     478                 :            :     aRB3.Text = OUString( "Desperation"  );
     479                 :            :     aRB3.Location = Rectangle( Point( 4500, 16000 ), Size( 3000, 1000 ) );
     480                 :            :     aRB3.Selected = true;
     481                 :            :     aRB3.RadioGroup = 1;
     482                 :            :     aWriter.CreateControl( aRB3 );
     483                 :            : 
     484                 :            :     PDFWriter::EditWidget aEditBox;
     485                 :            :     aEditBox.Name = OUString( "testEdit"  );
     486                 :            :     aEditBox.Description = OUString( "A test edit field"  );
     487                 :            :     aEditBox.Text = OUString( "A little test text"  );
     488                 :            :     aEditBox.TextStyle = TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER;
     489                 :            :     aEditBox.Location = Rectangle( Point( 10000, 18000 ), Size( 5000, 1500 ) );
     490                 :            :     aEditBox.MaxLen = 100;
     491                 :            :     aEditBox.Border = aEditBox.Background = true;
     492                 :            :     aEditBox.BorderColor = Color( COL_BLACK );
     493                 :            :     aWriter.CreateControl( aEditBox );
     494                 :            : 
     495                 :            :     // normal list box
     496                 :            :     PDFWriter::ListBoxWidget aLstBox;
     497                 :            :     aLstBox.Name = OUString( "testListBox"  );
     498                 :            :     aLstBox.Text = OUString( "One"  );
     499                 :            :     aLstBox.Description = OUString( "select me"  );
     500                 :            :     aLstBox.Location = Rectangle( Point( 4500, 18000 ), Size( 3000, 1500 ) );
     501                 :            :     aLstBox.Sort = true;
     502                 :            :     aLstBox.MultiSelect = true;
     503                 :            :     aLstBox.Border = aLstBox.Background = true;
     504                 :            :     aLstBox.BorderColor = Color( COL_BLACK );
     505                 :            :     aLstBox.Entries.push_back( OUString( "One"  ) );
     506                 :            :     aLstBox.Entries.push_back( OUString( "Two"  ) );
     507                 :            :     aLstBox.Entries.push_back( OUString( "Three"  ) );
     508                 :            :     aLstBox.Entries.push_back( OUString( "Four"  ) );
     509                 :            :     aLstBox.SelectedEntries.push_back( 1 );
     510                 :            :     aLstBox.SelectedEntries.push_back( 2 );
     511                 :            :     aWriter.CreateControl( aLstBox );
     512                 :            : 
     513                 :            :     // dropdown list box
     514                 :            :     aLstBox.Name = OUString( "testDropDownListBox"  );
     515                 :            :     aLstBox.DropDown = true;
     516                 :            :     aLstBox.Location = Rectangle( Point( 4500, 19500 ), Size( 3000, 500 ) );
     517                 :            :     aWriter.CreateControl( aLstBox );
     518                 :            : 
     519                 :            :     // combo box
     520                 :            :     PDFWriter::ComboBoxWidget aComboBox;
     521                 :            :     aComboBox.Name = OUString( "testComboBox"  );
     522                 :            :     aComboBox.Text = OUString( "test a combobox"  );
     523                 :            :     aComboBox.Entries.push_back( OUString( "Larry"  ) );
     524                 :            :     aComboBox.Entries.push_back( OUString( "Curly"  ) );
     525                 :            :     aComboBox.Entries.push_back( OUString( "Moe"  ) );
     526                 :            :     aComboBox.Location = Rectangle( Point( 4500, 20000 ), Size( 3000, 500 ) );
     527                 :            :     aWriter.CreateControl( aComboBox );
     528                 :            : 
     529                 :            :     // test outlines
     530                 :            :     sal_Int32 nPage1OL = aWriter.CreateOutlineItem();
     531                 :            :     aWriter.SetOutlineItemText( nPage1OL, OUString( "Page 1"  ) );
     532                 :            :     aWriter.SetOutlineItemDest( nPage1OL, nSecondDest );
     533                 :            :     aWriter.CreateOutlineItem( nPage1OL, OUString( "Dest 2"  ), nSecondDest );
     534                 :            :     aWriter.CreateOutlineItem( nPage1OL, OUString( "Dest 2 revisited"  ), nSecondDest );
     535                 :            :     aWriter.CreateOutlineItem( nPage1OL, OUString( "Dest 2 again"  ), nSecondDest );
     536                 :            :     sal_Int32 nPage2OL = aWriter.CreateOutlineItem();
     537                 :            :     aWriter.SetOutlineItemText( nPage2OL, OUString( "Page 2"  ) );
     538                 :            :     aWriter.CreateOutlineItem( nPage2OL, OUString( "Dest 1"  ), nFirstDest );
     539                 :            : 
     540                 :            :     aWriter.EndStructureElement(); // close document
     541                 :            : 
     542                 :            :     aWriter.Emit();
     543                 :            : }
     544                 :            : #endif
     545                 :            : 
     546                 :            : static const sal_Int32 nLog10Divisor = 1;
     547                 :            : static const double fDivisor = 10.0;
     548                 :            : 
     549                 :            : static inline double pixelToPoint( sal_Int32 px ) { return double(px)/fDivisor; }
     550                 :          0 : static inline double pixelToPoint( double px ) { return px/fDivisor; }
     551                 :          0 : static inline sal_Int32 pointToPixel( double pt ) { return sal_Int32(pt*fDivisor); }
     552                 :            : 
     553                 :            : const sal_uInt8 PDFWriterImpl::s_nPadString[32] =
     554                 :            : {
     555                 :            :     0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
     556                 :            :     0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
     557                 :            : };
     558                 :            : 
     559                 :          0 : static void appendHex( sal_Int8 nInt, OStringBuffer& rBuffer )
     560                 :            : {
     561                 :            :     static const sal_Char pHexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
     562                 :            :                                            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
     563                 :          0 :     rBuffer.append( pHexDigits[ (nInt >> 4) & 15 ] );
     564                 :          0 :     rBuffer.append( pHexDigits[ nInt & 15 ] );
     565                 :          0 : }
     566                 :            : 
     567                 :          0 : static void appendName( const OUString& rStr, OStringBuffer& rBuffer )
     568                 :            : {
     569                 :            : // FIXME i59651 add a check for max length of 127 chars? Per PDF spec 1.4, appendix C.1
     570                 :            : // I guess than when reading the #xx sequence it will count for a single character.
     571         [ #  # ]:          0 :     OString aStr( OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 ) );
     572                 :          0 :     const sal_Char* pStr = aStr.getStr();
     573                 :          0 :     int nLen = aStr.getLength();
     574         [ #  # ]:          0 :     for( int i = 0; i < nLen; i++ )
     575                 :            :     {
     576                 :            :         /*  #i16920# PDF recommendation: output UTF8, any byte
     577                 :            :          *  outside the interval [33(=ASCII'!');126(=ASCII'~')]
     578                 :            :          *  should be escaped hexadecimal
     579                 :            :          *  for the sake of ghostscript which also reads PDF
     580                 :            :          *  but has a narrower acceptance rate we only pass
     581                 :            :          *  alphanumerics and '-' literally.
     582                 :            :          */
     583 [ #  # ][ #  # ]:          0 :         if( (pStr[i] >= 'A' && pStr[i] <= 'Z' ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     584                 :          0 :             (pStr[i] >= 'a' && pStr[i] <= 'z' ) ||
     585                 :          0 :             (pStr[i] >= '0' && pStr[i] <= '9' ) ||
     586                 :          0 :             pStr[i] == '-' )
     587                 :            :         {
     588         [ #  # ]:          0 :             rBuffer.append( pStr[i] );
     589                 :            :         }
     590                 :            :         else
     591                 :            :         {
     592         [ #  # ]:          0 :             rBuffer.append( '#' );
     593         [ #  # ]:          0 :             appendHex( (sal_Int8)pStr[i], rBuffer );
     594                 :            :         }
     595                 :          0 :     }
     596                 :          0 : }
     597                 :            : 
     598                 :          0 : static void appendName( const sal_Char* pStr, OStringBuffer& rBuffer )
     599                 :            : {
     600                 :            : //FIXME i59651 see above
     601 [ #  # ][ #  # ]:          0 :     while( pStr && *pStr )
                 [ #  # ]
     602                 :            :     {
     603 [ #  # ][ #  # ]:          0 :         if( (*pStr >= 'A' && *pStr <= 'Z' ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     604                 :            :             (*pStr >= 'a' && *pStr <= 'z' ) ||
     605                 :            :             (*pStr >= '0' && *pStr <= '9' ) ||
     606                 :            :             *pStr == '-' )
     607                 :            :         {
     608                 :          0 :             rBuffer.append( *pStr );
     609                 :            :         }
     610                 :            :         else
     611                 :            :         {
     612                 :          0 :             rBuffer.append( '#' );
     613                 :          0 :             appendHex( (sal_Int8)*pStr, rBuffer );
     614                 :            :         }
     615                 :          0 :         pStr++;
     616                 :            :     }
     617                 :          0 : }
     618                 :            : 
     619                 :            : //used only to emit encoded passwords
     620                 :          0 : static void appendLiteralString( const sal_Char* pStr, sal_Int32 nLength, OStringBuffer& rBuffer )
     621                 :            : {
     622         [ #  # ]:          0 :     while( nLength )
     623                 :            :     {
     624   [ #  #  #  #  :          0 :         switch( *pStr )
                #  #  # ]
     625                 :            :         {
     626                 :            :         case '\n' :
     627                 :          0 :             rBuffer.append( "\\n" );
     628                 :          0 :             break;
     629                 :            :         case '\r' :
     630                 :          0 :             rBuffer.append( "\\r" );
     631                 :          0 :             break;
     632                 :            :         case '\t' :
     633                 :          0 :             rBuffer.append( "\\t" );
     634                 :          0 :             break;
     635                 :            :         case '\b' :
     636                 :          0 :             rBuffer.append( "\\b" );
     637                 :          0 :             break;
     638                 :            :         case '\f' :
     639                 :          0 :             rBuffer.append( "\\f" );
     640                 :          0 :             break;
     641                 :            :         case '(' :
     642                 :            :         case ')' :
     643                 :            :         case '\\' :
     644                 :          0 :             rBuffer.append( "\\" );
     645                 :          0 :             rBuffer.append( (sal_Char) *pStr );
     646                 :          0 :             break;
     647                 :            :         default:
     648                 :          0 :             rBuffer.append( (sal_Char) *pStr );
     649                 :          0 :             break;
     650                 :            :         }
     651                 :          0 :         pStr++;
     652                 :          0 :         nLength--;
     653                 :            :     }
     654                 :          0 : }
     655                 :            : 
     656                 :            : /**--->i56629
     657                 :            :  * Convert a string before using it.
     658                 :            :  *
     659                 :            :  * This string conversion function is needed because the destination name
     660                 :            :  * in a PDF file seen through an Internet browser should be
     661                 :            :  * specially crafted, in order to be used directly by the browser.
     662                 :            :  * In this way the fragment part of a hyperlink to a PDF file (e.g. something
     663                 :            :  * as 'test1/test2/a-file.pdf#thefragment) will be (hopefully) interpreted by the
     664                 :            :  * PDF reader (currently only Adobe Reader plug-in seems to be working that way) called
     665                 :            :  * from inside the Internet browser as: 'open the file test1/test2/a-file.pdf
     666                 :            :  * and go to named destination thefragment using default zoom'.
     667                 :            :  * The conversion is needed because in case of a fragment in the form: Slide%201
     668                 :            :  * (meaning Slide 1) as it is converted obeying the Inet rules, it will become Slide25201
     669                 :            :  * using this conversion, in both the generated named destinations, fragment and GoToR
     670                 :            :  * destination.
     671                 :            :  *
     672                 :            :  * The names for destinations are name objects and so they don't need to be encrypted
     673                 :            :  * even though they expose the content of PDF file (e.g. guessing the PDF content from the
     674                 :            :  * destination name).
     675                 :            :  *
     676                 :            :  * Fhurter limitation: it is advisable to use standard ASCII characters for
     677                 :            :  * OOo bookmarks.
     678                 :            : */
     679                 :          0 : static void appendDestinationName( const rtl::OUString& rString, OStringBuffer& rBuffer )
     680                 :            : {
     681                 :          0 :     const sal_Unicode* pStr = rString.getStr();
     682                 :          0 :     sal_Int32 nLen = rString.getLength();
     683         [ #  # ]:          0 :     for( int i = 0; i < nLen; i++ )
     684                 :            :     {
     685                 :          0 :         sal_Unicode aChar = pStr[i];
     686 [ #  # ][ #  # ]:          0 :         if( (aChar >= '0' && aChar <= '9' ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     687                 :            :             (aChar >= 'a' && aChar <= 'z' ) ||
     688                 :            :             (aChar >= 'A' && aChar <= 'Z' ) ||
     689                 :            :             aChar == '-' )
     690                 :            :         {
     691                 :          0 :             rBuffer.append((sal_Char)aChar);
     692                 :            :         }
     693                 :            :         else
     694                 :            :         {
     695                 :          0 :             sal_Int8 aValueHigh = sal_Int8(aChar >> 8);
     696         [ #  # ]:          0 :             if(aValueHigh > 0)
     697                 :          0 :                 appendHex( aValueHigh, rBuffer );
     698                 :          0 :             appendHex( (sal_Int8)(aChar & 255 ), rBuffer );
     699                 :            :         }
     700                 :            :     }
     701                 :          0 : }
     702                 :            : //<--- i56629
     703                 :            : 
     704                 :          0 : static void appendUnicodeTextString( const rtl::OUString& rString, OStringBuffer& rBuffer )
     705                 :            : {
     706                 :          0 :     rBuffer.append( "FEFF" );
     707                 :          0 :     const sal_Unicode* pStr = rString.getStr();
     708                 :          0 :     sal_Int32 nLen = rString.getLength();
     709         [ #  # ]:          0 :     for( int i = 0; i < nLen; i++ )
     710                 :            :     {
     711                 :          0 :         sal_Unicode aChar = pStr[i];
     712                 :          0 :         appendHex( (sal_Int8)(aChar >> 8), rBuffer );
     713                 :          0 :         appendHex( (sal_Int8)(aChar & 255 ), rBuffer );
     714                 :            :     }
     715                 :          0 : }
     716                 :            : 
     717                 :          0 : void PDFWriterImpl::createWidgetFieldName( sal_Int32 i_nWidgetIndex, const PDFWriter::AnyWidget& i_rControl )
     718                 :            : {
     719                 :            :     /* #i80258# previously we use appendName here
     720                 :            :        however we need a slightly different coding scheme than the normal
     721                 :            :        name encoding for field names
     722                 :            :     */
     723         [ #  # ]:          0 :     const OUString& rName = (m_aContext.Version > PDFWriter::PDF_1_2) ? i_rControl.Name : i_rControl.Text;
     724         [ #  # ]:          0 :     OString aStr( OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ) );
     725                 :          0 :     const sal_Char* pStr = aStr.getStr();
     726                 :          0 :     int nLen = aStr.getLength();
     727                 :            : 
     728                 :          0 :     OStringBuffer aBuffer( rName.getLength()+64 );
     729         [ #  # ]:          0 :     for( int i = 0; i < nLen; i++ )
     730                 :            :     {
     731                 :            :         /*  #i16920# PDF recommendation: output UTF8, any byte
     732                 :            :          *  outside the interval [32(=ASCII' ');126(=ASCII'~')]
     733                 :            :          *  should be escaped hexadecimal
     734                 :            :          */
     735 [ #  # ][ #  # ]:          0 :         if( (pStr[i] >= 32 && pStr[i] <= 126 ) )
     736         [ #  # ]:          0 :             aBuffer.append( pStr[i] );
     737                 :            :         else
     738                 :            :         {
     739         [ #  # ]:          0 :             aBuffer.append( '#' );
     740         [ #  # ]:          0 :             appendHex( (sal_Int8)pStr[i], aBuffer );
     741                 :            :         }
     742                 :            :     }
     743                 :            : 
     744                 :          0 :     OString aFullName( aBuffer.makeStringAndClear() );
     745                 :            : 
     746                 :            :     /* #i82785# create hierarchical fields down to the for each dot in i_rName */
     747                 :          0 :     sal_Int32 nTokenIndex = 0, nLastTokenIndex = 0;
     748                 :          0 :     OString aPartialName;
     749                 :          0 :     OString aDomain;
     750         [ #  # ]:          0 :     do
     751                 :            :     {
     752                 :          0 :         nLastTokenIndex = nTokenIndex;
     753                 :          0 :         aPartialName = aFullName.getToken( 0, '.', nTokenIndex );
     754         [ #  # ]:          0 :         if( nTokenIndex != -1 )
     755                 :            :         {
     756                 :            :             // find or create a hierarchical field
     757                 :            :             // first find the fully qualified name up to this field
     758                 :          0 :             aDomain = aFullName.copy( 0, nTokenIndex-1 );
     759         [ #  # ]:          0 :             boost::unordered_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain );
     760 [ #  # ][ #  # ]:          0 :             if( it == m_aFieldNameMap.end() )
     761                 :            :             {
     762                 :            :                  // create new hierarchy field
     763                 :          0 :                 sal_Int32 nNewWidget = m_aWidgets.size();
     764 [ #  # ][ #  # ]:          0 :                 m_aWidgets.push_back( PDFWidget() );
                 [ #  # ]
     765         [ #  # ]:          0 :                 m_aWidgets[nNewWidget].m_nObject = createObject();
     766                 :          0 :                 m_aWidgets[nNewWidget].m_eType = PDFWriter::Hierarchy;
     767                 :          0 :                 m_aWidgets[nNewWidget].m_aName = aPartialName;
     768                 :          0 :                 m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject;
     769         [ #  # ]:          0 :                 m_aFieldNameMap[aDomain] = nNewWidget;
     770                 :          0 :                 m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject;
     771         [ #  # ]:          0 :                 if( nLastTokenIndex > 0 )
     772                 :            :                 {
     773                 :            :                     // this field is not a root field and
     774                 :            :                     // needs to be inserted to its parent
     775                 :          0 :                     OString aParentDomain( aDomain.copy( 0, nLastTokenIndex-1 ) );
     776         [ #  # ]:          0 :                     it = m_aFieldNameMap.find( aParentDomain );
     777                 :            :                     OSL_ENSURE( it != m_aFieldNameMap.end(), "field name not found" );
     778 [ #  # ][ #  # ]:          0 :                     if( it != m_aFieldNameMap.end()  )
     779                 :            :                     {
     780                 :            :                         OSL_ENSURE( it->second < sal_Int32(m_aWidgets.size()), "invalid field number entry" );
     781 [ #  # ][ #  # ]:          0 :                         if( it->second < sal_Int32(m_aWidgets.size()) )
     782                 :            :                         {
     783         [ #  # ]:          0 :                             PDFWidget& rParentField( m_aWidgets[it->second] );
     784         [ #  # ]:          0 :                             rParentField.m_aKids.push_back( m_aWidgets[nNewWidget].m_nObject );
     785         [ #  # ]:          0 :                             rParentField.m_aKidsIndex.push_back( nNewWidget );
     786                 :          0 :                             m_aWidgets[nNewWidget].m_nParent = rParentField.m_nObject;
     787                 :            :                         }
     788                 :          0 :                     }
     789                 :            :                 }
     790                 :            :             }
     791 [ #  # ][ #  # ]:          0 :             else if( m_aWidgets[it->second].m_eType != PDFWriter::Hierarchy )
     792                 :            :             {
     793                 :            :                 // this is invalid, someone tries to have a terminal field as parent
     794                 :            :                 // example: a button with the name foo.bar exists and
     795                 :            :                 // another button is named foo.bar.no
     796                 :            :                 // workaround: put the second terminal field as much up in the hierarchy as
     797                 :            :                 // necessary to have a non-terminal field as parent (or none at all)
     798                 :            :                 // since it->second already is terminal, we just need to use its parent
     799                 :          0 :                 aDomain = OString();
     800                 :          0 :                 aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 );
     801         [ #  # ]:          0 :                 if( nLastTokenIndex > 0 )
     802                 :            :                 {
     803                 :          0 :                     aDomain = aFullName.copy( 0, nLastTokenIndex-1 );
     804                 :          0 :                     OStringBuffer aBuf( aDomain.getLength() + 1 + aPartialName.getLength() );
     805         [ #  # ]:          0 :                     aBuf.append( aDomain );
     806         [ #  # ]:          0 :                     aBuf.append( '.' );
     807         [ #  # ]:          0 :                     aBuf.append( aPartialName );
     808                 :          0 :                     aFullName = aBuf.makeStringAndClear();
     809                 :            :                 }
     810                 :            :                 else
     811                 :          0 :                     aFullName = aPartialName;
     812                 :            :                 break;
     813                 :            :             }
     814                 :            :         }
     815                 :            :     } while( nTokenIndex != -1 );
     816                 :            : 
     817                 :            :     // insert widget into its hierarchy field
     818         [ #  # ]:          0 :     if( !aDomain.isEmpty() )
     819                 :            :     {
     820         [ #  # ]:          0 :         boost::unordered_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain );
     821 [ #  # ][ #  # ]:          0 :         if( it != m_aFieldNameMap.end() )
     822                 :            :         {
     823                 :            :             OSL_ENSURE( it->second >= 0 && it->second < sal_Int32( m_aWidgets.size() ), "invalid field index" );
     824 [ #  # ][ #  # ]:          0 :             if( it->second >= 0 && it->second < sal_Int32(m_aWidgets.size()) )
         [ #  # ][ #  # ]
                 [ #  # ]
     825                 :            :             {
     826         [ #  # ]:          0 :                 m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[it->second].m_nObject;
     827 [ #  # ][ #  # ]:          0 :                 m_aWidgets[it->second].m_aKids.push_back( m_aWidgets[i_nWidgetIndex].m_nObject);
     828 [ #  # ][ #  # ]:          0 :                 m_aWidgets[it->second].m_aKidsIndex.push_back( i_nWidgetIndex );
     829                 :            :             }
     830                 :            :         }
     831                 :            :     }
     832                 :            : 
     833         [ #  # ]:          0 :     if( aPartialName.isEmpty() )
     834                 :            :     {
     835                 :            :         // how funny, an empty field name
     836         [ #  # ]:          0 :         if( i_rControl.getType() == PDFWriter::RadioButton )
     837                 :            :         {
     838                 :          0 :             aPartialName  = "RadioGroup";
     839                 :          0 :             aPartialName += OString::valueOf( static_cast<const PDFWriter::RadioButtonWidget&>(i_rControl).RadioGroup );
     840                 :            :         }
     841                 :            :         else
     842                 :          0 :             aPartialName = OString( "Widget" );
     843                 :            :     }
     844                 :            : 
     845         [ #  # ]:          0 :     if( ! m_aContext.AllowDuplicateFieldNames )
     846                 :            :     {
     847         [ #  # ]:          0 :         boost::unordered_map<OString, sal_Int32, OStringHash>::iterator it = m_aFieldNameMap.find( aFullName );
     848                 :            : 
     849 [ #  # ][ #  # ]:          0 :         if( it != m_aFieldNameMap.end() ) // not unique
     850                 :            :         {
     851                 :          0 :             boost::unordered_map< OString, sal_Int32, OStringHash >::const_iterator check_it;
     852                 :          0 :             OString aTry;
     853                 :          0 :             sal_Int32 nTry = 2;
     854         [ #  # ]:          0 :             do
     855                 :            :             {
     856                 :          0 :                 OStringBuffer aUnique( aFullName.getLength() + 16 );
     857         [ #  # ]:          0 :                 aUnique.append( aFullName );
     858         [ #  # ]:          0 :                 aUnique.append( '_' );
     859         [ #  # ]:          0 :                 aUnique.append( nTry++ );
     860                 :          0 :                 aTry = aUnique.makeStringAndClear();
     861         [ #  # ]:          0 :                 check_it = m_aFieldNameMap.find( aTry );
     862         [ #  # ]:          0 :             } while( check_it != m_aFieldNameMap.end() );
     863                 :          0 :             aFullName = aTry;
     864         [ #  # ]:          0 :             m_aFieldNameMap[ aFullName ] = i_nWidgetIndex;
     865                 :          0 :             aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 );
     866                 :            :         }
     867                 :            :         else
     868         [ #  # ]:          0 :             m_aFieldNameMap[ aFullName ] = i_nWidgetIndex;
     869                 :            :     }
     870                 :            : 
     871                 :            :     // finally
     872                 :          0 :     m_aWidgets[i_nWidgetIndex].m_aName = aPartialName;
     873                 :          0 : }
     874                 :            : 
     875                 :          0 : static void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = nLog10Divisor )
     876                 :            : {
     877         [ #  # ]:          0 :     if( nValue < 0 )
     878                 :            :     {
     879                 :          0 :         rBuffer.append( '-' );
     880                 :          0 :         nValue = -nValue;
     881                 :            :     }
     882                 :          0 :     sal_Int32 nFactor = 1, nDiv = nPrecision;
     883         [ #  # ]:          0 :     while( nDiv-- )
     884                 :          0 :         nFactor *= 10;
     885                 :            : 
     886                 :          0 :     sal_Int32 nInt      = nValue / nFactor;
     887                 :          0 :     rBuffer.append( nInt );
     888         [ #  # ]:          0 :     if( nFactor > 1 )
     889                 :            :     {
     890                 :          0 :         sal_Int32 nDecimal  = nValue % nFactor;
     891         [ #  # ]:          0 :         if( nDecimal )
     892                 :            :         {
     893                 :          0 :             rBuffer.append( '.' );
     894                 :            :             // omit trailing zeros
     895         [ #  # ]:          0 :             while( (nDecimal % 10) == 0 )
     896                 :          0 :                 nDecimal /= 10;
     897                 :          0 :             rBuffer.append( nDecimal );
     898                 :            :         }
     899                 :            :     }
     900                 :          0 : }
     901                 :            : 
     902                 :            : 
     903                 :            : // appends a double. PDF does not accept exponential format, only fixed point
     904                 :          0 : static void appendDouble( double fValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = 5 )
     905                 :            : {
     906                 :          0 :     bool bNeg = false;
     907         [ #  # ]:          0 :     if( fValue < 0.0 )
     908                 :            :     {
     909                 :          0 :         bNeg = true;
     910                 :          0 :         fValue=-fValue;
     911                 :            :     }
     912                 :            : 
     913                 :          0 :     sal_Int64 nInt = (sal_Int64)fValue;
     914                 :          0 :     fValue -= (double)nInt;
     915                 :            :     // optimizing hardware may lead to a value of 1.0 after the subtraction
     916 [ #  # ][ #  # ]:          0 :     if( fValue == 1.0 || log10( 1.0-fValue ) <= -nPrecision )
                 [ #  # ]
     917                 :            :     {
     918                 :          0 :         nInt++;
     919                 :          0 :         fValue = 0.0;
     920                 :            :     }
     921                 :          0 :     sal_Int64 nFrac = 0;
     922         [ #  # ]:          0 :     if( fValue )
     923                 :            :     {
     924                 :          0 :         fValue *= pow( 10.0, (double)nPrecision );
     925                 :          0 :         nFrac = (sal_Int64)fValue;
     926                 :            :     }
     927 [ #  # ][ #  # ]:          0 :     if( bNeg && ( nInt || nFrac ) )
                 [ #  # ]
     928                 :          0 :         rBuffer.append( '-' );
     929                 :          0 :     rBuffer.append( nInt );
     930         [ #  # ]:          0 :     if( nFrac )
     931                 :            :     {
     932                 :            :         int i;
     933                 :          0 :         rBuffer.append( '.' );
     934                 :          0 :         sal_Int64 nBound = (sal_Int64)(pow( 10.0, nPrecision - 1.0 )+0.5);
     935 [ #  # ][ #  # ]:          0 :         for ( i = 0; ( i < nPrecision ) && nFrac; i++ )
                 [ #  # ]
     936                 :            :         {
     937                 :          0 :             sal_Int64 nNumb = nFrac / nBound;
     938                 :          0 :             nFrac -= nNumb * nBound;
     939                 :          0 :             rBuffer.append( nNumb );
     940                 :          0 :             nBound /= 10;
     941                 :            :         }
     942                 :            :     }
     943                 :          0 : }
     944                 :            : 
     945                 :            : 
     946                 :          0 : static void appendColor( const Color& rColor, OStringBuffer& rBuffer, bool bConvertToGrey = false )
     947                 :            : {
     948                 :            : 
     949         [ #  # ]:          0 :     if( rColor != Color( COL_TRANSPARENT ) )
     950                 :            :     {
     951         [ #  # ]:          0 :         if( bConvertToGrey )
     952                 :            :         {
     953                 :          0 :             sal_uInt8 cByte = rColor.GetLuminance();
     954                 :          0 :             appendDouble( (double)cByte / 255.0, rBuffer );
     955                 :            :         }
     956                 :            :         else
     957                 :            :         {
     958                 :          0 :             appendDouble( (double)rColor.GetRed() / 255.0, rBuffer );
     959                 :          0 :             rBuffer.append( ' ' );
     960                 :          0 :             appendDouble( (double)rColor.GetGreen() / 255.0, rBuffer );
     961                 :          0 :             rBuffer.append( ' ' );
     962                 :          0 :             appendDouble( (double)rColor.GetBlue() / 255.0, rBuffer );
     963                 :            :         }
     964                 :            :     }
     965                 :          0 : }
     966                 :            : 
     967                 :          0 : void PDFWriterImpl::appendStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
     968                 :            : {
     969         [ #  # ]:          0 :     if( rColor != Color( COL_TRANSPARENT ) )
     970                 :            :     {
     971                 :          0 :         bool bGrey = m_aContext.ColorMode == PDFWriter::DrawGreyscale;
     972                 :          0 :         appendColor( rColor, rBuffer, bGrey );
     973 [ #  # ][ #  # ]:          0 :         rBuffer.append( bGrey ? " G" : " RG" );
     974                 :            :     }
     975                 :          0 : }
     976                 :            : 
     977                 :          0 : void PDFWriterImpl::appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
     978                 :            : {
     979         [ #  # ]:          0 :     if( rColor != Color( COL_TRANSPARENT ) )
     980                 :            :     {
     981                 :          0 :         bool bGrey = m_aContext.ColorMode == PDFWriter::DrawGreyscale;
     982                 :          0 :         appendColor( rColor, rBuffer, bGrey );
     983 [ #  # ][ #  # ]:          0 :         rBuffer.append( bGrey ? " g" : " rg" );
     984                 :            :     }
     985                 :          0 : }
     986                 :            : 
     987                 :            : // matrix helper class
     988                 :            : // TODO: use basegfx matrix class instead or derive from it
     989                 :            : namespace vcl // TODO: use anonymous namespace to keep this class local
     990                 :            : {
     991                 :            : /*  for sparse matrices of the form (2D linear transformations)
     992                 :            :  *  f[0] f[1] 0
     993                 :            :  *  f[2] f[3] 0
     994                 :            :  *  f[4] f[5] 1
     995                 :            :  */
     996                 :            : class Matrix3
     997                 :            : {
     998                 :            :     double f[6];
     999                 :            : 
    1000         [ #  # ]:          0 :     void set( double *pn ) { for( int i = 0 ; i < 6; i++ ) f[i] = pn[i]; }
    1001                 :            : public:
    1002                 :            :     Matrix3();
    1003                 :          0 :     ~Matrix3() {}
    1004                 :            : 
    1005                 :            :     void skew( double alpha, double beta );
    1006                 :            :     void scale( double sx, double sy );
    1007                 :            :     void rotate( double angle );
    1008                 :            :     void translate( double tx, double ty );
    1009                 :            :     bool invert();
    1010                 :            : 
    1011                 :            :     void append( PDFWriterImpl::PDFPage& rPage, OStringBuffer& rBuffer, Point* pBack = NULL );
    1012                 :            : 
    1013                 :            :     Point transform( const Point& rPoint ) const;
    1014                 :            : };
    1015                 :            : }
    1016                 :            : 
    1017                 :          0 : Matrix3::Matrix3()
    1018                 :            : {
    1019                 :            :     // initialize to unity
    1020                 :          0 :     f[0] = 1.0;
    1021                 :          0 :     f[1] = 0.0;
    1022                 :          0 :     f[2] = 0.0;
    1023                 :          0 :     f[3] = 1.0;
    1024                 :          0 :     f[4] = 0.0;
    1025                 :          0 :     f[5] = 0.0;
    1026                 :          0 : }
    1027                 :            : 
    1028                 :          0 : Point Matrix3::transform( const Point& rOrig ) const
    1029                 :            : {
    1030                 :          0 :     double x = (double)rOrig.X(), y = (double)rOrig.Y();
    1031                 :          0 :     return Point( (int)(x*f[0] + y*f[2] + f[4]), (int)(x*f[1] + y*f[3] + f[5]) );
    1032                 :            : }
    1033                 :            : 
    1034                 :          0 : void Matrix3::skew( double alpha, double beta )
    1035                 :            : {
    1036                 :            :     double fn[6];
    1037                 :          0 :     double tb = tan( beta );
    1038                 :          0 :     fn[0] = f[0] + f[2]*tb;
    1039                 :          0 :     fn[1] = f[1];
    1040                 :          0 :     fn[2] = f[2] + f[3]*tb;
    1041                 :          0 :     fn[3] = f[3];
    1042                 :          0 :     fn[4] = f[4] + f[5]*tb;
    1043                 :          0 :     fn[5] = f[5];
    1044         [ #  # ]:          0 :     if( alpha != 0.0 )
    1045                 :            :     {
    1046                 :          0 :         double ta = tan( alpha );
    1047                 :          0 :         fn[1] += f[0]*ta;
    1048                 :          0 :         fn[3] += f[2]*ta;
    1049                 :          0 :         fn[5] += f[4]*ta;
    1050                 :            :     }
    1051                 :          0 :     set( fn );
    1052                 :          0 : }
    1053                 :            : 
    1054                 :          0 : void Matrix3::scale( double sx, double sy )
    1055                 :            : {
    1056                 :            :     double fn[6];
    1057                 :          0 :     fn[0] = sx*f[0];
    1058                 :          0 :     fn[1] = sy*f[1];
    1059                 :          0 :     fn[2] = sx*f[2];
    1060                 :          0 :     fn[3] = sy*f[3];
    1061                 :          0 :     fn[4] = sx*f[4];
    1062                 :          0 :     fn[5] = sy*f[5];
    1063                 :          0 :     set( fn );
    1064                 :          0 : }
    1065                 :            : 
    1066                 :          0 : void Matrix3::rotate( double angle )
    1067                 :            : {
    1068                 :            :     double fn[6];
    1069                 :          0 :     double fSin = sin(angle);
    1070                 :          0 :     double fCos = cos(angle);
    1071                 :          0 :     fn[0] = f[0]*fCos - f[1]*fSin;
    1072                 :          0 :     fn[1] = f[0]*fSin + f[1]*fCos;
    1073                 :          0 :     fn[2] = f[2]*fCos - f[3]*fSin;
    1074                 :          0 :     fn[3] = f[2]*fSin + f[3]*fCos;
    1075                 :          0 :     fn[4] = f[4]*fCos - f[5]*fSin;
    1076                 :          0 :     fn[5] = f[4]*fSin + f[5]*fCos;
    1077                 :          0 :     set( fn );
    1078                 :          0 : }
    1079                 :            : 
    1080                 :          0 : void Matrix3::translate( double tx, double ty )
    1081                 :            : {
    1082                 :          0 :     f[4] += tx;
    1083                 :          0 :     f[5] += ty;
    1084                 :          0 : }
    1085                 :            : 
    1086                 :          0 : bool Matrix3::invert()
    1087                 :            : {
    1088                 :            :     // short circuit trivial cases
    1089 [ #  # ][ #  # ]:          0 :     if( f[1]==f[2] && f[1]==0.0 && f[0]==f[3] && f[0]==1.0 )
         [ #  # ][ #  # ]
    1090                 :            :     {
    1091                 :          0 :         f[4] = -f[4];
    1092                 :          0 :         f[5] = -f[5];
    1093                 :          0 :         return true;
    1094                 :            :     }
    1095                 :            : 
    1096                 :            :     // check determinant
    1097                 :          0 :     const double fDet = f[0]*f[3]-f[1]*f[2];
    1098         [ #  # ]:          0 :     if( fDet == 0.0 )
    1099                 :          0 :         return false;
    1100                 :            : 
    1101                 :            :     // invert the matrix
    1102                 :            :     double fn[6];
    1103                 :          0 :     fn[0] = +f[3] / fDet;
    1104                 :          0 :     fn[1] = -f[1] / fDet;
    1105                 :          0 :     fn[2] = -f[2] / fDet;
    1106                 :          0 :     fn[3] = +f[0] / fDet;
    1107                 :            : 
    1108                 :            :     // apply inversion to translation
    1109                 :          0 :     fn[4] = -(f[4]*fn[0] + f[5]*fn[2]);
    1110                 :          0 :     fn[5] = -(f[4]*fn[1] + f[5]*fn[3]);
    1111                 :            : 
    1112                 :          0 :     set( fn );
    1113                 :          0 :     return true;
    1114                 :            : }
    1115                 :            : 
    1116                 :          0 : void Matrix3::append( PDFWriterImpl::PDFPage& rPage, OStringBuffer& rBuffer, Point* pBack )
    1117                 :            : {
    1118                 :          0 :     appendDouble( f[0], rBuffer );
    1119                 :          0 :     rBuffer.append( ' ' );
    1120                 :          0 :     appendDouble( f[1], rBuffer );
    1121                 :          0 :     rBuffer.append( ' ' );
    1122                 :          0 :     appendDouble( f[2], rBuffer );
    1123                 :          0 :     rBuffer.append( ' ' );
    1124                 :          0 :     appendDouble( f[3], rBuffer );
    1125                 :          0 :     rBuffer.append( ' ' );
    1126         [ #  # ]:          0 :     rPage.appendPoint( Point( (long)f[4], (long)f[5] ), rBuffer, false, pBack );
    1127                 :          0 : }
    1128                 :            : 
    1129                 :          0 : static void appendResourceMap( OStringBuffer& rBuf, const char* pPrefix, const PDFWriterImpl::ResourceMap& rList )
    1130                 :            : {
    1131         [ #  # ]:          0 :     if( rList.empty() )
    1132                 :          0 :         return;
    1133                 :          0 :     rBuf.append( '/' );
    1134                 :          0 :     rBuf.append( pPrefix );
    1135                 :          0 :     rBuf.append( "<<" );
    1136                 :          0 :     int ni = 0;
    1137         [ #  # ]:          0 :     for( PDFWriterImpl::ResourceMap::const_iterator it = rList.begin(); it != rList.end(); ++it )
    1138                 :            :     {
    1139 [ #  # ][ #  # ]:          0 :         if( !it->first.isEmpty() && it->second > 0 )
                 [ #  # ]
    1140                 :            :         {
    1141         [ #  # ]:          0 :             rBuf.append( '/' );
    1142         [ #  # ]:          0 :             rBuf.append( it->first );
    1143         [ #  # ]:          0 :             rBuf.append( ' ' );
    1144         [ #  # ]:          0 :             rBuf.append( it->second );
    1145         [ #  # ]:          0 :             rBuf.append( " 0 R" );
    1146         [ #  # ]:          0 :             if( ((++ni) & 7) == 0 )
    1147         [ #  # ]:          0 :                 rBuf.append( '\n' );
    1148                 :            :         }
    1149                 :            :     }
    1150                 :          0 :     rBuf.append( ">>\n" );
    1151                 :            : }
    1152                 :            : 
    1153                 :          0 : void PDFWriterImpl::ResourceDict::append( OStringBuffer& rBuf, sal_Int32 nFontDictObject )
    1154                 :            : {
    1155                 :          0 :     rBuf.append( "<</Font " );
    1156                 :          0 :     rBuf.append( nFontDictObject );
    1157                 :          0 :     rBuf.append( " 0 R\n" );
    1158                 :          0 :     appendResourceMap( rBuf, "XObject", m_aXObjects );
    1159                 :          0 :     appendResourceMap( rBuf, "ExtGState", m_aExtGStates );
    1160                 :          0 :     appendResourceMap( rBuf, "Shading", m_aShadings );
    1161                 :          0 :     appendResourceMap( rBuf, "Pattern", m_aPatterns );
    1162                 :          0 :     rBuf.append( "/ProcSet[/PDF/Text" );
    1163         [ #  # ]:          0 :     if( !m_aXObjects.empty() )
    1164                 :          0 :         rBuf.append( "/ImageC/ImageI/ImageB" );
    1165                 :          0 :     rBuf.append( "]\n>>\n" );
    1166                 :          0 : };
    1167                 :            : 
    1168                 :          0 : PDFWriterImpl::PDFPage::PDFPage( PDFWriterImpl* pWriter, sal_Int32 nPageWidth, sal_Int32 nPageHeight, PDFWriter::Orientation eOrientation )
    1169                 :            :         :
    1170                 :            :         m_pWriter( pWriter ),
    1171                 :            :         m_nPageWidth( nPageWidth ),
    1172                 :            :         m_nPageHeight( nPageHeight ),
    1173                 :            :         m_eOrientation( eOrientation ),
    1174                 :            :         m_nPageObject( 0 ),  // invalid object number
    1175                 :            :         m_nPageIndex( -1 ), // invalid index
    1176                 :            :         m_nStreamLengthObject( 0 ),
    1177                 :            :         m_nBeginStreamPos( 0 ),
    1178                 :            :         m_eTransition( PDFWriter::Regular ),
    1179                 :            :         m_nTransTime( 0 ),
    1180                 :            :         m_nDuration( 0 ),
    1181 [ #  # ][ #  # ]:          0 :         m_bHasWidgets( false )
    1182                 :            : {
    1183                 :            :     // object ref must be only ever updated in emit()
    1184         [ #  # ]:          0 :     m_nPageObject = m_pWriter->createObject();
    1185                 :          0 : }
    1186                 :            : 
    1187                 :          0 : PDFWriterImpl::PDFPage::~PDFPage()
    1188                 :            : {
    1189                 :          0 : }
    1190                 :            : 
    1191                 :          0 : void PDFWriterImpl::PDFPage::beginStream()
    1192                 :            : {
    1193                 :            : #if OSL_DEBUG_LEVEL > 1
    1194                 :            :     {
    1195                 :            :         OStringBuffer aLine( "PDFWriterImpl::PDFPage::beginStream, +" );
    1196                 :            :          m_pWriter->emitComment( aLine.getStr() );
    1197                 :            :     }
    1198                 :            : #endif
    1199 [ #  # ][ #  # ]:          0 :     m_aStreamObjects.push_back(m_pWriter->createObject());
    1200 [ #  # ][ #  # ]:          0 :     if( ! m_pWriter->updateObject( m_aStreamObjects.back() ) )
                 [ #  # ]
    1201                 :            :         return;
    1202                 :            : 
    1203         [ #  # ]:          0 :     m_nStreamLengthObject = m_pWriter->createObject();
    1204                 :            :     // write content stream header
    1205                 :          0 :     OStringBuffer aLine;
    1206 [ #  # ][ #  # ]:          0 :     aLine.append( m_aStreamObjects.back() );
    1207         [ #  # ]:          0 :     aLine.append( " 0 obj\n<</Length " );
    1208         [ #  # ]:          0 :     aLine.append( m_nStreamLengthObject );
    1209         [ #  # ]:          0 :     aLine.append( " 0 R" );
    1210                 :            : #if defined ( COMPRESS_PAGES ) && !defined ( DEBUG_DISABLE_PDFCOMPRESSION )
    1211         [ #  # ]:          0 :     aLine.append( "/Filter/FlateDecode" );
    1212                 :            : #endif
    1213         [ #  # ]:          0 :     aLine.append( ">>\nstream\n" );
    1214 [ #  # ][ #  # ]:          0 :     if( ! m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() ) )
    1215                 :            :         return;
    1216 [ #  # ][ #  # ]:          0 :     if( osl_File_E_None != osl_getFilePos( m_pWriter->m_aFile, &m_nBeginStreamPos ) )
    1217                 :            :     {
    1218         [ #  # ]:          0 :         osl_closeFile( m_pWriter->m_aFile );
    1219                 :          0 :         m_pWriter->m_bOpen = false;
    1220                 :            :     }
    1221                 :            : #if defined ( COMPRESS_PAGES ) && !defined ( DEBUG_DISABLE_PDFCOMPRESSION )
    1222         [ #  # ]:          0 :     m_pWriter->beginCompression();
    1223                 :            : #endif
    1224 [ #  # ][ #  # ]:          0 :     m_pWriter->checkAndEnableStreamEncryption( m_aStreamObjects.back() );
                 [ #  # ]
    1225                 :            : }
    1226                 :            : 
    1227                 :          0 : void PDFWriterImpl::PDFPage::endStream()
    1228                 :            : {
    1229                 :            : #if defined ( COMPRESS_PAGES ) && !defined ( DEBUG_DISABLE_PDFCOMPRESSION )
    1230         [ #  # ]:          0 :     m_pWriter->endCompression();
    1231                 :            : #endif
    1232                 :            :     sal_uInt64 nEndStreamPos;
    1233 [ #  # ][ #  # ]:          0 :     if( osl_File_E_None != osl_getFilePos( m_pWriter->m_aFile, &nEndStreamPos ) )
    1234                 :            :     {
    1235         [ #  # ]:          0 :         osl_closeFile( m_pWriter->m_aFile );
    1236                 :          0 :         m_pWriter->m_bOpen = false;
    1237                 :            :         return;
    1238                 :            :     }
    1239                 :          0 :     m_pWriter->disableStreamEncryption();
    1240 [ #  # ][ #  # ]:          0 :     if( ! m_pWriter->writeBuffer( "\nendstream\nendobj\n\n", 19 ) )
    1241                 :            :         return;
    1242                 :            :     // emit stream length object
    1243 [ #  # ][ #  # ]:          0 :     if( ! m_pWriter->updateObject( m_nStreamLengthObject ) )
    1244                 :            :         return;
    1245                 :          0 :     OStringBuffer aLine;
    1246         [ #  # ]:          0 :     aLine.append( m_nStreamLengthObject );
    1247         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    1248         [ #  # ]:          0 :     aLine.append( (sal_Int64)(nEndStreamPos-m_nBeginStreamPos) );
    1249         [ #  # ]:          0 :     aLine.append( "\nendobj\n\n" );
    1250         [ #  # ]:          0 :     m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
    1251                 :            : }
    1252                 :            : 
    1253                 :          0 : bool PDFWriterImpl::PDFPage::emit(sal_Int32 nParentObject )
    1254                 :            : {
    1255                 :            :     // emit page object
    1256 [ #  # ][ #  # ]:          0 :     if( ! m_pWriter->updateObject( m_nPageObject ) )
    1257                 :          0 :         return false;
    1258                 :          0 :     OStringBuffer aLine;
    1259                 :            : 
    1260         [ #  # ]:          0 :     aLine.append( m_nPageObject );
    1261                 :            :     aLine.append( " 0 obj\n"
    1262         [ #  # ]:          0 :                   "<</Type/Page/Parent " );
    1263         [ #  # ]:          0 :     aLine.append( nParentObject );
    1264         [ #  # ]:          0 :     aLine.append( " 0 R" );
    1265         [ #  # ]:          0 :     aLine.append( "/Resources " );
    1266 [ #  # ][ #  # ]:          0 :     aLine.append( m_pWriter->getResourceDictObj() );
    1267         [ #  # ]:          0 :     aLine.append( " 0 R" );
    1268 [ #  # ][ #  # ]:          0 :     if( m_nPageWidth && m_nPageHeight )
    1269                 :            :     {
    1270         [ #  # ]:          0 :         aLine.append( "/MediaBox[0 0 " );
    1271         [ #  # ]:          0 :         aLine.append( m_nPageWidth );
    1272         [ #  # ]:          0 :         aLine.append( ' ' );
    1273         [ #  # ]:          0 :         aLine.append( m_nPageHeight );
    1274         [ #  # ]:          0 :         aLine.append( "]" );
    1275                 :            :     }
    1276   [ #  #  #  # ]:          0 :     switch( m_eOrientation )
    1277                 :            :     {
    1278         [ #  # ]:          0 :         case PDFWriter::Landscape: aLine.append( "/Rotate 90\n" );break;
    1279         [ #  # ]:          0 :         case PDFWriter::Seascape:  aLine.append( "/Rotate -90\n" );break;
    1280         [ #  # ]:          0 :         case PDFWriter::Portrait:  aLine.append( "/Rotate 0\n" );break;
    1281                 :            : 
    1282                 :            :         case PDFWriter::Inherit:
    1283                 :            :         default:
    1284                 :          0 :             break;
    1285                 :            :     }
    1286                 :          0 :     int nAnnots = m_aAnnotations.size();
    1287         [ #  # ]:          0 :     if( nAnnots > 0 )
    1288                 :            :     {
    1289         [ #  # ]:          0 :         aLine.append( "/Annots[\n" );
    1290         [ #  # ]:          0 :         for( int i = 0; i < nAnnots; i++ )
    1291                 :            :         {
    1292 [ #  # ][ #  # ]:          0 :             aLine.append( m_aAnnotations[i] );
    1293         [ #  # ]:          0 :             aLine.append( " 0 R" );
    1294 [ #  # ][ #  # ]:          0 :             aLine.append( ((i+1)%15) ? " " : "\n" );
    1295                 :            :         }
    1296         [ #  # ]:          0 :         aLine.append( "]\n" );
    1297                 :            :     }
    1298         [ #  # ]:          0 :     if( m_aMCIDParents.size() > 0 )
    1299                 :            :     {
    1300                 :          0 :         OStringBuffer aStructParents( 1024 );
    1301         [ #  # ]:          0 :         aStructParents.append( "[ " );
    1302                 :          0 :         int nParents = m_aMCIDParents.size();
    1303         [ #  # ]:          0 :         for( int i = 0; i < nParents; i++ )
    1304                 :            :         {
    1305 [ #  # ][ #  # ]:          0 :             aStructParents.append( m_aMCIDParents[i] );
    1306         [ #  # ]:          0 :             aStructParents.append( " 0 R" );
    1307 [ #  # ][ #  # ]:          0 :             aStructParents.append( ((i%10) == 9) ? "\n" : " " );
    1308                 :            :         }
    1309         [ #  # ]:          0 :         aStructParents.append( "]" );
    1310         [ #  # ]:          0 :         m_pWriter->m_aStructParentTree.push_back( aStructParents.makeStringAndClear() );
    1311                 :            : 
    1312         [ #  # ]:          0 :         aLine.append( "/StructParents " );
    1313         [ #  # ]:          0 :         aLine.append( sal_Int32(m_pWriter->m_aStructParentTree.size()-1) );
    1314         [ #  # ]:          0 :         aLine.append( "\n" );
    1315                 :            :     }
    1316         [ #  # ]:          0 :     if( m_nDuration > 0 )
    1317                 :            :     {
    1318         [ #  # ]:          0 :         aLine.append( "/Dur " );
    1319         [ #  # ]:          0 :         aLine.append( (sal_Int32)m_nDuration );
    1320         [ #  # ]:          0 :         aLine.append( "\n" );
    1321                 :            :     }
    1322 [ #  # ][ #  # ]:          0 :     if( m_eTransition != PDFWriter::Regular && m_nTransTime > 0 )
    1323                 :            :     {
    1324                 :            :         // transition duration
    1325         [ #  # ]:          0 :         aLine.append( "/Trans<</D " );
    1326         [ #  # ]:          0 :         appendDouble( (double)m_nTransTime/1000.0, aLine, 3 );
    1327         [ #  # ]:          0 :         aLine.append( "\n" );
    1328                 :          0 :         const char *pStyle = NULL, *pDm = NULL, *pM = NULL, *pDi = NULL;
    1329   [ #  #  #  #  :          0 :         switch( m_eTransition )
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1330                 :            :         {
    1331                 :            :             case PDFWriter::SplitHorizontalInward:
    1332                 :          0 :                 pStyle = "Split"; pDm = "H"; pM = "I"; break;
    1333                 :            :             case PDFWriter::SplitHorizontalOutward:
    1334                 :          0 :                 pStyle = "Split"; pDm = "H"; pM = "O"; break;
    1335                 :            :             case PDFWriter::SplitVerticalInward:
    1336                 :          0 :                 pStyle = "Split"; pDm = "V"; pM = "I"; break;
    1337                 :            :             case PDFWriter::SplitVerticalOutward:
    1338                 :          0 :                 pStyle = "Split"; pDm = "V"; pM = "O"; break;
    1339                 :            :             case PDFWriter::BlindsHorizontal:
    1340                 :          0 :                 pStyle = "Blinds"; pDm = "H"; break;
    1341                 :            :             case PDFWriter::BlindsVertical:
    1342                 :          0 :                 pStyle = "Blinds"; pDm = "V"; break;
    1343                 :            :             case PDFWriter::BoxInward:
    1344                 :          0 :                 pStyle = "Box"; pM = "I"; break;
    1345                 :            :             case PDFWriter::BoxOutward:
    1346                 :          0 :                 pStyle = "Box"; pM = "O"; break;
    1347                 :            :             case PDFWriter::WipeLeftToRight:
    1348                 :          0 :                 pStyle = "Wipe"; pDi = "0"; break;
    1349                 :            :             case PDFWriter::WipeBottomToTop:
    1350                 :          0 :                 pStyle = "Wipe"; pDi = "90"; break;
    1351                 :            :             case PDFWriter::WipeRightToLeft:
    1352                 :          0 :                 pStyle = "Wipe"; pDi = "180"; break;
    1353                 :            :             case PDFWriter::WipeTopToBottom:
    1354                 :          0 :                 pStyle = "Wipe"; pDi = "270"; break;
    1355                 :            :             case PDFWriter::Dissolve:
    1356                 :          0 :                 pStyle = "Dissolve"; break;
    1357                 :            :             case PDFWriter::GlitterLeftToRight:
    1358                 :          0 :                 pStyle = "Glitter"; pDi = "0"; break;
    1359                 :            :             case PDFWriter::GlitterTopToBottom:
    1360                 :          0 :                 pStyle = "Glitter"; pDi = "270"; break;
    1361                 :            :             case PDFWriter::GlitterTopLeftToBottomRight:
    1362                 :          0 :                 pStyle = "Glitter"; pDi = "315"; break;
    1363                 :            :             case PDFWriter::Regular:
    1364                 :          0 :                 break;
    1365                 :            :         }
    1366                 :            :         // transition style
    1367         [ #  # ]:          0 :         if( pStyle )
    1368                 :            :         {
    1369         [ #  # ]:          0 :             aLine.append( "/S/" );
    1370         [ #  # ]:          0 :             aLine.append( pStyle );
    1371         [ #  # ]:          0 :             aLine.append( "\n" );
    1372                 :            :         }
    1373         [ #  # ]:          0 :         if( pDm )
    1374                 :            :         {
    1375         [ #  # ]:          0 :             aLine.append( "/Dm/" );
    1376         [ #  # ]:          0 :             aLine.append( pDm );
    1377         [ #  # ]:          0 :             aLine.append( "\n" );
    1378                 :            :         }
    1379         [ #  # ]:          0 :         if( pM )
    1380                 :            :         {
    1381         [ #  # ]:          0 :             aLine.append( "/M/" );
    1382         [ #  # ]:          0 :             aLine.append( pM );
    1383         [ #  # ]:          0 :             aLine.append( "\n" );
    1384                 :            :         }
    1385         [ #  # ]:          0 :         if( pDi  )
    1386                 :            :         {
    1387         [ #  # ]:          0 :             aLine.append( "/Di " );
    1388         [ #  # ]:          0 :             aLine.append( pDi );
    1389         [ #  # ]:          0 :             aLine.append( "\n" );
    1390                 :            :         }
    1391         [ #  # ]:          0 :         aLine.append( ">>\n" );
    1392                 :            :     }
    1393 [ #  # ][ #  # ]:          0 :     if( m_pWriter->getVersion() > PDFWriter::PDF_1_3 && ! m_pWriter->m_bIsPDF_A1 )
                 [ #  # ]
    1394                 :            :     {
    1395         [ #  # ]:          0 :         aLine.append( "/Group<</S/Transparency/CS/DeviceRGB/I true>>" );
    1396                 :            :     }
    1397         [ #  # ]:          0 :     aLine.append( "/Contents" );
    1398                 :          0 :     unsigned int nStreamObjects = m_aStreamObjects.size();
    1399         [ #  # ]:          0 :     if( nStreamObjects > 1 )
    1400         [ #  # ]:          0 :         aLine.append( '[' );
    1401         [ #  # ]:          0 :     for( unsigned int i = 0; i < m_aStreamObjects.size(); i++ )
    1402                 :            :     {
    1403         [ #  # ]:          0 :         aLine.append( ' ' );
    1404 [ #  # ][ #  # ]:          0 :         aLine.append( m_aStreamObjects[i] );
    1405         [ #  # ]:          0 :         aLine.append( " 0 R" );
    1406                 :            :     }
    1407         [ #  # ]:          0 :     if( nStreamObjects > 1 )
    1408         [ #  # ]:          0 :         aLine.append( ']' );
    1409         [ #  # ]:          0 :     aLine.append( ">>\nendobj\n\n" );
    1410         [ #  # ]:          0 :     return m_pWriter->writeBuffer( aLine.getStr(), aLine.getLength() );
    1411                 :            : }
    1412                 :            : 
    1413                 :            : namespace vcl
    1414                 :            : {
    1415                 :            : template < class GEOMETRY >
    1416                 :          0 : GEOMETRY lcl_convert( const MapMode& _rSource, const MapMode& _rDest, OutputDevice* _pPixelConversion, const GEOMETRY& _rObject )
    1417                 :            : {
    1418                 :          0 :     GEOMETRY aPoint;
    1419   [ #  #  #  #  :          0 :     if ( MAP_PIXEL == _rSource.GetMapUnit() )
             #  #  #  # ]
    1420                 :            :     {
    1421 [ #  # ][ #  # ]:          0 :         aPoint = _pPixelConversion->PixelToLogic( _rObject, _rDest );
                 [ #  # ]
    1422                 :            :     }
    1423                 :            :     else
    1424                 :            :     {
    1425 [ #  # ][ #  # ]:          0 :         aPoint = OutputDevice::LogicToLogic( _rObject, _rSource, _rDest );
                 [ #  # ]
    1426                 :            :     }
    1427                 :          0 :     return aPoint;
    1428                 :            : }
    1429                 :            : }
    1430                 :            : 
    1431                 :          0 : void PDFWriterImpl::PDFPage::appendPoint( const Point& rPoint, OStringBuffer& rBuffer, bool bNeg, Point* pOutPoint ) const
    1432                 :            : {
    1433         [ #  # ]:          0 :     if( pOutPoint )
    1434                 :            :     {
    1435         [ #  # ]:          0 :         Point aPoint( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1436                 :            :                                    m_pWriter->m_aMapMode,
    1437                 :            :                                    m_pWriter->getReferenceDevice(),
    1438 [ #  # ][ #  # ]:          0 :                                    rPoint ) );
    1439                 :          0 :         *pOutPoint = aPoint;
    1440                 :            :     }
    1441                 :            : 
    1442         [ #  # ]:          0 :     Point aPoint( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1443                 :            :                                m_pWriter->m_aMapMode,
    1444                 :            :                                m_pWriter->getReferenceDevice(),
    1445 [ #  # ][ #  # ]:          0 :                                rPoint ) );
    1446                 :            : 
    1447                 :          0 :     sal_Int32 nValue    = aPoint.X();
    1448         [ #  # ]:          0 :     if( bNeg )
    1449                 :          0 :         nValue = -nValue;
    1450                 :            : 
    1451         [ #  # ]:          0 :     appendFixedInt( nValue, rBuffer );
    1452                 :            : 
    1453         [ #  # ]:          0 :     rBuffer.append( ' ' );
    1454                 :            : 
    1455                 :          0 :     nValue      = pointToPixel(getHeight()) - aPoint.Y();
    1456         [ #  # ]:          0 :     if( bNeg )
    1457                 :          0 :         nValue = -nValue;
    1458                 :            : 
    1459         [ #  # ]:          0 :     appendFixedInt( nValue, rBuffer );
    1460                 :          0 : }
    1461                 :            : 
    1462                 :          0 : void PDFWriterImpl::PDFPage::appendPixelPoint( const basegfx::B2DPoint& rPoint, OStringBuffer& rBuffer ) const
    1463                 :            : {
    1464                 :          0 :     double fValue   = pixelToPoint(rPoint.getX());
    1465                 :            : 
    1466                 :          0 :     appendDouble( fValue, rBuffer, nLog10Divisor );
    1467                 :            : 
    1468                 :          0 :     rBuffer.append( ' ' );
    1469                 :            : 
    1470                 :          0 :     fValue      = double(getHeight()) - pixelToPoint(rPoint.getY());
    1471                 :            : 
    1472                 :          0 :     appendDouble( fValue, rBuffer, nLog10Divisor );
    1473                 :          0 : }
    1474                 :            : 
    1475                 :          0 : void PDFWriterImpl::PDFPage::appendRect( const Rectangle& rRect, OStringBuffer& rBuffer ) const
    1476                 :            : {
    1477 [ #  # ][ #  # ]:          0 :     appendPoint( rRect.BottomLeft() + Point( 0, 1 ), rBuffer );
    1478                 :          0 :     rBuffer.append( ' ' );
    1479                 :          0 :     appendMappedLength( (sal_Int32)rRect.GetWidth(), rBuffer, false );
    1480                 :          0 :     rBuffer.append( ' ' );
    1481                 :          0 :     appendMappedLength( (sal_Int32)rRect.GetHeight(), rBuffer, true );
    1482                 :          0 :     rBuffer.append( " re" );
    1483                 :          0 : }
    1484                 :            : 
    1485                 :          0 : void PDFWriterImpl::PDFPage::convertRect( Rectangle& rRect ) const
    1486                 :            : {
    1487         [ #  # ]:          0 :     Point aLL = lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1488                 :            :                              m_pWriter->m_aMapMode,
    1489                 :            :                              m_pWriter->getReferenceDevice(),
    1490         [ #  # ]:          0 :                              rRect.BottomLeft() + Point( 0, 1 )
    1491 [ #  # ][ #  # ]:          0 :                              );
    1492         [ #  # ]:          0 :     Size aSize = lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1493                 :            :                               m_pWriter->m_aMapMode,
    1494                 :            :                               m_pWriter->getReferenceDevice(),
    1495 [ #  # ][ #  # ]:          0 :                               rRect.GetSize() );
                 [ #  # ]
    1496                 :          0 :     rRect.Left()    = aLL.X();
    1497                 :          0 :     rRect.Right()   = aLL.X() + aSize.Width();
    1498                 :          0 :     rRect.Top()     = pointToPixel(getHeight()) - aLL.Y();
    1499                 :          0 :     rRect.Bottom()  = rRect.Top() + aSize.Height();
    1500                 :          0 : }
    1501                 :            : 
    1502                 :          0 : void PDFWriterImpl::PDFPage::appendPolygon( const Polygon& rPoly, OStringBuffer& rBuffer, bool bClose ) const
    1503                 :            : {
    1504                 :          0 :     sal_uInt16 nPoints = rPoly.GetSize();
    1505                 :            :     /*
    1506                 :            :      *  #108582# applications do weird things
    1507                 :            :      */
    1508                 :          0 :     sal_uInt32 nBufLen = rBuffer.getLength();
    1509         [ #  # ]:          0 :     if( nPoints > 0 )
    1510                 :            :     {
    1511                 :          0 :         const sal_uInt8* pFlagArray = rPoly.GetConstFlagAry();
    1512                 :          0 :         appendPoint( rPoly[0], rBuffer );
    1513                 :          0 :         rBuffer.append( " m\n" );
    1514         [ #  # ]:          0 :         for( sal_uInt16 i = 1; i < nPoints; i++ )
    1515                 :            :         {
    1516 [ #  # ][ #  # ]:          0 :             if( pFlagArray && pFlagArray[i] == POLY_CONTROL && nPoints-i > 2 )
                 [ #  # ]
    1517                 :            :             {
    1518                 :            :                 // bezier
    1519                 :            :                 DBG_ASSERT( pFlagArray[i+1] == POLY_CONTROL && pFlagArray[i+2] != POLY_CONTROL, "unexpected sequence of control points" );
    1520                 :          0 :                 appendPoint( rPoly[i], rBuffer );
    1521                 :          0 :                 rBuffer.append( " " );
    1522                 :          0 :                 appendPoint( rPoly[i+1], rBuffer );
    1523                 :          0 :                 rBuffer.append( " " );
    1524                 :          0 :                 appendPoint( rPoly[i+2], rBuffer );
    1525                 :          0 :                 rBuffer.append( " c" );
    1526                 :          0 :                 i += 2; // add additionally consumed points
    1527                 :            :             }
    1528                 :            :             else
    1529                 :            :             {
    1530                 :            :                 // line
    1531                 :          0 :                 appendPoint( rPoly[i], rBuffer );
    1532                 :          0 :                 rBuffer.append( " l" );
    1533                 :            :             }
    1534         [ #  # ]:          0 :             if( (rBuffer.getLength() - nBufLen) > 65 )
    1535                 :            :             {
    1536                 :          0 :                 rBuffer.append( "\n" );
    1537                 :          0 :                 nBufLen = rBuffer.getLength();
    1538                 :            :             }
    1539                 :            :             else
    1540                 :          0 :                 rBuffer.append( " " );
    1541                 :            :         }
    1542         [ #  # ]:          0 :         if( bClose )
    1543                 :          0 :             rBuffer.append( "h\n" );
    1544                 :            :     }
    1545                 :          0 : }
    1546                 :            : 
    1547                 :          0 : void PDFWriterImpl::PDFPage::appendPolygon( const basegfx::B2DPolygon& rPoly, OStringBuffer& rBuffer, bool bClose ) const
    1548                 :            : {
    1549         [ #  # ]:          0 :     basegfx::B2DPolygon aPoly( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1550                 :            :                                             m_pWriter->m_aMapMode,
    1551                 :            :                                             m_pWriter->getReferenceDevice(),
    1552 [ #  # ][ #  # ]:          0 :                                             rPoly ) );
    1553                 :            : 
    1554 [ #  # ][ #  # ]:          0 :     if( basegfx::tools::isRectangle( aPoly ) )
    1555                 :            :     {
    1556         [ #  # ]:          0 :         basegfx::B2DRange aRange( aPoly.getB2DRange() );
    1557 [ #  # ][ #  # ]:          0 :         basegfx::B2DPoint aBL( aRange.getMinX(), aRange.getMaxY() );
    1558         [ #  # ]:          0 :         appendPixelPoint( aBL, rBuffer );
    1559         [ #  # ]:          0 :         rBuffer.append( ' ' );
    1560 [ #  # ][ #  # ]:          0 :         appendMappedLength( aRange.getWidth(), rBuffer, false, NULL, nLog10Divisor );
    1561         [ #  # ]:          0 :         rBuffer.append( ' ' );
    1562 [ #  # ][ #  # ]:          0 :         appendMappedLength( aRange.getHeight(), rBuffer, true, NULL, nLog10Divisor );
    1563         [ #  # ]:          0 :         rBuffer.append( " re\n" );
    1564                 :          0 :         return;
    1565                 :            :     }
    1566         [ #  # ]:          0 :     sal_uInt32 nPoints = aPoly.count();
    1567         [ #  # ]:          0 :     if( nPoints > 0 )
    1568                 :            :     {
    1569                 :          0 :         sal_uInt32 nBufLen = rBuffer.getLength();
    1570         [ #  # ]:          0 :         basegfx::B2DPoint aLastPoint( aPoly.getB2DPoint( 0 ) );
    1571         [ #  # ]:          0 :         appendPixelPoint( aLastPoint, rBuffer );
    1572         [ #  # ]:          0 :         rBuffer.append( " m\n" );
    1573         [ #  # ]:          0 :         for( sal_uInt32 i = 1; i <= nPoints; i++ )
    1574                 :            :         {
    1575 [ #  # ][ #  # ]:          0 :             if( i != nPoints || aPoly.isClosed() )
         [ #  # ][ #  # ]
    1576                 :            :             {
    1577                 :          0 :                 sal_uInt32 nCurPoint  = i % nPoints;
    1578                 :          0 :                 sal_uInt32 nLastPoint = i-1;
    1579         [ #  # ]:          0 :                 basegfx::B2DPoint aPoint( aPoly.getB2DPoint( nCurPoint ) );
    1580 [ #  # ][ #  # ]:          0 :                 if( aPoly.isNextControlPointUsed( nLastPoint ) &&
         [ #  # ][ #  # ]
    1581         [ #  # ]:          0 :                     aPoly.isPrevControlPointUsed( nCurPoint ) )
    1582                 :            :                 {
    1583 [ #  # ][ #  # ]:          0 :                     appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer );
    1584         [ #  # ]:          0 :                     rBuffer.append( ' ' );
    1585 [ #  # ][ #  # ]:          0 :                     appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer );
    1586         [ #  # ]:          0 :                     rBuffer.append( ' ' );
    1587         [ #  # ]:          0 :                     appendPixelPoint( aPoint, rBuffer );
    1588         [ #  # ]:          0 :                     rBuffer.append( " c" );
    1589                 :            :                 }
    1590 [ #  # ][ #  # ]:          0 :                 else if( aPoly.isNextControlPointUsed( nLastPoint ) )
    1591                 :            :                 {
    1592 [ #  # ][ #  # ]:          0 :                     appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer );
    1593         [ #  # ]:          0 :                     rBuffer.append( ' ' );
    1594         [ #  # ]:          0 :                     appendPixelPoint( aPoint, rBuffer );
    1595         [ #  # ]:          0 :                     rBuffer.append( " y" );
    1596                 :            :                 }
    1597 [ #  # ][ #  # ]:          0 :                 else if( aPoly.isPrevControlPointUsed( nCurPoint ) )
    1598                 :            :                 {
    1599 [ #  # ][ #  # ]:          0 :                     appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer );
    1600         [ #  # ]:          0 :                     rBuffer.append( ' ' );
    1601         [ #  # ]:          0 :                     appendPixelPoint( aPoint, rBuffer );
    1602         [ #  # ]:          0 :                     rBuffer.append( " v" );
    1603                 :            :                 }
    1604                 :            :                 else
    1605                 :            :                 {
    1606         [ #  # ]:          0 :                     appendPixelPoint( aPoint, rBuffer );
    1607         [ #  # ]:          0 :                     rBuffer.append( " l" );
    1608                 :            :                 }
    1609         [ #  # ]:          0 :                 if( (rBuffer.getLength() - nBufLen) > 65 )
    1610                 :            :                 {
    1611         [ #  # ]:          0 :                     rBuffer.append( "\n" );
    1612                 :          0 :                     nBufLen = rBuffer.getLength();
    1613                 :            :                 }
    1614                 :            :                 else
    1615         [ #  # ]:          0 :                     rBuffer.append( " " );
    1616                 :            :             }
    1617                 :            :         }
    1618         [ #  # ]:          0 :         if( bClose )
    1619         [ #  # ]:          0 :             rBuffer.append( "h\n" );
    1620 [ #  # ][ #  # ]:          0 :     }
    1621                 :            : }
    1622                 :            : 
    1623                 :          0 : void PDFWriterImpl::PDFPage::appendPolyPolygon( const PolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const
    1624                 :            : {
    1625                 :          0 :     sal_uInt16 nPolygons = rPolyPoly.Count();
    1626         [ #  # ]:          0 :     for( sal_uInt16 n = 0; n < nPolygons; n++ )
    1627                 :          0 :         appendPolygon( rPolyPoly[n], rBuffer, bClose );
    1628                 :          0 : }
    1629                 :            : 
    1630                 :          0 : void PDFWriterImpl::PDFPage::appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const
    1631                 :            : {
    1632                 :          0 :     sal_uInt32 nPolygons = rPolyPoly.count();
    1633         [ #  # ]:          0 :     for( sal_uInt32 n = 0; n < nPolygons; n++ )
    1634         [ #  # ]:          0 :         appendPolygon( rPolyPoly.getB2DPolygon( n ), rBuffer, bClose );
    1635                 :          0 : }
    1636                 :            : 
    1637                 :          0 : void PDFWriterImpl::PDFPage::appendMappedLength( sal_Int32 nLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength ) const
    1638                 :            : {
    1639                 :          0 :     sal_Int32 nValue = nLength;
    1640         [ #  # ]:          0 :     if ( nLength < 0 )
    1641                 :            :     {
    1642         [ #  # ]:          0 :         rBuffer.append( '-' );
    1643                 :          0 :         nValue = -nLength;
    1644                 :            :     }
    1645         [ #  # ]:          0 :     Size aSize( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1646                 :            :                              m_pWriter->m_aMapMode,
    1647                 :            :                              m_pWriter->getReferenceDevice(),
    1648 [ #  # ][ #  # ]:          0 :                              Size( nValue, nValue ) ) );
    1649         [ #  # ]:          0 :     nValue = bVertical ? aSize.Height() : aSize.Width();
    1650         [ #  # ]:          0 :     if( pOutLength )
    1651         [ #  # ]:          0 :         *pOutLength = ((nLength < 0 ) ? -nValue : nValue);
    1652                 :            : 
    1653         [ #  # ]:          0 :     appendFixedInt( nValue, rBuffer, 1 );
    1654                 :          0 : }
    1655                 :            : 
    1656                 :          0 : void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength, sal_Int32 nPrecision ) const
    1657                 :            : {
    1658         [ #  # ]:          0 :     Size aSize( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode,
    1659                 :            :                              m_pWriter->m_aMapMode,
    1660                 :            :                              m_pWriter->getReferenceDevice(),
    1661 [ #  # ][ #  # ]:          0 :                              Size( 1000, 1000 ) ) );
    1662         [ #  # ]:          0 :     if( pOutLength )
    1663         [ #  # ]:          0 :         *pOutLength = (sal_Int32)(fLength*(double)(bVertical ? aSize.Height() : aSize.Width())/1000.0);
    1664         [ #  # ]:          0 :     fLength *= pixelToPoint((double)(bVertical ? aSize.Height() : aSize.Width()) / 1000.0);
    1665         [ #  # ]:          0 :     appendDouble( fLength, rBuffer, nPrecision );
    1666                 :          0 : }
    1667                 :            : 
    1668                 :          0 : bool PDFWriterImpl::PDFPage::appendLineInfo( const LineInfo& rInfo, OStringBuffer& rBuffer ) const
    1669                 :            : {
    1670                 :          0 :     bool bRet = true;
    1671         [ #  # ]:          0 :     if( rInfo.GetStyle() == LINE_DASH )
    1672                 :            :     {
    1673                 :          0 :         rBuffer.append( "[ " );
    1674         [ #  # ]:          0 :         if( rInfo.GetDashLen() == rInfo.GetDotLen() ) // degraded case
    1675                 :            :         {
    1676                 :          0 :             appendMappedLength( (sal_Int32)rInfo.GetDashLen(), rBuffer );
    1677                 :          0 :             rBuffer.append( ' ' );
    1678                 :          0 :             appendMappedLength( (sal_Int32)rInfo.GetDistance(), rBuffer );
    1679                 :          0 :             rBuffer.append( ' ' );
    1680                 :            :         }
    1681                 :            :         else
    1682                 :            :         {
    1683                 :            :             // check for implementation limits of dash array
    1684                 :            :             // in PDF reader apps (e.g. acroread)
    1685         [ #  # ]:          0 :             if( 2*(rInfo.GetDashCount() + rInfo.GetDotCount()) > 10 )
    1686                 :          0 :                 bRet = false;
    1687         [ #  # ]:          0 :             for( int n = 0; n < rInfo.GetDashCount(); n++ )
    1688                 :            :             {
    1689                 :          0 :                 appendMappedLength( (sal_Int32)rInfo.GetDashLen(), rBuffer );
    1690                 :          0 :                 rBuffer.append( ' ' );
    1691                 :          0 :                 appendMappedLength( (sal_Int32)rInfo.GetDistance(), rBuffer );
    1692                 :          0 :                 rBuffer.append( ' ' );
    1693                 :            :             }
    1694         [ #  # ]:          0 :             for( int m = 0; m < rInfo.GetDotCount(); m++ )
    1695                 :            :             {
    1696                 :          0 :                 appendMappedLength( (sal_Int32)rInfo.GetDotLen(), rBuffer );
    1697                 :          0 :                 rBuffer.append( ' ' );
    1698                 :          0 :                 appendMappedLength( (sal_Int32)rInfo.GetDistance(), rBuffer );
    1699                 :          0 :                 rBuffer.append( ' ' );
    1700                 :            :             }
    1701                 :            :         }
    1702                 :          0 :         rBuffer.append( "] 0 d\n" );
    1703                 :            :     }
    1704         [ #  # ]:          0 :     if( rInfo.GetWidth() > 1 )
    1705                 :            :     {
    1706                 :          0 :         appendMappedLength( (sal_Int32)rInfo.GetWidth(), rBuffer );
    1707                 :          0 :         rBuffer.append( " w\n" );
    1708                 :            :     }
    1709         [ #  # ]:          0 :     else if( rInfo.GetWidth() == 0 )
    1710                 :            :     {
    1711                 :            :         // "pixel" line
    1712                 :          0 :         appendDouble( 72.0/double(m_pWriter->getReferenceDevice()->ImplGetDPIX()), rBuffer );
    1713                 :          0 :         rBuffer.append( " w\n" );
    1714                 :            :     }
    1715                 :          0 :     return bRet;
    1716                 :            : }
    1717                 :            : 
    1718                 :          0 : void PDFWriterImpl::PDFPage::appendWaveLine( sal_Int32 nWidth, sal_Int32 nY, sal_Int32 nDelta, OStringBuffer& rBuffer ) const
    1719                 :            : {
    1720         [ #  # ]:          0 :     if( nWidth <= 0 )
    1721                 :          0 :         return;
    1722         [ #  # ]:          0 :     if( nDelta < 1 )
    1723                 :          0 :         nDelta = 1;
    1724                 :            : 
    1725                 :          0 :     rBuffer.append( "0 " );
    1726                 :          0 :     appendMappedLength( nY, rBuffer, true );
    1727                 :          0 :     rBuffer.append( " m\n" );
    1728         [ #  # ]:          0 :     for( sal_Int32 n = 0; n < nWidth; )
    1729                 :            :     {
    1730                 :          0 :         n += nDelta;
    1731                 :          0 :         appendMappedLength( n, rBuffer, false );
    1732                 :          0 :         rBuffer.append( ' ' );
    1733                 :          0 :         appendMappedLength( nDelta+nY, rBuffer, true );
    1734                 :          0 :         rBuffer.append( ' ' );
    1735                 :          0 :         n += nDelta;
    1736                 :          0 :         appendMappedLength( n, rBuffer, false );
    1737                 :          0 :         rBuffer.append( ' ' );
    1738                 :          0 :         appendMappedLength( nY, rBuffer, true );
    1739                 :          0 :         rBuffer.append( " v " );
    1740         [ #  # ]:          0 :         if( n < nWidth )
    1741                 :            :         {
    1742                 :          0 :             n += nDelta;
    1743                 :          0 :             appendMappedLength( n, rBuffer, false );
    1744                 :          0 :             rBuffer.append( ' ' );
    1745                 :          0 :             appendMappedLength( nY-nDelta, rBuffer, true );
    1746                 :          0 :             rBuffer.append( ' ' );
    1747                 :          0 :             n += nDelta;
    1748                 :          0 :             appendMappedLength( n, rBuffer, false );
    1749                 :          0 :             rBuffer.append( ' ' );
    1750                 :          0 :             appendMappedLength( nY, rBuffer, true );
    1751                 :          0 :             rBuffer.append( " v\n" );
    1752                 :            :         }
    1753                 :            :     }
    1754                 :          0 :     rBuffer.append( "S\n" );
    1755                 :            : }
    1756                 :            : 
    1757                 :            : /*
    1758                 :            :  *  class PDFWriterImpl
    1759                 :            :  */
    1760                 :            : 
    1761                 :          0 :  PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext,
    1762                 :            :                                const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >& xEnc,
    1763                 :            :                                PDFWriter& i_rOuterFace)
    1764                 :            :         :
    1765                 :            :         m_pReferenceDevice( NULL ),
    1766                 :            :         m_aMapMode( MAP_POINT, Point(), Fraction( 1L, pointToPixel(1) ), Fraction( 1L, pointToPixel(1) ) ),
    1767                 :            :         m_nCurrentStructElement( 0 ),
    1768                 :            :         m_bEmitStructure( true ),
    1769                 :            :         m_bNewMCID( false ),
    1770                 :            :         m_bEmbedStandardFonts( false ),
    1771                 :            :         m_nNextFID( 1 ),
    1772                 :            :         m_nInheritedPageWidth( 595 ),  // default A4
    1773                 :            :         m_nInheritedPageHeight( 842 ), // default A4
    1774                 :            :         m_eInheritedOrientation( PDFWriter::Portrait ),
    1775                 :            :         m_nCurrentPage( -1 ),
    1776                 :            :         m_nSignatureObject( -1 ),
    1777                 :            :         m_nSignatureContentOffset( 0 ),
    1778                 :            :         m_nSignatureLastByteRangeNoOffset( 0 ),
    1779                 :            :         m_nResourceDict( -1 ),
    1780                 :            :         m_nFontDictObject( -1 ),
    1781                 :            :         m_pCodec( NULL ),
    1782                 :          0 :         m_aDocDigest( rtl_digest_createMD5() ),
    1783                 :            :         m_aCipher( (rtlCipher)NULL ),
    1784                 :            :         m_aDigest( NULL ),
    1785                 :            :         m_bEncryptThisStream( false ),
    1786                 :            :         m_pEncryptionBuffer( NULL ),
    1787                 :            :         m_nEncryptionBufferSize( 0 ),
    1788                 :            :         m_bIsPDF_A1( false ),
    1789 [ #  # ][ #  # ]:          0 :         m_rOuterFace( i_rOuterFace )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1790                 :            : {
    1791                 :            : #ifdef DO_TEST_PDF
    1792                 :            :     static bool bOnce = true;
    1793                 :            :     if( bOnce )
    1794                 :            :     {
    1795                 :            :         bOnce = false;
    1796                 :            :         doTestCode();
    1797                 :            :     }
    1798                 :            : #endif
    1799         [ #  # ]:          0 :     m_aContext = rContext;
    1800 [ #  # ][ #  # ]:          0 :     m_aStructure.push_back( PDFStructureElement() );
    1801                 :          0 :     m_aStructure[0].m_nOwnElement       = 0;
    1802                 :          0 :     m_aStructure[0].m_nParentElement    = 0;
    1803                 :            : 
    1804         [ #  # ]:          0 :     Font aFont;
    1805 [ #  # ][ #  # ]:          0 :     aFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ) );
         [ #  # ][ #  # ]
    1806         [ #  # ]:          0 :     aFont.SetSize( Size( 0, 12 ) );
    1807                 :            : 
    1808         [ #  # ]:          0 :     GraphicsState aState;
    1809         [ #  # ]:          0 :     aState.m_aMapMode       = m_aMapMode;
    1810         [ #  # ]:          0 :     aState.m_aFont          = aFont;
    1811         [ #  # ]:          0 :     m_aGraphicsStack.push_front( aState );
    1812                 :            : 
    1813         [ #  # ]:          0 :     oslFileError  aError = osl_openFile( m_aContext.URL.pData, &m_aFile, osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
    1814         [ #  # ]:          0 :     if( aError != osl_File_E_None )
    1815                 :            :     {
    1816         [ #  # ]:          0 :         if( aError == osl_File_E_EXIST )
    1817                 :            :         {
    1818         [ #  # ]:          0 :             aError = osl_openFile( m_aContext.URL.pData, &m_aFile, osl_File_OpenFlag_Write );
    1819         [ #  # ]:          0 :             if( aError == osl_File_E_None )
    1820         [ #  # ]:          0 :                 aError = osl_setFileSize( m_aFile, 0 );
    1821                 :            :         }
    1822                 :            :     }
    1823         [ #  # ]:          0 :     if( aError != osl_File_E_None )
    1824                 :            :         return;
    1825                 :            : 
    1826                 :          0 :     m_bOpen = true;
    1827                 :            : 
    1828                 :            :     // setup DocInfo
    1829         [ #  # ]:          0 :     setupDocInfo();
    1830                 :            : 
    1831                 :            :     /* prepare the cypher engine, can be done in CTOR, free in DTOR */
    1832                 :          0 :     m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
    1833                 :          0 :     m_aDigest = rtl_digest_createMD5();
    1834                 :            : 
    1835                 :            :     /* the size of the Codec default maximum */
    1836         [ #  # ]:          0 :     checkEncryptionBufferSize( 0x4000 );
    1837                 :            : 
    1838         [ #  # ]:          0 :     if( xEnc.is() )
    1839         [ #  # ]:          0 :         prepareEncryption( xEnc );
    1840                 :            : 
    1841         [ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() )
    1842                 :            :     {
    1843                 :            :         // sanity check
    1844   [ #  #  #  #  :          0 :         if( m_aContext.Encryption.OValue.size() != ENCRYPTED_PWD_SIZE ||
           #  # ][ #  # ]
    1845                 :          0 :             m_aContext.Encryption.UValue.size() != ENCRYPTED_PWD_SIZE ||
    1846                 :          0 :             m_aContext.Encryption.EncryptionKey.size() != MAXIMUM_RC4_KEY_LENGTH
    1847                 :            :            )
    1848                 :            :         {
    1849                 :            :             // the field lengths are invalid ? This was not setup by initEncryption.
    1850                 :            :             // do not encrypt after all
    1851                 :          0 :             m_aContext.Encryption.OValue.clear();
    1852                 :          0 :             m_aContext.Encryption.UValue.clear();
    1853                 :            :             OSL_ENSURE( 0, "encryption data failed sanity check, encryption disabled" );
    1854                 :            :         }
    1855                 :            :         else // setup key lengths
    1856         [ #  # ]:          0 :             m_nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, m_nKeyLength, m_nRC4KeyLength );
    1857                 :            :     }
    1858                 :            : 
    1859                 :            :     // write header
    1860                 :          0 :     OStringBuffer aBuffer( 20 );
    1861         [ #  # ]:          0 :     aBuffer.append( "%PDF-" );
    1862   [ #  #  #  # ]:          0 :     switch( m_aContext.Version )
    1863                 :            :     {
    1864         [ #  # ]:          0 :         case PDFWriter::PDF_1_2: aBuffer.append( "1.2" );break;
    1865         [ #  # ]:          0 :         case PDFWriter::PDF_1_3: aBuffer.append( "1.3" );break;
    1866                 :            :         case PDFWriter::PDF_A_1:
    1867                 :            :         default:
    1868         [ #  # ]:          0 :         case PDFWriter::PDF_1_4: aBuffer.append( "1.4" );break;
    1869         [ #  # ]:          0 :         case PDFWriter::PDF_1_5: aBuffer.append( "1.5" );break;
    1870                 :            :     }
    1871                 :            :     // append something binary as comment (suggested in PDF Reference)
    1872         [ #  # ]:          0 :     aBuffer.append( "\n%äüöß\n" );
    1873 [ #  # ][ #  # ]:          0 :     if( !writeBuffer( aBuffer.getStr(), aBuffer.getLength() ) )
    1874                 :            :     {
    1875         [ #  # ]:          0 :         osl_closeFile( m_aFile );
    1876                 :          0 :         m_bOpen = false;
    1877                 :            :         return;
    1878                 :            :     }
    1879                 :            : 
    1880                 :            :     // insert outline root
    1881 [ #  # ][ #  # ]:          0 :     m_aOutline.push_back( PDFOutlineEntry() );
    1882                 :            : 
    1883                 :          0 :     m_bIsPDF_A1 = (m_aContext.Version == PDFWriter::PDF_A_1);
    1884         [ #  # ]:          0 :     if( m_bIsPDF_A1 )
    1885                 :          0 :         m_aContext.Version = PDFWriter::PDF_1_4; //meaning we need PDF 1.4, PDF/A flavour
    1886                 :            : 
    1887 [ #  # ][ #  # ]:          0 :     m_bEmbedStandardFonts = m_aContext.EmbedStandardFonts;
         [ #  # ][ #  # ]
                 [ #  # ]
    1888                 :            : }
    1889                 :            : 
    1890 [ #  # ][ #  # ]:          0 : PDFWriterImpl::~PDFWriterImpl()
         [ #  # ][ #  # ]
    1891                 :            : {
    1892         [ #  # ]:          0 :     if( m_aDocDigest )
    1893                 :          0 :         rtl_digest_destroyMD5( m_aDocDigest );
    1894 [ #  # ][ #  # ]:          0 :     delete static_cast<VirtualDevice*>(m_pReferenceDevice);
    1895                 :            : 
    1896         [ #  # ]:          0 :     if( m_aCipher )
    1897                 :          0 :         rtl_cipher_destroyARCFOUR( m_aCipher );
    1898         [ #  # ]:          0 :     if( m_aDigest )
    1899                 :          0 :         rtl_digest_destroyMD5( m_aDigest );
    1900                 :            : 
    1901                 :          0 :     rtl_freeMemory( m_pEncryptionBuffer );
    1902                 :          0 : }
    1903                 :            : 
    1904                 :          0 : void PDFWriterImpl::setupDocInfo()
    1905                 :            : {
    1906         [ #  # ]:          0 :     std::vector< sal_uInt8 > aId;
    1907         [ #  # ]:          0 :     computeDocumentIdentifier( aId, m_aContext.DocumentInfo, m_aCreationDateString, m_aCreationMetaDateString );
    1908         [ #  # ]:          0 :     if( m_aContext.Encryption.DocumentIdentifier.empty() )
    1909         [ #  # ]:          0 :         m_aContext.Encryption.DocumentIdentifier = aId;
    1910                 :          0 : }
    1911                 :            : 
    1912                 :          0 : void PDFWriterImpl::computeDocumentIdentifier( std::vector< sal_uInt8 >& o_rIdentifier,
    1913                 :            :                                                const vcl::PDFWriter::PDFDocInfo& i_rDocInfo,
    1914                 :            :                                                rtl::OString& o_rCString1,
    1915                 :            :                                                rtl::OString& o_rCString2
    1916                 :            :                                                )
    1917                 :            : {
    1918                 :          0 :     o_rIdentifier.clear();
    1919                 :            : 
    1920                 :            :     //build the document id
    1921                 :          0 :     rtl::OString aInfoValuesOut;
    1922                 :          0 :     OStringBuffer aID( 1024 );
    1923         [ #  # ]:          0 :     if( i_rDocInfo.Title.Len() )
    1924 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Title, aID );
    1925         [ #  # ]:          0 :     if( i_rDocInfo.Author.Len() )
    1926 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Author, aID );
    1927         [ #  # ]:          0 :     if( i_rDocInfo.Subject.Len() )
    1928 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Subject, aID );
    1929         [ #  # ]:          0 :     if( i_rDocInfo.Keywords.Len() )
    1930 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Keywords, aID );
    1931         [ #  # ]:          0 :     if( i_rDocInfo.Creator.Len() )
    1932 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Creator, aID );
    1933         [ #  # ]:          0 :     if( i_rDocInfo.Producer.Len() )
    1934 [ #  # ][ #  # ]:          0 :         appendUnicodeTextString( i_rDocInfo.Producer, aID );
    1935                 :            : 
    1936                 :            :     TimeValue aTVal, aGMT;
    1937                 :            :     oslDateTime aDT;
    1938         [ #  # ]:          0 :     osl_getSystemTime( &aGMT );
    1939         [ #  # ]:          0 :     osl_getLocalTimeFromSystemTime( &aGMT, &aTVal );
    1940         [ #  # ]:          0 :     osl_getDateTimeFromTimeValue( &aTVal, &aDT );
    1941                 :          0 :     rtl::OStringBuffer aCreationDateString(64), aCreationMetaDateString(64);
    1942         [ #  # ]:          0 :     aCreationDateString.append( "D:" );
    1943         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
    1944         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
    1945         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
    1946         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
    1947         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
    1948         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
    1949         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
    1950         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
    1951         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
    1952         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
    1953         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
    1954         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
    1955         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
    1956         [ #  # ]:          0 :     aCreationDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
    1957                 :            : 
    1958                 :            :     //--> i59651, we fill the Metadata date string as well, if PDF/A is requested
    1959                 :            :     // according to ISO 19005-1:2005 6.7.3 the date is corrected for
    1960                 :            :     // local time zone offset UTC only, whereas Acrobat 8 seems
    1961                 :            :     // to use the localtime notation only
    1962                 :            :     // according to a raccomandation in XMP Specification (Jan 2004, page 75)
    1963                 :            :     // the Acrobat way seems the right approach
    1964         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/1000)%10)) );
    1965         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/100)%10)) );
    1966         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year/10)%10)) );
    1967         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Year)%10)) );
    1968         [ #  # ]:          0 :     aCreationMetaDateString.append( "-" );
    1969         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month/10)%10)) );
    1970         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Month)%10)) );
    1971         [ #  # ]:          0 :     aCreationMetaDateString.append( "-" );
    1972         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day/10)%10)) );
    1973         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Day)%10)) );
    1974         [ #  # ]:          0 :     aCreationMetaDateString.append( "T" );
    1975         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours/10)%10)) );
    1976         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Hours)%10)) );
    1977         [ #  # ]:          0 :     aCreationMetaDateString.append( ":" );
    1978         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes/10)%10)) );
    1979         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Minutes)%10)) );
    1980         [ #  # ]:          0 :     aCreationMetaDateString.append( ":" );
    1981         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds/10)%10)) );
    1982         [ #  # ]:          0 :     aCreationMetaDateString.append( (sal_Char)('0' + ((aDT.Seconds)%10)) );
    1983                 :            : 
    1984                 :          0 :     sal_uInt32 nDelta = 0;
    1985         [ #  # ]:          0 :     if( aGMT.Seconds > aTVal.Seconds )
    1986                 :            :     {
    1987         [ #  # ]:          0 :         aCreationDateString.append( "-" );
    1988                 :          0 :         nDelta = aGMT.Seconds-aTVal.Seconds;
    1989         [ #  # ]:          0 :         aCreationMetaDateString.append( "-" );
    1990                 :            :     }
    1991         [ #  # ]:          0 :     else if( aGMT.Seconds < aTVal.Seconds )
    1992                 :            :     {
    1993         [ #  # ]:          0 :         aCreationDateString.append( "+" );
    1994                 :          0 :         nDelta = aTVal.Seconds-aGMT.Seconds;
    1995         [ #  # ]:          0 :         aCreationMetaDateString.append( "+" );
    1996                 :            :     }
    1997                 :            :     else
    1998                 :            :     {
    1999         [ #  # ]:          0 :         aCreationDateString.append( "Z" );
    2000         [ #  # ]:          0 :         aCreationMetaDateString.append( "Z" );
    2001                 :            : 
    2002                 :            :     }
    2003         [ #  # ]:          0 :     if( nDelta )
    2004                 :            :     {
    2005         [ #  # ]:          0 :         aCreationDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
    2006         [ #  # ]:          0 :         aCreationDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
    2007         [ #  # ]:          0 :         aCreationDateString.append( "'" );
    2008         [ #  # ]:          0 :         aCreationDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
    2009         [ #  # ]:          0 :         aCreationDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
    2010                 :            : 
    2011         [ #  # ]:          0 :         aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/36000)%10)) );
    2012         [ #  # ]:          0 :         aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/3600)%10)) );
    2013         [ #  # ]:          0 :         aCreationMetaDateString.append( ":" );
    2014         [ #  # ]:          0 :         aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/600)%6)) );
    2015         [ #  # ]:          0 :         aCreationMetaDateString.append( (sal_Char)('0' + ((nDelta/60)%10)) );
    2016                 :            :     }
    2017         [ #  # ]:          0 :     aCreationDateString.append( "'" );
    2018         [ #  # ]:          0 :     aID.append( aCreationDateString.getStr(), aCreationDateString.getLength() );
    2019                 :            : 
    2020                 :          0 :     aInfoValuesOut = aID.makeStringAndClear();
    2021                 :          0 :     o_rCString1 = aCreationDateString.makeStringAndClear();
    2022                 :          0 :     o_rCString2 = aCreationMetaDateString.makeStringAndClear();
    2023                 :            : 
    2024                 :          0 :     rtlDigest aDigest = rtl_digest_createMD5();
    2025                 :            :     OSL_ENSURE( aDigest != NULL, "PDFWriterImpl::computeDocumentIdentifier: cannot obtain a digest object !" );
    2026         [ #  # ]:          0 :     if( aDigest )
    2027                 :            :     {
    2028                 :          0 :         rtlDigestError nError = rtl_digest_updateMD5( aDigest, &aGMT, sizeof( aGMT ) );
    2029         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    2030                 :          0 :             nError = rtl_digest_updateMD5( aDigest, aInfoValuesOut.getStr(), aInfoValuesOut.getLength() );
    2031         [ #  # ]:          0 :         if( nError == rtl_Digest_E_None )
    2032                 :            :         {
    2033         [ #  # ]:          0 :             o_rIdentifier = std::vector< sal_uInt8 >( 16, 0 );
    2034                 :            :             //the binary form of the doc id is needed for encryption stuff
    2035         [ #  # ]:          0 :             rtl_digest_getMD5( aDigest, &o_rIdentifier[0], 16 );
    2036                 :            :         }
    2037                 :          0 :     }
    2038                 :          0 : }
    2039                 :            : 
    2040                 :            : /* i12626 methods */
    2041                 :            : /*
    2042                 :            : check if the Unicode string must be encrypted or not, perform the requested task,
    2043                 :            : append the string as unicode hex, encrypted if needed
    2044                 :            :  */
    2045                 :          0 : inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer )
    2046                 :            : {
    2047                 :          0 :     rOutBuffer.append( "<" );
    2048         [ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() )
    2049                 :            :     {
    2050                 :          0 :         const sal_Unicode* pStr = rInString.getStr();
    2051                 :          0 :         sal_Int32 nLen = rInString.getLength();
    2052                 :            : //prepare a unicode string, encrypt it
    2053         [ #  # ]:          0 :         if( checkEncryptionBufferSize( nLen*2 ) )
    2054                 :            :         {
    2055                 :          0 :             enableStringEncryption( nInObjectNumber );
    2056                 :          0 :             register sal_uInt8 *pCopy = m_pEncryptionBuffer;
    2057                 :          0 :             sal_Int32 nChars = 2;
    2058                 :          0 :             *pCopy++ = 0xFE;
    2059                 :          0 :             *pCopy++ = 0xFF;
    2060                 :            : // we need to prepare a byte stream from the unicode string buffer
    2061         [ #  # ]:          0 :             for( register int i = 0; i < nLen; i++ )
    2062                 :            :             {
    2063                 :          0 :                 register sal_Unicode aUnChar = pStr[i];
    2064                 :          0 :                 *pCopy++ = (sal_uInt8)( aUnChar >> 8 );
    2065                 :          0 :                 *pCopy++ = (sal_uInt8)( aUnChar & 255 );
    2066                 :          0 :                 nChars += 2;
    2067                 :            :             }
    2068                 :            : //encrypt in place
    2069                 :          0 :             rtl_cipher_encodeARCFOUR( m_aCipher, m_pEncryptionBuffer, nChars, m_pEncryptionBuffer, nChars );
    2070                 :            : //now append, hexadecimal (appendHex), the encrypted result
    2071         [ #  # ]:          0 :             for(register int i = 0; i < nChars; i++)
    2072                 :          0 :                 appendHex( m_pEncryptionBuffer[i], rOutBuffer );
    2073                 :            :         }
    2074                 :            :     }
    2075                 :            :     else
    2076                 :          0 :         appendUnicodeTextString( rInString, rOutBuffer );
    2077                 :          0 :     rOutBuffer.append( ">" );
    2078                 :          0 : }
    2079                 :            : 
    2080                 :          0 : inline void PDFWriterImpl::appendLiteralStringEncrypt( rtl::OStringBuffer& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer )
    2081                 :            : {
    2082                 :          0 :     rOutBuffer.append( "(" );
    2083                 :          0 :     sal_Int32 nChars = rInString.getLength();
    2084                 :            : //check for encryption, if ok, encrypt the string, then convert with appndLiteralString
    2085 [ #  # ][ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() && checkEncryptionBufferSize( nChars ) )
                 [ #  # ]
    2086                 :            :     {
    2087                 :            : //encrypt the string in a buffer, then append it
    2088                 :          0 :         enableStringEncryption( nInObjectNumber );
    2089                 :          0 :         rtl_cipher_encodeARCFOUR( m_aCipher, rInString.getStr(), nChars, m_pEncryptionBuffer, nChars );
    2090                 :          0 :         appendLiteralString( (const sal_Char*)m_pEncryptionBuffer, nChars, rOutBuffer );
    2091                 :            :     }
    2092                 :            :     else
    2093                 :          0 :         appendLiteralString( rInString.getStr(), nChars , rOutBuffer );
    2094                 :          0 :     rOutBuffer.append( ")" );
    2095                 :          0 : }
    2096                 :            : 
    2097                 :          0 : inline void PDFWriterImpl::appendLiteralStringEncrypt( const rtl::OString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer )
    2098                 :            : {
    2099         [ #  # ]:          0 :     rtl::OStringBuffer aBufferString( rInString );
    2100         [ #  # ]:          0 :     appendLiteralStringEncrypt( aBufferString, nInObjectNumber, rOutBuffer);
    2101                 :          0 : }
    2102                 :            : 
    2103                 :          0 : void PDFWriterImpl::appendLiteralStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc )
    2104                 :            : {
    2105         [ #  # ]:          0 :     rtl::OString aBufferString( rtl::OUStringToOString( rInString, nEnc ) );
    2106                 :          0 :     sal_Int32 nLen = aBufferString.getLength();
    2107                 :          0 :     rtl::OStringBuffer aBuf( nLen );
    2108                 :          0 :     const sal_Char* pT = aBufferString.getStr();
    2109                 :            : 
    2110         [ #  # ]:          0 :     for( sal_Int32 i = 0; i < nLen; i++, pT++ )
    2111                 :            :     {
    2112         [ #  # ]:          0 :         if( (*pT & 0x80) == 0 )
    2113         [ #  # ]:          0 :             aBuf.append( *pT );
    2114                 :            :         else
    2115                 :            :         {
    2116         [ #  # ]:          0 :             aBuf.append( '<' );
    2117         [ #  # ]:          0 :             appendHex( *pT, aBuf );
    2118         [ #  # ]:          0 :             aBuf.append( '>' );
    2119                 :            :         }
    2120                 :            :     }
    2121                 :          0 :     aBufferString = aBuf.makeStringAndClear();
    2122         [ #  # ]:          0 :     appendLiteralStringEncrypt( aBufferString, nInObjectNumber, rOutBuffer);
    2123                 :          0 : }
    2124                 :            : 
    2125                 :            : /* end i12626 methods */
    2126                 :            : 
    2127                 :          0 : void PDFWriterImpl::emitComment( const char* pComment )
    2128                 :            : {
    2129                 :          0 :     OStringBuffer aLine( 64 );
    2130         [ #  # ]:          0 :     aLine.append( "% " );
    2131         [ #  # ]:          0 :     aLine.append( (const sal_Char*)pComment );
    2132         [ #  # ]:          0 :     aLine.append( "\n" );
    2133         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    2134                 :          0 : }
    2135                 :            : 
    2136                 :          0 : bool PDFWriterImpl::compressStream( SvMemoryStream* pStream )
    2137                 :            : {
    2138                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    2139         [ #  # ]:          0 :     pStream->Seek( STREAM_SEEK_TO_END );
    2140                 :          0 :     sal_uLong nEndPos = pStream->Tell();
    2141         [ #  # ]:          0 :     pStream->Seek( STREAM_SEEK_TO_BEGIN );
    2142 [ #  # ][ #  # ]:          0 :     ZCodec* pCodec = new ZCodec( 0x4000, 0x4000 );
    2143         [ #  # ]:          0 :     SvMemoryStream aStream;
    2144         [ #  # ]:          0 :     pCodec->BeginCompression();
    2145 [ #  # ][ #  # ]:          0 :     pCodec->Write( aStream, (const sal_uInt8*)pStream->GetData(), nEndPos );
    2146         [ #  # ]:          0 :     pCodec->EndCompression();
    2147 [ #  # ][ #  # ]:          0 :     delete pCodec;
    2148                 :          0 :     nEndPos = aStream.Tell();
    2149         [ #  # ]:          0 :     pStream->Seek( STREAM_SEEK_TO_BEGIN );
    2150         [ #  # ]:          0 :     aStream.Seek( STREAM_SEEK_TO_BEGIN );
    2151         [ #  # ]:          0 :     pStream->SetStreamSize( nEndPos );
    2152 [ #  # ][ #  # ]:          0 :     pStream->Write( aStream.GetData(), nEndPos );
    2153         [ #  # ]:          0 :     return true;
    2154                 :            : #else
    2155                 :            :     (void)pStream;
    2156                 :            :     return false;
    2157                 :            : #endif
    2158                 :            : }
    2159                 :            : 
    2160                 :          0 : void PDFWriterImpl::beginCompression()
    2161                 :            : {
    2162                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    2163         [ #  # ]:          0 :     m_pCodec = new ZCodec( 0x4000, 0x4000 );
    2164         [ #  # ]:          0 :     m_pMemStream = new SvMemoryStream();
    2165                 :          0 :     m_pCodec->BeginCompression();
    2166                 :            : #endif
    2167                 :          0 : }
    2168                 :            : 
    2169                 :          0 : void PDFWriterImpl::endCompression()
    2170                 :            : {
    2171                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    2172         [ #  # ]:          0 :     if( m_pCodec )
    2173                 :            :     {
    2174                 :          0 :         m_pCodec->EndCompression();
    2175         [ #  # ]:          0 :         delete m_pCodec;
    2176                 :          0 :         m_pCodec = NULL;
    2177                 :          0 :         sal_uInt64 nLen = m_pMemStream->Tell();
    2178                 :          0 :         m_pMemStream->Seek( 0 );
    2179                 :          0 :         writeBuffer( m_pMemStream->GetData(), nLen );
    2180         [ #  # ]:          0 :         delete m_pMemStream;
    2181                 :          0 :         m_pMemStream = NULL;
    2182                 :            :     }
    2183                 :            : #endif
    2184                 :          0 : }
    2185                 :            : 
    2186                 :          0 : bool PDFWriterImpl::writeBuffer( const void* pBuffer, sal_uInt64 nBytes )
    2187                 :            : {
    2188         [ #  # ]:          0 :     if( ! m_bOpen ) // we are already down the drain
    2189                 :          0 :         return false;
    2190                 :            : 
    2191         [ #  # ]:          0 :     if( ! nBytes ) // huh ?
    2192                 :          0 :         return true;
    2193                 :            : 
    2194         [ #  # ]:          0 :     if( m_aOutputStreams.begin() != m_aOutputStreams.end() )
    2195                 :            :     {
    2196 [ #  # ][ #  # ]:          0 :         m_aOutputStreams.front().m_pStream->Seek( STREAM_SEEK_TO_END );
    2197 [ #  # ][ #  # ]:          0 :         m_aOutputStreams.front().m_pStream->Write( pBuffer, sal::static_int_cast<sal_Size>(nBytes) );
    2198                 :          0 :         return true;
    2199                 :            :     }
    2200                 :            : 
    2201                 :            :     sal_uInt64 nWritten;
    2202         [ #  # ]:          0 :     if( m_pCodec )
    2203                 :            :     {
    2204         [ #  # ]:          0 :         m_pCodec->Write( *m_pMemStream, static_cast<const sal_uInt8*>(pBuffer), (sal_uLong)nBytes );
    2205                 :          0 :         nWritten = nBytes;
    2206                 :            :     }
    2207                 :            :     else
    2208                 :            :     {
    2209                 :          0 :         sal_Bool  buffOK = sal_True;
    2210         [ #  # ]:          0 :         if( m_bEncryptThisStream )
    2211                 :            :         {
    2212                 :            : /* implement the encryption part of the PDF spec encryption algorithm 3.1 */
    2213 [ #  # ][ #  # ]:          0 :             if( ( buffOK = checkEncryptionBufferSize( static_cast<sal_Int32>(nBytes) ) ) != sal_False )
    2214                 :            :                 rtl_cipher_encodeARCFOUR( m_aCipher,
    2215                 :            :                                           (sal_uInt8*)pBuffer, static_cast<sal_Size>(nBytes),
    2216                 :          0 :                                           m_pEncryptionBuffer, static_cast<sal_Size>(nBytes) );
    2217                 :            :         }
    2218                 :            : 
    2219 [ #  # ][ #  # ]:          0 :         const void* pWriteBuffer = ( m_bEncryptThisStream && buffOK ) ? m_pEncryptionBuffer  : pBuffer;
    2220         [ #  # ]:          0 :         if( m_aDocDigest )
    2221                 :          0 :             rtl_digest_updateMD5( m_aDocDigest, pWriteBuffer, static_cast<sal_uInt32>(nBytes) );
    2222                 :            : 
    2223         [ #  # ]:          0 :         if( osl_writeFile( m_aFile,
    2224                 :            :                            pWriteBuffer,
    2225         [ #  # ]:          0 :                            nBytes, &nWritten ) != osl_File_E_None )
    2226                 :          0 :             nWritten = 0;
    2227                 :            : 
    2228         [ #  # ]:          0 :         if( nWritten != nBytes )
    2229                 :            :         {
    2230         [ #  # ]:          0 :             osl_closeFile( m_aFile );
    2231                 :          0 :             m_bOpen = false;
    2232                 :            :         }
    2233                 :            :     }
    2234                 :            : 
    2235                 :          0 :     return nWritten == nBytes;
    2236                 :            : }
    2237                 :            : 
    2238                 :          0 : OutputDevice* PDFWriterImpl::getReferenceDevice()
    2239                 :            : {
    2240         [ #  # ]:          0 :     if( ! m_pReferenceDevice )
    2241                 :            :     {
    2242         [ #  # ]:          0 :         VirtualDevice*  pVDev = new VirtualDevice( 0 );
    2243                 :            : 
    2244                 :          0 :         m_pReferenceDevice = pVDev;
    2245                 :            : 
    2246 [ #  # ][ #  # ]:          0 :         if( m_aContext.DPIx == 0 || m_aContext.DPIy == 0 )
    2247                 :          0 :             pVDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_PDF1 );
    2248                 :            :         else
    2249                 :          0 :             pVDev->SetReferenceDevice( m_aContext.DPIx, m_aContext.DPIy );
    2250                 :            : 
    2251         [ #  # ]:          0 :         pVDev->SetOutputSizePixel( Size( 640, 480 ) );
    2252         [ #  # ]:          0 :         pVDev->SetMapMode( MAP_MM );
    2253                 :            : 
    2254                 :          0 :         m_pReferenceDevice->mpPDFWriter = this;
    2255                 :          0 :         m_pReferenceDevice->ImplUpdateFontData( sal_True );
    2256                 :            :     }
    2257                 :          0 :     return m_pReferenceDevice;
    2258                 :            : }
    2259                 :            : 
    2260         [ #  # ]:          0 : class ImplPdfBuiltinFontData : public PhysicalFontFace
    2261                 :            : {
    2262                 :            : private:
    2263                 :            :     const PDFWriterImpl::BuiltinFont& mrBuiltin;
    2264                 :            : 
    2265                 :            : public:
    2266                 :            :     enum {PDF_FONT_MAGIC = 0xBDFF0A1C };
    2267                 :            :                                         ImplPdfBuiltinFontData( const PDFWriterImpl::BuiltinFont& );
    2268                 :          0 :     const PDFWriterImpl::BuiltinFont*   GetBuiltinFont() const  { return &mrBuiltin; }
    2269                 :            : 
    2270         [ #  # ]:          0 :     virtual PhysicalFontFace*           Clone() const { return new ImplPdfBuiltinFontData(*this); }
    2271                 :            :     virtual ImplFontEntry*              CreateFontInstance( FontSelectPattern& ) const;
    2272                 :          0 :     virtual sal_IntPtr                  GetFontId() const { return reinterpret_cast<sal_IntPtr>(&mrBuiltin); }
    2273                 :            : };
    2274                 :            : 
    2275                 :          0 : inline const ImplPdfBuiltinFontData* GetPdfFontData( const PhysicalFontFace* pFontData )
    2276                 :            : {
    2277                 :          0 :     const ImplPdfBuiltinFontData* pFD = NULL;
    2278 [ #  # ][ #  # ]:          0 :     if( pFontData && pFontData->CheckMagic( ImplPdfBuiltinFontData::PDF_FONT_MAGIC ) )
                 [ #  # ]
    2279                 :          0 :         pFD = static_cast<const ImplPdfBuiltinFontData*>( pFontData );
    2280                 :          0 :     return pFD;
    2281                 :            : }
    2282                 :            : 
    2283                 :          0 : static ImplDevFontAttributes GetDevFontAttributes( const PDFWriterImpl::BuiltinFont& rBuiltin )
    2284                 :            : {
    2285                 :          0 :     ImplDevFontAttributes aDFA;
    2286         [ #  # ]:          0 :     aDFA.maName         = rtl::OUString::createFromAscii( rBuiltin.m_pName );
    2287         [ #  # ]:          0 :     aDFA.maStyleName    = rtl::OUString::createFromAscii( rBuiltin.m_pStyleName );
    2288                 :          0 :     aDFA.meFamily       = rBuiltin.m_eFamily;
    2289                 :          0 :     aDFA.mbSymbolFlag   = (rBuiltin.m_eCharSet != RTL_TEXTENCODING_MS_1252 );
    2290                 :          0 :     aDFA.mePitch        = rBuiltin.m_ePitch;
    2291                 :          0 :     aDFA.meWeight       = rBuiltin.m_eWeight;
    2292                 :          0 :     aDFA.meItalic       = rBuiltin.m_eItalic;
    2293                 :          0 :     aDFA.meWidthType    = rBuiltin.m_eWidthType;
    2294                 :            : 
    2295                 :          0 :     aDFA.mbOrientation  = true;
    2296                 :          0 :     aDFA.mbDevice       = true;
    2297                 :          0 :     aDFA.mnQuality      = 50000;
    2298                 :          0 :     aDFA.mbSubsettable  = false;
    2299                 :          0 :     aDFA.mbEmbeddable   = false;
    2300                 :          0 :     return aDFA;
    2301                 :            : }
    2302                 :            : 
    2303                 :          0 : ImplPdfBuiltinFontData::ImplPdfBuiltinFontData( const PDFWriterImpl::BuiltinFont& rBuiltin )
    2304                 :            : :   PhysicalFontFace( GetDevFontAttributes(rBuiltin), PDF_FONT_MAGIC ),
    2305         [ #  # ]:          0 :     mrBuiltin( rBuiltin )
    2306                 :          0 : {}
    2307                 :            : 
    2308                 :          0 : ImplFontEntry* ImplPdfBuiltinFontData::CreateFontInstance( FontSelectPattern& rFSD ) const
    2309                 :            : {
    2310         [ #  # ]:          0 :     ImplFontEntry* pEntry = new ImplFontEntry( rFSD );
    2311                 :          0 :     return pEntry;
    2312                 :            : }
    2313                 :            : 
    2314                 :          0 : ImplDevFontList* PDFWriterImpl::filterDevFontList( ImplDevFontList* pFontList )
    2315                 :            : {
    2316                 :            :     DBG_ASSERT( m_aSubsets.empty(), "Fonts changing during PDF generation, document will be invalid" );
    2317                 :          0 :     ImplDevFontList* pFiltered = pFontList->Clone( true, true );
    2318                 :            : 
    2319                 :            :     // append the PDF builtin fonts
    2320 [ #  # ][ #  # ]:          0 :     if( !m_bIsPDF_A1 && !m_bEmbedStandardFonts)
    2321         [ #  # ]:          0 :         for( unsigned int i = 0; i < SAL_N_ELEMENTS(m_aBuiltinFonts); i++ )
    2322                 :            :         {
    2323         [ #  # ]:          0 :             PhysicalFontFace* pNewData = new ImplPdfBuiltinFontData( m_aBuiltinFonts[i] );
    2324                 :          0 :             pFiltered->Add( pNewData );
    2325                 :            :         }
    2326                 :          0 :     return pFiltered;
    2327                 :            : }
    2328                 :            : 
    2329                 :          0 : bool PDFWriterImpl::isBuiltinFont( const PhysicalFontFace* pFont ) const
    2330                 :            : {
    2331                 :          0 :     const ImplPdfBuiltinFontData* pFD = GetPdfFontData( pFont );
    2332                 :          0 :     return (pFD != NULL);
    2333                 :            : }
    2334                 :            : 
    2335                 :          0 : void PDFWriterImpl::getFontMetric( FontSelectPattern* pSelect, ImplFontMetricData* pMetric ) const
    2336                 :            : {
    2337                 :          0 :     const ImplPdfBuiltinFontData* pFD = GetPdfFontData( pSelect->mpFontData );
    2338         [ #  # ]:          0 :     if( !pFD )
    2339                 :          0 :         return;
    2340                 :          0 :     const BuiltinFont* pBuiltinFont = pFD->GetBuiltinFont();
    2341                 :            : 
    2342                 :          0 :     pMetric->mnOrientation  = sal::static_int_cast<short>(pSelect->mnOrientation);
    2343                 :          0 :     pMetric->meFamily       = pBuiltinFont->m_eFamily;
    2344                 :          0 :     pMetric->mePitch        = pBuiltinFont->m_ePitch;
    2345                 :          0 :     pMetric->meWeight       = pBuiltinFont->m_eWeight;
    2346                 :          0 :     pMetric->meItalic       = pBuiltinFont->m_eItalic;
    2347                 :          0 :     pMetric->mbSymbolFlag   = pFD->IsSymbolFont();
    2348                 :          0 :     pMetric->mnWidth        = pSelect->mnHeight;
    2349                 :          0 :     pMetric->mnAscent       = ( pSelect->mnHeight * +pBuiltinFont->m_nAscent + 500 ) / 1000;
    2350                 :          0 :     pMetric->mnDescent      = ( pSelect->mnHeight * -pBuiltinFont->m_nDescent + 500 ) / 1000;
    2351                 :          0 :     pMetric->mnIntLeading   = 0;
    2352                 :          0 :     pMetric->mnExtLeading   = 0;
    2353                 :          0 :     pMetric->mnSlant        = 0;
    2354                 :          0 :     pMetric->mbScalableFont = true;
    2355                 :          0 :     pMetric->mbDevice       = true;
    2356                 :            : }
    2357                 :            : 
    2358                 :            : // -----------------------------------------------------------------------
    2359                 :            : 
    2360                 :            : namespace vcl {
    2361                 :            : 
    2362 [ #  # ][ #  # ]:          0 : class PDFSalLayout : public GenericSalLayout
    2363                 :            : {
    2364                 :            :     PDFWriterImpl&  mrPDFWriterImpl;
    2365                 :            :     const PDFWriterImpl::BuiltinFont& mrBuiltinFont;
    2366                 :            :     bool            mbIsSymbolFont;
    2367                 :            :     long            mnPixelPerEM;
    2368                 :            :     String          maOrigText;
    2369                 :            : 
    2370                 :            : public:
    2371                 :            :                     PDFSalLayout( PDFWriterImpl&,
    2372                 :            :                                   const PDFWriterImpl::BuiltinFont&,
    2373                 :            :                                   long nPixelPerEM, int nOrientation );
    2374                 :            : 
    2375                 :          0 :     void            SetText( const rtl::OUString& rText )  { maOrigText = rText; }
    2376                 :            :     virtual bool    LayoutText( ImplLayoutArgs& );
    2377                 :            :     virtual void    InitFont() const;
    2378                 :            :     virtual void    DrawText( SalGraphics& ) const;
    2379                 :            : };
    2380                 :            : 
    2381                 :            : }
    2382                 :            : 
    2383                 :            : // -----------------------------------------------------------------------
    2384                 :            : 
    2385                 :          0 : PDFSalLayout::PDFSalLayout( PDFWriterImpl& rPDFWriterImpl,
    2386                 :            :     const PDFWriterImpl::BuiltinFont& rBuiltinFont,
    2387                 :            :     long nPixelPerEM, int nOrientation )
    2388                 :            : :   mrPDFWriterImpl( rPDFWriterImpl ),
    2389                 :            :     mrBuiltinFont( rBuiltinFont ),
    2390         [ #  # ]:          0 :     mnPixelPerEM( nPixelPerEM )
    2391                 :            : {
    2392                 :          0 :     mbIsSymbolFont = (rBuiltinFont.m_eCharSet != RTL_TEXTENCODING_MS_1252);
    2393                 :          0 :     SetOrientation( nOrientation );
    2394                 :          0 : }
    2395                 :            : 
    2396                 :            : // -----------------------------------------------------------------------
    2397                 :            : 
    2398                 :          0 : bool PDFSalLayout::LayoutText( ImplLayoutArgs& rArgs )
    2399                 :            : {
    2400                 :          0 :     const rtl::OUString aText(rArgs.mpStr+rArgs.mnMinCharPos, rArgs.mnEndCharPos-rArgs.mnMinCharPos);
    2401         [ #  # ]:          0 :     SetText( aText );
    2402                 :          0 :     SetUnitsPerPixel( 1000 );
    2403                 :            : 
    2404         [ #  # ]:          0 :     rtl_UnicodeToTextConverter aConv = rtl_createTextToUnicodeConverter( mrBuiltinFont.m_eCharSet );
    2405                 :            : 
    2406                 :          0 :     Point aNewPos( 0, 0 );
    2407                 :            :     bool bRightToLeft;
    2408         [ #  # ]:          0 :     Reserve(rArgs.mnLength);
    2409 [ #  # ][ #  # ]:          0 :     for( int nCharPos = -1; rArgs.GetNextPos( &nCharPos, &bRightToLeft ); )
    2410                 :            :     {
    2411                 :            :         // TODO: handle unicode surrogates
    2412                 :            :         // on the other hand the PDF builtin fonts don't support them anyway
    2413                 :          0 :         sal_Unicode cChar = rArgs.mpStr[ nCharPos ];
    2414         [ #  # ]:          0 :         if( bRightToLeft )
    2415         [ #  # ]:          0 :             cChar = static_cast<sal_Unicode>(GetMirroredChar( cChar ));
    2416                 :            : 
    2417                 :            :         sal_Char aBuf[4];
    2418                 :            :         sal_uInt32 nInfo;
    2419                 :            :         sal_Size nSrcCvtChars;
    2420                 :            : 
    2421                 :            :         sal_Size nConv = rtl_convertUnicodeToText( aConv,
    2422                 :            :                                                    NULL,
    2423                 :            :                                                    &cChar, 1,
    2424                 :            :                                                    aBuf, sizeof(aBuf)/sizeof(*aBuf),
    2425                 :            :                                                    RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR,
    2426         [ #  # ]:          0 :                                                    &nInfo, &nSrcCvtChars );
    2427                 :            :         // check whether conversion was possible
    2428                 :            :         // else fallback font is needed as the standard fonts
    2429                 :            :         // are handled via WinAnsi encoding
    2430         [ #  # ]:          0 :         if( nConv > 0 )
    2431                 :          0 :             cChar = ((sal_Unicode)aBuf[0]) & 0x00ff;
    2432                 :            : 
    2433         [ #  # ]:          0 :         if( cChar & 0xff00 )
    2434                 :            :         {
    2435                 :          0 :             cChar = 0;   // NotDef glyph
    2436         [ #  # ]:          0 :             rArgs.NeedFallback( nCharPos, bRightToLeft );
    2437                 :            :         }
    2438                 :            : 
    2439                 :          0 :         long nGlyphWidth = (long)mrBuiltinFont.m_aWidths[cChar] * mnPixelPerEM;
    2440                 :          0 :         long nGlyphFlags = 0; // builtin fonts don't have diacritic glyphs
    2441         [ #  # ]:          0 :         if( bRightToLeft )
    2442                 :          0 :             nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
    2443                 :            :         // TODO: get kerning from builtin fonts
    2444                 :          0 :         GlyphItem aGI( nCharPos, cChar, aNewPos, nGlyphFlags, nGlyphWidth );
    2445         [ #  # ]:          0 :         AppendGlyph( aGI );
    2446                 :            : 
    2447                 :          0 :         aNewPos.X() += nGlyphWidth;
    2448                 :            :     }
    2449                 :            : 
    2450         [ #  # ]:          0 :     rtl_destroyUnicodeToTextConverter( aConv );
    2451                 :            : 
    2452                 :          0 :     return true;
    2453                 :            : }
    2454                 :            : 
    2455                 :            : // -----------------------------------------------------------------------
    2456                 :            : 
    2457                 :          0 : void PDFSalLayout::InitFont() const
    2458                 :            : {
    2459                 :            :     // TODO: recreate font with all its attributes
    2460                 :          0 : }
    2461                 :            : 
    2462                 :            : // -----------------------------------------------------------------------
    2463                 :            : 
    2464                 :          0 : void PDFSalLayout::DrawText( SalGraphics& ) const
    2465                 :            : {
    2466                 :          0 :     mrPDFWriterImpl.drawLayout( *const_cast<PDFSalLayout*>(this), maOrigText, true );
    2467                 :          0 : }
    2468                 :            : 
    2469                 :            : // -----------------------------------------------------------------------
    2470                 :            : 
    2471                 :          0 : SalLayout* PDFWriterImpl::GetTextLayout( ImplLayoutArgs& rArgs, FontSelectPattern* pSelect )
    2472                 :            : {
    2473                 :            :     DBG_ASSERT( (pSelect->mpFontData != NULL),
    2474                 :            :         "PDFWriterImpl::GetTextLayout mpFontData is NULL" );
    2475                 :            : 
    2476                 :          0 :     const ImplPdfBuiltinFontData* pFD = GetPdfFontData( pSelect->mpFontData );
    2477         [ #  # ]:          0 :     if( !pFD )
    2478                 :          0 :         return NULL;
    2479                 :          0 :     const BuiltinFont* pBuiltinFont = pFD->GetBuiltinFont();
    2480                 :            : 
    2481         [ #  # ]:          0 :     long nPixelPerEM = pSelect->mnWidth ? pSelect->mnWidth : pSelect->mnHeight;
    2482                 :          0 :     int nOrientation = pSelect->mnOrientation;
    2483         [ #  # ]:          0 :     PDFSalLayout* pLayout = new PDFSalLayout( *this, *pBuiltinFont, nPixelPerEM, nOrientation );
    2484         [ #  # ]:          0 :     pLayout->SetText( rArgs.mpStr );
    2485                 :          0 :     return pLayout;
    2486                 :            : }
    2487                 :            : 
    2488                 :          0 : sal_Int32 PDFWriterImpl::newPage( sal_Int32 nPageWidth, sal_Int32 nPageHeight, PDFWriter::Orientation eOrientation )
    2489                 :            : {
    2490         [ #  # ]:          0 :     endPage();
    2491                 :          0 :     m_nCurrentPage = m_aPages.size();
    2492 [ #  # ][ #  # ]:          0 :     m_aPages.push_back( PDFPage(this, nPageWidth, nPageHeight, eOrientation ) );
    2493         [ #  # ]:          0 :     m_aPages.back().m_nPageIndex = m_nCurrentPage;
    2494 [ #  # ][ #  # ]:          0 :     m_aPages.back().beginStream();
    2495                 :            : 
    2496                 :            :     // setup global graphics state
    2497                 :            :     // linewidth is "1 pixel" by default
    2498                 :          0 :     OStringBuffer aBuf( 16 );
    2499 [ #  # ][ #  # ]:          0 :     appendDouble( 72.0/double(getReferenceDevice()->ImplGetDPIX()), aBuf );
    2500         [ #  # ]:          0 :     aBuf.append( " w\n" );
    2501         [ #  # ]:          0 :     writeBuffer( aBuf.getStr(), aBuf.getLength() );
    2502                 :            : 
    2503                 :          0 :     return m_nCurrentPage;
    2504                 :            : }
    2505                 :            : 
    2506                 :          0 : void PDFWriterImpl::endPage()
    2507                 :            : {
    2508 [ #  # ][ #  # ]:          0 :     if( m_aPages.begin() != m_aPages.end() )
    2509                 :            :     {
    2510                 :            :         // close eventual MC sequence
    2511         [ #  # ]:          0 :         endStructureElementMCSeq();
    2512                 :            : 
    2513                 :            :         // sanity check
    2514         [ #  # ]:          0 :         if( m_aOutputStreams.begin() != m_aOutputStreams.end() )
    2515                 :            :         {
    2516                 :            :             OSL_FAIL( "redirection across pages !!!" );
    2517                 :          0 :             m_aOutputStreams.clear(); // leak !
    2518         [ #  # ]:          0 :             m_aMapMode.SetOrigin( Point() );
    2519                 :            :         }
    2520                 :            : 
    2521                 :          0 :         m_aGraphicsStack.clear();
    2522 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.push_back( GraphicsState() );
                 [ #  # ]
    2523                 :            : 
    2524                 :            :         // this should pop the PDF graphics stack if necessary
    2525         [ #  # ]:          0 :         updateGraphicsState();
    2526                 :            : 
    2527 [ #  # ][ #  # ]:          0 :         m_aPages.back().endStream();
    2528                 :            : 
    2529                 :            :         // reset the default font
    2530         [ #  # ]:          0 :         Font aFont;
    2531 [ #  # ][ #  # ]:          0 :         aFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ) );
         [ #  # ][ #  # ]
    2532         [ #  # ]:          0 :         aFont.SetSize( Size( 0, 12 ) );
    2533                 :            : 
    2534 [ #  # ][ #  # ]:          0 :         m_aCurrentPDFState = m_aGraphicsStack.front();
    2535 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFont =  aFont;
    2536                 :            : 
    2537         [ #  # ]:          0 :         for( std::list<BitmapEmit>::iterator it = m_aBitmaps.begin();
    2538                 :          0 :              it != m_aBitmaps.end(); ++it )
    2539                 :            :         {
    2540 [ #  # ][ #  # ]:          0 :             if( ! it->m_aBitmap.IsEmpty() )
    2541                 :            :             {
    2542         [ #  # ]:          0 :                 writeBitmapObject( *it );
    2543 [ #  # ][ #  # ]:          0 :                 it->m_aBitmap = BitmapEx();
                 [ #  # ]
    2544                 :            :             }
    2545                 :            :         }
    2546         [ #  # ]:          0 :         for( std::list<JPGEmit>::iterator jpeg = m_aJPGs.begin(); jpeg != m_aJPGs.end(); ++jpeg )
    2547                 :            :         {
    2548         [ #  # ]:          0 :             if( jpeg->m_pStream )
    2549                 :            :             {
    2550         [ #  # ]:          0 :                 writeJPG( *jpeg );
    2551 [ #  # ][ #  # ]:          0 :                 delete jpeg->m_pStream;
    2552                 :          0 :                 jpeg->m_pStream = NULL;
    2553 [ #  # ][ #  # ]:          0 :                 jpeg->m_aMask = Bitmap();
                 [ #  # ]
    2554                 :            :             }
    2555                 :            :         }
    2556         [ #  # ]:          0 :         for( std::list<TransparencyEmit>::iterator t = m_aTransparentObjects.begin();
    2557                 :          0 :              t != m_aTransparentObjects.end(); ++t )
    2558                 :            :         {
    2559         [ #  # ]:          0 :             if( t->m_pContentStream )
    2560                 :            :             {
    2561         [ #  # ]:          0 :                 writeTransparentObject( *t );
    2562 [ #  # ][ #  # ]:          0 :                 delete t->m_pContentStream;
    2563                 :          0 :                 t->m_pContentStream = NULL;
    2564                 :            :             }
    2565         [ #  # ]:          0 :         }
    2566                 :            :     }
    2567                 :          0 : }
    2568                 :            : 
    2569                 :          0 : sal_Int32 PDFWriterImpl::createObject()
    2570                 :            : {
    2571         [ #  # ]:          0 :     m_aObjects.push_back( ~0U );
    2572                 :          0 :     return m_aObjects.size();
    2573                 :            : }
    2574                 :            : 
    2575                 :          0 : bool PDFWriterImpl::updateObject( sal_Int32 n )
    2576                 :            : {
    2577         [ #  # ]:          0 :     if( ! m_bOpen )
    2578                 :          0 :         return false;
    2579                 :            : 
    2580                 :          0 :     sal_uInt64 nOffset = ~0U;
    2581         [ #  # ]:          0 :     oslFileError aError = osl_getFilePos( m_aFile, &nOffset );
    2582                 :            :     DBG_ASSERT( aError == osl_File_E_None, "could not register object" );
    2583         [ #  # ]:          0 :     if( aError != osl_File_E_None )
    2584                 :            :     {
    2585         [ #  # ]:          0 :         osl_closeFile( m_aFile );
    2586                 :          0 :         m_bOpen = false;
    2587                 :            :     }
    2588         [ #  # ]:          0 :     m_aObjects[ n-1 ] = nOffset;
    2589                 :          0 :     return aError == osl_File_E_None;
    2590                 :            : }
    2591                 :            : 
    2592                 :            : #define CHECK_RETURN( x ) if( !(x) ) return 0
    2593                 :            : 
    2594                 :          0 : sal_Int32 PDFWriterImpl::emitStructParentTree( sal_Int32 nObject )
    2595                 :            : {
    2596         [ #  # ]:          0 :     if( nObject > 0 )
    2597                 :            :     {
    2598                 :          0 :         OStringBuffer aLine( 1024 );
    2599                 :            : 
    2600         [ #  # ]:          0 :         aLine.append( nObject );
    2601                 :            :         aLine.append( " 0 obj\n"
    2602         [ #  # ]:          0 :                       "<</Nums[\n" );
    2603                 :          0 :         sal_Int32 nTreeItems = m_aStructParentTree.size();
    2604         [ #  # ]:          0 :         for( sal_Int32 n = 0; n < nTreeItems; n++ )
    2605                 :            :         {
    2606         [ #  # ]:          0 :             aLine.append( n );
    2607         [ #  # ]:          0 :             aLine.append( ' ' );
    2608         [ #  # ]:          0 :             aLine.append( m_aStructParentTree[n] );
    2609         [ #  # ]:          0 :             aLine.append( "\n" );
    2610                 :            :         }
    2611         [ #  # ]:          0 :         aLine.append( "]>>\nendobj\n\n" );
    2612 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( updateObject( nObject ) );
    2613 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
                 [ #  # ]
    2614                 :            :     }
    2615                 :          0 :     return nObject;
    2616                 :            : }
    2617                 :            : 
    2618                 :          0 : const sal_Char* PDFWriterImpl::getAttributeTag( PDFWriter::StructAttribute eAttr )
    2619                 :            : {
    2620 [ #  # ][ #  # ]:          0 :     static std::map< PDFWriter::StructAttribute, const char* > aAttributeStrings;
         [ #  # ][ #  # ]
    2621                 :            :     // fill maps once
    2622         [ #  # ]:          0 :     if( aAttributeStrings.empty() )
    2623                 :            :     {
    2624         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::Placement ]           = "Placement";
    2625         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::WritingMode ]         = "WritingMode";
    2626         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::SpaceBefore ]         = "SpaceBefore";
    2627         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::SpaceAfter ]          = "SpaceAfter";
    2628         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::StartIndent ]         = "StartIndent";
    2629         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::EndIndent ]           = "EndIndent";
    2630         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::TextIndent ]          = "TextIndent";
    2631         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::TextAlign ]           = "TextAlign";
    2632         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::Width ]               = "Width";
    2633         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::Height ]              = "Height";
    2634         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::BlockAlign ]          = "BlockAlign";
    2635         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::InlineAlign ]         = "InlineAlign";
    2636         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::LineHeight ]          = "LineHeight";
    2637         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::BaselineShift ]       = "BaselineShift";
    2638         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::TextDecorationType ]  = "TextDecorationType";
    2639         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::ListNumbering ]       = "ListNumbering";
    2640         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::RowSpan ]             = "RowSpan";
    2641         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::ColSpan ]             = "ColSpan";
    2642         [ #  # ]:          0 :         aAttributeStrings[ PDFWriter::LinkAnnotation ]      = "LinkAnnotation";
    2643                 :            :     }
    2644                 :            : 
    2645                 :            :     std::map< PDFWriter::StructAttribute, const char* >::const_iterator it =
    2646 [ #  # ][ #  # ]:          0 :         aAttributeStrings.find( eAttr );
    2647                 :            : 
    2648                 :            : #if OSL_DEBUG_LEVEL > 1
    2649                 :            :     if( it == aAttributeStrings.end() )
    2650                 :            :         fprintf( stderr, "invalid PDFWriter::StructAttribute %d\n", eAttr );
    2651                 :            : #endif
    2652                 :            : 
    2653 [ #  # ][ #  # ]:          0 :     return it != aAttributeStrings.end() ? it->second : "";
         [ #  # ][ #  # ]
    2654                 :            : }
    2655                 :            : 
    2656                 :          0 : const sal_Char* PDFWriterImpl::getAttributeValueTag( PDFWriter::StructAttributeValue eVal )
    2657                 :            : {
    2658 [ #  # ][ #  # ]:          0 :     static std::map< PDFWriter::StructAttributeValue, const char* > aValueStrings;
         [ #  # ][ #  # ]
    2659                 :            : 
    2660         [ #  # ]:          0 :     if( aValueStrings.empty() )
    2661                 :            :     {
    2662         [ #  # ]:          0 :         aValueStrings[ PDFWriter::NONE ]                    = "None";
    2663         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Block ]                   = "Block";
    2664         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Inline ]                  = "Inline";
    2665         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Before ]                  = "Before";
    2666         [ #  # ]:          0 :         aValueStrings[ PDFWriter::After ]                   = "After";
    2667         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Start ]                   = "Start";
    2668         [ #  # ]:          0 :         aValueStrings[ PDFWriter::End ]                     = "End";
    2669         [ #  # ]:          0 :         aValueStrings[ PDFWriter::LrTb ]                    = "LrTb";
    2670         [ #  # ]:          0 :         aValueStrings[ PDFWriter::RlTb ]                    = "RlTb";
    2671         [ #  # ]:          0 :         aValueStrings[ PDFWriter::TbRl ]                    = "TbRl";
    2672         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Center ]                  = "Center";
    2673         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Justify ]                 = "Justify";
    2674         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Auto ]                    = "Auto";
    2675         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Middle ]                  = "Middle";
    2676         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Normal ]                  = "Normal";
    2677         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Underline ]               = "Underline";
    2678         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Overline ]                = "Overline";
    2679         [ #  # ]:          0 :         aValueStrings[ PDFWriter::LineThrough ]             = "LineThrough";
    2680         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Disc ]                    = "Disc";
    2681         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Circle ]                  = "Circle";
    2682         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Square ]                  = "Square";
    2683         [ #  # ]:          0 :         aValueStrings[ PDFWriter::Decimal ]                 = "Decimal";
    2684         [ #  # ]:          0 :         aValueStrings[ PDFWriter::UpperRoman ]              = "UpperRoman";
    2685         [ #  # ]:          0 :         aValueStrings[ PDFWriter::LowerRoman ]              = "LowerRoman";
    2686         [ #  # ]:          0 :         aValueStrings[ PDFWriter::UpperAlpha ]              = "UpperAlpha";
    2687         [ #  # ]:          0 :         aValueStrings[ PDFWriter::LowerAlpha ]              = "LowerAlpha";
    2688                 :            :     }
    2689                 :            : 
    2690                 :            :     std::map< PDFWriter::StructAttributeValue, const char* >::const_iterator it =
    2691 [ #  # ][ #  # ]:          0 :         aValueStrings.find( eVal );
    2692                 :            : 
    2693                 :            : #if OSL_DEBUG_LEVEL > 1
    2694                 :            :     if( it == aValueStrings.end() )
    2695                 :            :         fprintf( stderr, "invalid PDFWriter::StructAttributeValue %d\n", eVal );
    2696                 :            : #endif
    2697                 :            : 
    2698 [ #  # ][ #  # ]:          0 :     return it != aValueStrings.end() ? it->second : "";
         [ #  # ][ #  # ]
    2699                 :            : }
    2700                 :            : 
    2701                 :          0 : static void appendStructureAttributeLine( PDFWriter::StructAttribute i_eAttr, const PDFWriterImpl::PDFStructureAttribute& i_rVal, OStringBuffer& o_rLine, bool i_bIsFixedInt )
    2702                 :            : {
    2703                 :          0 :     o_rLine.append( "/" );
    2704         [ #  # ]:          0 :     o_rLine.append( PDFWriterImpl::getAttributeTag( i_eAttr ) );
    2705                 :            : 
    2706         [ #  # ]:          0 :     if( i_rVal.eValue != PDFWriter::Invalid )
    2707                 :            :     {
    2708                 :          0 :         o_rLine.append( "/" );
    2709         [ #  # ]:          0 :         o_rLine.append( PDFWriterImpl::getAttributeValueTag( i_rVal.eValue ) );
    2710                 :            :     }
    2711                 :            :     else
    2712                 :            :     {
    2713                 :            :         // numerical value
    2714                 :          0 :         o_rLine.append( " " );
    2715         [ #  # ]:          0 :         if( i_bIsFixedInt )
    2716                 :          0 :             appendFixedInt( i_rVal.nValue, o_rLine );
    2717                 :            :         else
    2718                 :          0 :             o_rLine.append( i_rVal.nValue );
    2719                 :            :     }
    2720                 :          0 :     o_rLine.append( "\n" );
    2721                 :          0 : }
    2722                 :            : 
    2723                 :          0 : OString PDFWriterImpl::emitStructureAttributes( PDFStructureElement& i_rEle )
    2724                 :            : {
    2725                 :            :     // create layout, list and table attribute sets
    2726                 :          0 :     OStringBuffer aLayout(256), aList(64), aTable(64);
    2727         [ #  # ]:          0 :     for( PDFStructAttributes::const_iterator it = i_rEle.m_aAttributes.begin();
    2728                 :          0 :          it != i_rEle.m_aAttributes.end(); ++it )
    2729                 :            :     {
    2730         [ #  # ]:          0 :         if( it->first == PDFWriter::ListNumbering )
    2731         [ #  # ]:          0 :             appendStructureAttributeLine( it->first, it->second, aList, true );
    2732   [ #  #  #  # ]:          0 :         else if( it->first == PDFWriter::RowSpan ||
                 [ #  # ]
    2733                 :          0 :                  it->first == PDFWriter::ColSpan )
    2734         [ #  # ]:          0 :             appendStructureAttributeLine( it->first, it->second, aTable, false );
    2735         [ #  # ]:          0 :         else if( it->first == PDFWriter::LinkAnnotation )
    2736                 :            :         {
    2737                 :          0 :             sal_Int32 nLink = it->second.nValue;
    2738                 :            :             std::map< sal_Int32, sal_Int32 >::const_iterator link_it =
    2739 [ #  # ][ #  # ]:          0 :                 m_aLinkPropertyMap.find( nLink );
    2740 [ #  # ][ #  # ]:          0 :             if( link_it != m_aLinkPropertyMap.end() )
                 [ #  # ]
    2741         [ #  # ]:          0 :                 nLink = link_it->second;
    2742 [ #  # ][ #  # ]:          0 :             if( nLink >= 0 && nLink < (sal_Int32)m_aLinks.size() )
                 [ #  # ]
    2743                 :            :             {
    2744                 :            :                 // update struct parent of link
    2745                 :          0 :                 OStringBuffer aStructParentEntry( 32 );
    2746         [ #  # ]:          0 :                 aStructParentEntry.append( i_rEle.m_nObject );
    2747         [ #  # ]:          0 :                 aStructParentEntry.append( " 0 R" );
    2748         [ #  # ]:          0 :                 m_aStructParentTree.push_back( aStructParentEntry.makeStringAndClear() );
    2749                 :          0 :                 m_aLinks[ nLink ].m_nStructParent = m_aStructParentTree.size()-1;
    2750                 :            : 
    2751         [ #  # ]:          0 :                 sal_Int32 nRefObject = createObject();
    2752                 :          0 :                 OStringBuffer aRef( 256 );
    2753         [ #  # ]:          0 :                 aRef.append( nRefObject );
    2754                 :            :                 aRef.append( " 0 obj\n"
    2755         [ #  # ]:          0 :                              "<</Type/OBJR/Obj " );
    2756         [ #  # ]:          0 :                 aRef.append( m_aLinks[ nLink ].m_nObject );
    2757                 :            :                 aRef.append( " 0 R>>\n"
    2758                 :            :                              "endobj\n\n"
    2759         [ #  # ]:          0 :                              );
    2760         [ #  # ]:          0 :                 updateObject( nRefObject );
    2761         [ #  # ]:          0 :                 writeBuffer( aRef.getStr(), aRef.getLength() );
    2762                 :            : 
    2763         [ #  # ]:          0 :                 i_rEle.m_aKids.push_back( PDFStructureElementKid( nRefObject ) );
    2764                 :            :             }
    2765                 :            :             else
    2766                 :            :             {
    2767                 :            :                 OSL_FAIL( "unresolved link id for Link structure" );
    2768                 :            : #if OSL_DEBUG_LEVEL > 1
    2769                 :            :                 fprintf( stderr, "unresolved link id %" SAL_PRIdINT32 " for Link structure\n", nLink );
    2770                 :            :                 {
    2771                 :            :                     OStringBuffer aLine( "unresolved link id " );
    2772                 :            :                     aLine.append( nLink );
    2773                 :            :                     aLine.append( " for Link structure" );
    2774                 :            :                     emitComment( aLine.getStr() );
    2775                 :            :                 }
    2776                 :            : #endif
    2777                 :            :             }
    2778                 :            :         }
    2779                 :            :         else
    2780         [ #  # ]:          0 :             appendStructureAttributeLine( it->first, it->second, aLayout, true );
    2781                 :            :     }
    2782 [ #  # ][ #  # ]:          0 :     if( ! i_rEle.m_aBBox.IsEmpty() )
    2783                 :            :     {
    2784         [ #  # ]:          0 :         aLayout.append( "/BBox[" );
    2785         [ #  # ]:          0 :         appendFixedInt( i_rEle.m_aBBox.Left(), aLayout );
    2786         [ #  # ]:          0 :         aLayout.append( " " );
    2787         [ #  # ]:          0 :         appendFixedInt( i_rEle.m_aBBox.Top(), aLayout );
    2788         [ #  # ]:          0 :         aLayout.append( " " );
    2789         [ #  # ]:          0 :         appendFixedInt( i_rEle.m_aBBox.Right(), aLayout );
    2790         [ #  # ]:          0 :         aLayout.append( " " );
    2791         [ #  # ]:          0 :         appendFixedInt( i_rEle.m_aBBox.Bottom(), aLayout );
    2792         [ #  # ]:          0 :         aLayout.append( "]\n" );
    2793                 :            :     }
    2794                 :            : 
    2795         [ #  # ]:          0 :     std::vector< sal_Int32 > aAttribObjects;
    2796         [ #  # ]:          0 :     if( aLayout.getLength() )
    2797                 :            :     {
    2798 [ #  # ][ #  # ]:          0 :         aAttribObjects.push_back( createObject() );
    2799 [ #  # ][ #  # ]:          0 :         updateObject( aAttribObjects.back() );
    2800                 :          0 :         OStringBuffer aObj( 64 );
    2801 [ #  # ][ #  # ]:          0 :         aObj.append( aAttribObjects.back() );
    2802                 :            :         aObj.append( " 0 obj\n"
    2803         [ #  # ]:          0 :                      "<</O/Layout\n" );
    2804         [ #  # ]:          0 :         aLayout.append( ">>\nendobj\n\n" );
    2805         [ #  # ]:          0 :         writeBuffer( aObj.getStr(), aObj.getLength() );
    2806         [ #  # ]:          0 :         writeBuffer( aLayout.getStr(), aLayout.getLength() );
    2807                 :            :     }
    2808         [ #  # ]:          0 :     if( aList.getLength() )
    2809                 :            :     {
    2810 [ #  # ][ #  # ]:          0 :         aAttribObjects.push_back( createObject() );
    2811 [ #  # ][ #  # ]:          0 :         updateObject( aAttribObjects.back() );
    2812                 :          0 :         OStringBuffer aObj( 64 );
    2813 [ #  # ][ #  # ]:          0 :         aObj.append( aAttribObjects.back() );
    2814                 :            :         aObj.append( " 0 obj\n"
    2815         [ #  # ]:          0 :                      "<</O/List\n" );
    2816         [ #  # ]:          0 :         aList.append( ">>\nendobj\n\n" );
    2817         [ #  # ]:          0 :         writeBuffer( aObj.getStr(), aObj.getLength() );
    2818         [ #  # ]:          0 :         writeBuffer( aList.getStr(), aList.getLength() );
    2819                 :            :     }
    2820         [ #  # ]:          0 :     if( aTable.getLength() )
    2821                 :            :     {
    2822 [ #  # ][ #  # ]:          0 :         aAttribObjects.push_back( createObject() );
    2823 [ #  # ][ #  # ]:          0 :         updateObject( aAttribObjects.back() );
    2824                 :          0 :         OStringBuffer aObj( 64 );
    2825 [ #  # ][ #  # ]:          0 :         aObj.append( aAttribObjects.back() );
    2826                 :            :         aObj.append( " 0 obj\n"
    2827         [ #  # ]:          0 :                      "<</O/Table\n" );
    2828         [ #  # ]:          0 :         aTable.append( ">>\nendobj\n\n" );
    2829         [ #  # ]:          0 :         writeBuffer( aObj.getStr(), aObj.getLength() );
    2830         [ #  # ]:          0 :         writeBuffer( aTable.getStr(), aTable.getLength() );
    2831                 :            :     }
    2832                 :            : 
    2833                 :          0 :     OStringBuffer aRet( 64 );
    2834         [ #  # ]:          0 :     if( aAttribObjects.size() > 1 )
    2835         [ #  # ]:          0 :         aRet.append( " [" );
    2836         [ #  # ]:          0 :     for( std::vector< sal_Int32 >::const_iterator at_it = aAttribObjects.begin();
           [ #  #  #  # ]
                 [ #  # ]
    2837                 :          0 :          at_it != aAttribObjects.end(); ++at_it )
    2838                 :            :     {
    2839         [ #  # ]:          0 :         aRet.append( " " );
    2840 [ #  # ][ #  # ]:          0 :         aRet.append( *at_it );
    2841         [ #  # ]:          0 :         aRet.append( " 0 R" );
    2842                 :            :     }
    2843         [ #  # ]:          0 :     if( aAttribObjects.size() > 1 )
    2844         [ #  # ]:          0 :         aRet.append( " ]" );
    2845                 :          0 :     return aRet.makeStringAndClear();
    2846                 :            : }
    2847                 :            : 
    2848                 :          0 : sal_Int32 PDFWriterImpl::emitStructure( PDFStructureElement& rEle )
    2849                 :            : {
    2850 [ #  # ][ #  # ]:          0 :     if(
    2851                 :            :        // do not emit NonStruct and its children
    2852                 :            :        rEle.m_eType == PDFWriter::NonStructElement &&
    2853                 :            :        rEle.m_nOwnElement != rEle.m_nParentElement // but of course emit the struct tree root
    2854                 :            :        )
    2855                 :          0 :         return 0;
    2856                 :            : 
    2857 [ #  # ][ #  # ]:          0 :     for( std::list< sal_Int32 >::const_iterator it = rEle.m_aChildren.begin(); it != rEle.m_aChildren.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
    2858                 :            :     {
    2859 [ #  # ][ #  # ]:          0 :         if( *it > 0 && *it < sal_Int32(m_aStructure.size()) )
         [ #  # ][ #  # ]
                 [ #  # ]
    2860                 :            :         {
    2861         [ #  # ]:          0 :             PDFStructureElement& rChild = m_aStructure[ *it ];
    2862         [ #  # ]:          0 :             if( rChild.m_eType != PDFWriter::NonStructElement )
    2863                 :            :             {
    2864         [ #  # ]:          0 :                 if( rChild.m_nParentElement == rEle.m_nOwnElement )
    2865         [ #  # ]:          0 :                     emitStructure( rChild );
    2866                 :            :                 else
    2867                 :            :                 {
    2868                 :            :                     OSL_FAIL( "PDFWriterImpl::emitStructure: invalid child structure element" );
    2869                 :            : #if OSL_DEBUG_LEVEL > 1
    2870                 :            :                     fprintf( stderr, "PDFWriterImpl::emitStructure: invalid child structure elemnt with id %" SAL_PRIdINT32 "\n", *it );
    2871                 :            : #endif
    2872                 :            :                 }
    2873                 :            :             }
    2874                 :            :         }
    2875                 :            :         else
    2876                 :            :         {
    2877                 :            :             OSL_FAIL( "PDFWriterImpl::emitStructure: invalid child structure id" );
    2878                 :            : #if OSL_DEBUG_LEVEL > 1
    2879                 :            :             fprintf( stderr, "PDFWriterImpl::emitStructure: invalid child structure id %" SAL_PRIdINT32 "\n", *it );
    2880                 :            : #endif
    2881                 :            :         }
    2882                 :            :     }
    2883                 :            : 
    2884                 :          0 :     OStringBuffer aLine( 512 );
    2885         [ #  # ]:          0 :     aLine.append( rEle.m_nObject );
    2886                 :            :     aLine.append( " 0 obj\n"
    2887         [ #  # ]:          0 :                   "<</Type" );
    2888                 :          0 :     sal_Int32 nParentTree = -1;
    2889         [ #  # ]:          0 :     if( rEle.m_nOwnElement == rEle.m_nParentElement )
    2890                 :            :     {
    2891         [ #  # ]:          0 :         nParentTree = createObject();
    2892         [ #  # ]:          0 :         CHECK_RETURN( nParentTree );
    2893         [ #  # ]:          0 :         aLine.append( "/StructTreeRoot\n" );
    2894         [ #  # ]:          0 :         aLine.append( "/ParentTree " );
    2895         [ #  # ]:          0 :         aLine.append( nParentTree );
    2896         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    2897         [ #  # ]:          0 :         if( ! m_aRoleMap.empty() )
    2898                 :            :         {
    2899         [ #  # ]:          0 :             aLine.append( "/RoleMap<<" );
    2900         [ #  # ]:          0 :             for( boost::unordered_map<OString,OString,OStringHash>::const_iterator
    2901 [ #  # ][ #  # ]:          0 :                  it = m_aRoleMap.begin(); it != m_aRoleMap.end(); ++it )
    2902                 :            :             {
    2903         [ #  # ]:          0 :                 aLine.append( '/' );
    2904 [ #  # ][ #  # ]:          0 :                 aLine.append(it->first);
    2905         [ #  # ]:          0 :                 aLine.append( '/' );
    2906 [ #  # ][ #  # ]:          0 :                 aLine.append( it->second );
    2907         [ #  # ]:          0 :                 aLine.append( '\n' );
    2908                 :            :             }
    2909         [ #  # ]:          0 :             aLine.append( ">>\n" );
    2910                 :            :         }
    2911                 :            :     }
    2912                 :            :     else
    2913                 :            :     {
    2914                 :            :         aLine.append( "/StructElem\n"
    2915         [ #  # ]:          0 :                       "/S/" );
    2916         [ #  # ]:          0 :         if( !rEle.m_aAlias.isEmpty() )
    2917         [ #  # ]:          0 :             aLine.append( rEle.m_aAlias );
    2918                 :            :         else
    2919 [ #  # ][ #  # ]:          0 :             aLine.append( getStructureTag( rEle.m_eType ) );
    2920                 :            :         aLine.append( "\n"
    2921         [ #  # ]:          0 :                       "/P " );
    2922         [ #  # ]:          0 :         aLine.append( m_aStructure[ rEle.m_nParentElement ].m_nObject );
    2923                 :            :         aLine.append( " 0 R\n"
    2924         [ #  # ]:          0 :                       "/Pg " );
    2925         [ #  # ]:          0 :         aLine.append( rEle.m_nFirstPageObject );
    2926         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    2927         [ #  # ]:          0 :         if( !rEle.m_aActualText.isEmpty() )
    2928                 :            :         {
    2929         [ #  # ]:          0 :             aLine.append( "/ActualText" );
    2930         [ #  # ]:          0 :             appendUnicodeTextStringEncrypt( rEle.m_aActualText, rEle.m_nObject, aLine );
    2931         [ #  # ]:          0 :             aLine.append( "\n" );
    2932                 :            :         }
    2933         [ #  # ]:          0 :         if( !rEle.m_aAltText.isEmpty() )
    2934                 :            :         {
    2935         [ #  # ]:          0 :             aLine.append( "/Alt" );
    2936         [ #  # ]:          0 :             appendUnicodeTextStringEncrypt( rEle.m_aAltText, rEle.m_nObject, aLine );
    2937         [ #  # ]:          0 :             aLine.append( "\n" );
    2938                 :            :         }
    2939                 :            :     }
    2940 [ #  # ][ #  # ]:          0 :     if( ! rEle.m_aBBox.IsEmpty() || rEle.m_aAttributes.size() )
         [ #  # ][ #  # ]
    2941                 :            :     {
    2942         [ #  # ]:          0 :         OString aAttribs =  emitStructureAttributes( rEle );
    2943         [ #  # ]:          0 :         if( !aAttribs.isEmpty() )
    2944                 :            :         {
    2945         [ #  # ]:          0 :             aLine.append( "/A" );
    2946         [ #  # ]:          0 :             aLine.append( aAttribs );
    2947         [ #  # ]:          0 :             aLine.append( "\n" );
    2948                 :          0 :         }
    2949                 :            :     }
    2950         [ #  # ]:          0 :     if( !rEle.m_aLocale.Language.isEmpty() )
    2951                 :            :     {
    2952                 :          0 :         OUStringBuffer aLocBuf( 16 );
    2953         [ #  # ]:          0 :         aLocBuf.append( rEle.m_aLocale.Language.toAsciiLowerCase() );
    2954         [ #  # ]:          0 :         if( !rEle.m_aLocale.Country.isEmpty() )
    2955                 :            :         {
    2956         [ #  # ]:          0 :             aLocBuf.append( sal_Unicode('-') );
    2957         [ #  # ]:          0 :             aLocBuf.append( rEle.m_aLocale.Country );
    2958                 :            :         }
    2959         [ #  # ]:          0 :         aLine.append( "/Lang" );
    2960 [ #  # ][ #  # ]:          0 :         appendLiteralStringEncrypt( aLocBuf.makeStringAndClear(), rEle.m_nObject, aLine );
    2961         [ #  # ]:          0 :         aLine.append( "\n" );
    2962                 :            :     }
    2963         [ #  # ]:          0 :     if( ! rEle.m_aKids.empty() )
    2964                 :            :     {
    2965                 :          0 :         unsigned int i = 0;
    2966         [ #  # ]:          0 :         aLine.append( "/K[" );
    2967         [ #  # ]:          0 :         for( std::list< PDFStructureElementKid >::const_iterator it =
    2968                 :          0 :                  rEle.m_aKids.begin(); it != rEle.m_aKids.end(); ++it, i++ )
    2969                 :            :         {
    2970         [ #  # ]:          0 :             if( it->nMCID == -1 )
    2971                 :            :             {
    2972         [ #  # ]:          0 :                 aLine.append( it->nObject );
    2973         [ #  # ]:          0 :                 aLine.append( " 0 R" );
    2974 [ #  # ][ #  # ]:          0 :                 aLine.append( ( (i & 15) == 15 ) ? "\n" : " " );
    2975                 :            :             }
    2976                 :            :             else
    2977                 :            :             {
    2978         [ #  # ]:          0 :                 if( it->nObject == rEle.m_nFirstPageObject )
    2979                 :            :                 {
    2980         [ #  # ]:          0 :                     aLine.append( it->nMCID );
    2981         [ #  # ]:          0 :                     aLine.append( " " );
    2982                 :            :                 }
    2983                 :            :                 else
    2984                 :            :                 {
    2985         [ #  # ]:          0 :                     aLine.append( "<</Type/MCR/Pg " );
    2986         [ #  # ]:          0 :                     aLine.append( it->nObject );
    2987         [ #  # ]:          0 :                     aLine.append( " 0 R /MCID " );
    2988         [ #  # ]:          0 :                     aLine.append( it->nMCID );
    2989         [ #  # ]:          0 :                     aLine.append( ">>\n" );
    2990                 :            :                 }
    2991                 :            :             }
    2992                 :            :         }
    2993         [ #  # ]:          0 :         aLine.append( "]\n" );
    2994                 :            :     }
    2995         [ #  # ]:          0 :     aLine.append( ">>\nendobj\n\n" );
    2996                 :            : 
    2997 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rEle.m_nObject ) );
    2998 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    2999                 :            : 
    3000 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( emitStructParentTree( nParentTree ) );
    3001                 :            : 
    3002                 :          0 :     return rEle.m_nObject;
    3003                 :            : }
    3004                 :            : 
    3005                 :          0 : bool PDFWriterImpl::emitGradients()
    3006                 :            : {
    3007         [ #  # ]:          0 :     for( std::list<GradientEmit>::iterator it = m_aGradients.begin();
    3008                 :          0 :          it != m_aGradients.end(); ++it )
    3009                 :            :     {
    3010 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeGradientFunction( *it ) );
    3011                 :            :     }
    3012                 :          0 :     return true;
    3013                 :            : }
    3014                 :            : 
    3015                 :          0 : bool PDFWriterImpl::emitTilings()
    3016                 :            : {
    3017                 :          0 :     OStringBuffer aTilingObj( 1024 );
    3018                 :            : 
    3019 [ #  # ][ #  # ]:          0 :     for( std::vector<TilingEmit>::iterator it = m_aTilings.begin(); it != m_aTilings.end(); ++it )
    3020                 :            :     {
    3021                 :            :         DBG_ASSERT( it->m_pTilingStream, "tiling without stream" );
    3022         [ #  # ]:          0 :         if( ! it->m_pTilingStream )
    3023                 :          0 :             continue;
    3024                 :            : 
    3025         [ #  # ]:          0 :         aTilingObj.setLength( 0 );
    3026                 :            : 
    3027                 :            :         #if OSL_DEBUG_LEVEL > 1
    3028                 :            :         emitComment( "PDFWriterImpl::emitTilings" );
    3029                 :            :         #endif
    3030                 :            : 
    3031                 :          0 :         sal_Int32 nX = (sal_Int32)it->m_aRectangle.Left();
    3032                 :          0 :         sal_Int32 nY = (sal_Int32)it->m_aRectangle.Top();
    3033         [ #  # ]:          0 :         sal_Int32 nW = (sal_Int32)it->m_aRectangle.GetWidth();
    3034         [ #  # ]:          0 :         sal_Int32 nH = (sal_Int32)it->m_aRectangle.GetHeight();
    3035         [ #  # ]:          0 :         if( it->m_aCellSize.Width() == 0 )
    3036                 :          0 :             it->m_aCellSize.Width() = nW;
    3037         [ #  # ]:          0 :         if( it->m_aCellSize.Height() == 0 )
    3038                 :          0 :             it->m_aCellSize.Height() = nH;
    3039                 :            : 
    3040         [ #  # ]:          0 :         bool bDeflate = compressStream( it->m_pTilingStream );
    3041         [ #  # ]:          0 :         it->m_pTilingStream->Seek( STREAM_SEEK_TO_END );
    3042                 :          0 :         sal_Size nTilingStreamSize = it->m_pTilingStream->Tell();
    3043         [ #  # ]:          0 :         it->m_pTilingStream->Seek( STREAM_SEEK_TO_BEGIN );
    3044                 :            : 
    3045                 :            :         // write pattern object
    3046         [ #  # ]:          0 :         aTilingObj.append( it->m_nObject );
    3047         [ #  # ]:          0 :         aTilingObj.append( " 0 obj\n" );
    3048                 :            :         aTilingObj.append( "<</Type/Pattern/PatternType 1\n"
    3049                 :            :                            "/PaintType 1\n"
    3050                 :            :                            "/TilingType 2\n"
    3051         [ #  # ]:          0 :                            "/BBox[" );
    3052         [ #  # ]:          0 :         appendFixedInt( nX, aTilingObj );
    3053         [ #  # ]:          0 :         aTilingObj.append( ' ' );
    3054         [ #  # ]:          0 :         appendFixedInt( nY, aTilingObj );
    3055         [ #  # ]:          0 :         aTilingObj.append( ' ' );
    3056         [ #  # ]:          0 :         appendFixedInt( nX+nW, aTilingObj );
    3057         [ #  # ]:          0 :         aTilingObj.append( ' ' );
    3058         [ #  # ]:          0 :         appendFixedInt( nY+nH, aTilingObj );
    3059                 :            :         aTilingObj.append( "]\n"
    3060         [ #  # ]:          0 :                            "/XStep " );
    3061         [ #  # ]:          0 :         appendFixedInt( it->m_aCellSize.Width(), aTilingObj );
    3062                 :            :         aTilingObj.append( "\n"
    3063         [ #  # ]:          0 :                            "/YStep " );
    3064         [ #  # ]:          0 :         appendFixedInt( it->m_aCellSize.Height(), aTilingObj );
    3065         [ #  # ]:          0 :         aTilingObj.append( "\n" );
    3066   [ #  #  #  #  :          0 :         if( it->m_aTransform.matrix[0] != 1.0 ||
          #  #  #  #  #  
                #  #  # ]
                 [ #  # ]
    3067                 :          0 :             it->m_aTransform.matrix[1] != 0.0 ||
    3068                 :          0 :             it->m_aTransform.matrix[3] != 0.0 ||
    3069                 :          0 :             it->m_aTransform.matrix[4] != 1.0 ||
    3070                 :          0 :             it->m_aTransform.matrix[2] != 0.0 ||
    3071                 :          0 :             it->m_aTransform.matrix[5] != 0.0 )
    3072                 :            :         {
    3073         [ #  # ]:          0 :             aTilingObj.append( "/Matrix [" );
    3074                 :            :             // TODO: scaling, mirroring on y, etc
    3075         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[0], aTilingObj );
    3076         [ #  # ]:          0 :             aTilingObj.append( ' ' );
    3077         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[1], aTilingObj );
    3078         [ #  # ]:          0 :             aTilingObj.append( ' ' );
    3079         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[3], aTilingObj );
    3080         [ #  # ]:          0 :             aTilingObj.append( ' ' );
    3081         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[4], aTilingObj );
    3082         [ #  # ]:          0 :             aTilingObj.append( ' ' );
    3083         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[2], aTilingObj );
    3084         [ #  # ]:          0 :             aTilingObj.append( ' ' );
    3085         [ #  # ]:          0 :             appendDouble( it->m_aTransform.matrix[5], aTilingObj );
    3086         [ #  # ]:          0 :             aTilingObj.append( "]\n" );
    3087                 :            :         }
    3088         [ #  # ]:          0 :         aTilingObj.append( "/Resources" );
    3089 [ #  # ][ #  # ]:          0 :         it->m_aResources.append( aTilingObj, getFontDictObject() );
    3090         [ #  # ]:          0 :         if( bDeflate )
    3091         [ #  # ]:          0 :             aTilingObj.append( "/Filter/FlateDecode" );
    3092         [ #  # ]:          0 :         aTilingObj.append( "/Length " );
    3093         [ #  # ]:          0 :         aTilingObj.append( (sal_Int32)nTilingStreamSize );
    3094         [ #  # ]:          0 :         aTilingObj.append( ">>\nstream\n" );
    3095 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( updateObject( it->m_nObject ) );
    3096 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) );
    3097         [ #  # ]:          0 :         checkAndEnableStreamEncryption( it->m_nObject );
    3098 [ #  # ][ #  # ]:          0 :         nTilingStreamSize = writeBuffer( it->m_pTilingStream->GetData(), nTilingStreamSize );
    3099 [ #  # ][ #  # ]:          0 :         delete it->m_pTilingStream;
    3100                 :          0 :         it->m_pTilingStream = NULL;
    3101         [ #  # ]:          0 :         if( nTilingStreamSize == 0 )
    3102                 :          0 :             return false;
    3103                 :          0 :         disableStreamEncryption();
    3104         [ #  # ]:          0 :         aTilingObj.setLength( 0 );
    3105         [ #  # ]:          0 :         aTilingObj.append( "\nendstream\nendobj\n\n" );
    3106 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aTilingObj.getStr(), aTilingObj.getLength() ) );
    3107                 :            :     }
    3108                 :          0 :     return true;
    3109                 :            : }
    3110                 :            : 
    3111                 :          0 : sal_Int32 PDFWriterImpl::emitBuiltinFont( const PhysicalFontFace* pFont, sal_Int32 nFontObject )
    3112                 :            : {
    3113                 :          0 :     const ImplPdfBuiltinFontData* pFD = GetPdfFontData( pFont );
    3114         [ #  # ]:          0 :     if( !pFD )
    3115                 :          0 :         return 0;
    3116                 :          0 :     const BuiltinFont* pBuiltinFont = pFD->GetBuiltinFont();
    3117                 :            : 
    3118                 :          0 :     OStringBuffer aLine( 1024 );
    3119                 :            : 
    3120         [ #  # ]:          0 :     if( nFontObject <= 0 )
    3121         [ #  # ]:          0 :         nFontObject = createObject();
    3122 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nFontObject ) );
    3123         [ #  # ]:          0 :     aLine.append( nFontObject );
    3124                 :            :     aLine.append( " 0 obj\n"
    3125         [ #  # ]:          0 :                   "<</Type/Font/Subtype/Type1/BaseFont/" );
    3126         [ #  # ]:          0 :     appendName( pBuiltinFont->m_pPSName, aLine );
    3127         [ #  # ]:          0 :     aLine.append( "\n" );
    3128         [ #  # ]:          0 :     if( pBuiltinFont->m_eCharSet == RTL_TEXTENCODING_MS_1252 )
    3129         [ #  # ]:          0 :          aLine.append( "/Encoding/WinAnsiEncoding\n" );
    3130         [ #  # ]:          0 :     aLine.append( ">>\nendobj\n\n" );
    3131 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    3132                 :          0 :     return nFontObject;
    3133                 :            : }
    3134                 :            : 
    3135                 :          0 : std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitSystemFont( const PhysicalFontFace* pFont, EmbedFont& rEmbed )
    3136                 :            : {
    3137         [ #  # ]:          0 :     std::map< sal_Int32, sal_Int32 > aRet;
    3138         [ #  # ]:          0 :     if( isBuiltinFont( pFont ) )
    3139                 :            :     {
    3140 [ #  # ][ #  # ]:          0 :         aRet[ rEmbed.m_nNormalFontID ] = emitBuiltinFont( pFont );
    3141                 :            :         return aRet;
    3142                 :            :     }
    3143                 :            : 
    3144                 :          0 :     sal_Int32 nFontDescriptor = 0;
    3145                 :          0 :     rtl::OString aSubType( "/Type1" );
    3146         [ #  # ]:          0 :     FontSubsetInfo aInfo;
    3147                 :            :     // fill in dummy values
    3148                 :          0 :     aInfo.m_nAscent = 1000;
    3149                 :          0 :     aInfo.m_nDescent = 200;
    3150                 :          0 :     aInfo.m_nCapHeight = 1000;
    3151         [ #  # ]:          0 :     aInfo.m_aFontBBox = Rectangle( Point( -200, -200 ), Size( 1700, 1700 ) );
    3152         [ #  # ]:          0 :     aInfo.m_aPSName = pFont->maName;
    3153                 :            :     sal_Int32 pWidths[256];
    3154                 :          0 :     memset( pWidths, 0, sizeof(pWidths) );
    3155         [ #  # ]:          0 :     if( pFont->IsEmbeddable() )
    3156                 :            :     {
    3157                 :          0 :         const unsigned char* pFontData = NULL;
    3158                 :          0 :         long nFontLen = 0;
    3159                 :            :         sal_Ucs nEncodedCodes[256];
    3160                 :            :         sal_Int32 pEncWidths[256];
    3161 [ #  # ][ #  # ]:          0 :         if( (pFontData = (const unsigned char*)m_pReferenceDevice->mpGraphics->GetEmbedFontData( pFont, nEncodedCodes, pEncWidths, aInfo, &nFontLen )) != NULL )
    3162                 :            :         {
    3163         [ #  # ]:          0 :             m_pReferenceDevice->mpGraphics->FreeEmbedFontData( pFontData, nFontLen );
    3164         [ #  # ]:          0 :             for( int i = 0; i < 256; i++ )
    3165                 :            :             {
    3166 [ #  # ][ #  # ]:          0 :                 if( nEncodedCodes[i] >= 32 && nEncodedCodes[i] < 256 )
    3167                 :            :                 {
    3168                 :          0 :                     pWidths[i] = pEncWidths[ i ];
    3169                 :            :                 }
    3170                 :            :             }
    3171                 :            :         }
    3172                 :            :     }
    3173         [ #  # ]:          0 :     else if( pFont->mbSubsettable )
    3174                 :            :     {
    3175                 :          0 :         aSubType = rtl::OString( "/TrueType" );
    3176         [ #  # ]:          0 :         Int32Vector aGlyphWidths;
    3177         [ #  # ]:          0 :         Ucs2UIntMap aUnicodeMap;
    3178         [ #  # ]:          0 :         m_pReferenceDevice->mpGraphics->GetGlyphWidths( pFont, false, aGlyphWidths, aUnicodeMap );
    3179                 :            : 
    3180                 :          0 :         OUString aTmpName;
    3181         [ #  # ]:          0 :         osl_createTempFile( NULL, NULL, &aTmpName.pData );
    3182                 :            :         sal_Int32 pGlyphIDs[ 256 ];
    3183                 :            :         sal_uInt8 pEncoding[ 256 ];
    3184                 :            :         sal_Ucs   pUnicodes[ 256 ];
    3185                 :            :         sal_Int32 pDuWidths[ 256 ];
    3186                 :            : 
    3187                 :          0 :         memset( pGlyphIDs, 0, sizeof( pGlyphIDs ) );
    3188                 :          0 :         memset( pEncoding, 0, sizeof( pEncoding ) );
    3189                 :          0 :         memset( pUnicodes, 0, sizeof( pUnicodes ) );
    3190                 :          0 :         memset( pDuWidths, 0, sizeof( pDuWidths ) );
    3191                 :            : 
    3192         [ #  # ]:          0 :         for( sal_Ucs c = 32; c < 256; c++ )
    3193                 :            :         {
    3194                 :          0 :             pUnicodes[c] = c;
    3195                 :          0 :             pEncoding[c] = c;
    3196                 :          0 :             pGlyphIDs[c] = 0;
    3197 [ #  # ][ #  # ]:          0 :             if( aUnicodeMap.find( c ) != aUnicodeMap.end() )
                 [ #  # ]
    3198 [ #  # ][ #  # ]:          0 :                 pWidths[ c ] = aGlyphWidths[ aUnicodeMap[ c ] ];
    3199                 :            :         }
    3200                 :            : 
    3201         [ #  # ]:          0 :         m_pReferenceDevice->mpGraphics->CreateFontSubset( aTmpName, pFont, pGlyphIDs, pEncoding, pDuWidths, 256, aInfo );
    3202         [ #  # ]:          0 :         osl_removeFile( aTmpName.pData );
    3203                 :            :     }
    3204                 :            :     else
    3205                 :            :     {
    3206                 :            :         OSL_FAIL( "system font neither embeddable nor subsettable" );
    3207                 :            :     }
    3208                 :            : 
    3209                 :            :     // write font descriptor
    3210         [ #  # ]:          0 :     nFontDescriptor = emitFontDescriptor( pFont, aInfo, 0, 0 );
    3211         [ #  # ]:          0 :     if( nFontDescriptor )
    3212                 :            :     {
    3213                 :            :         // write font object
    3214         [ #  # ]:          0 :         sal_Int32 nObject = createObject();
    3215 [ #  # ][ #  # ]:          0 :         if( updateObject( nObject ) )
    3216                 :            :         {
    3217                 :          0 :             OStringBuffer aLine( 1024 );
    3218         [ #  # ]:          0 :             aLine.append( nObject );
    3219                 :            :             aLine.append( " 0 obj\n"
    3220         [ #  # ]:          0 :                           "<</Type/Font/Subtype" );
    3221         [ #  # ]:          0 :             aLine.append( aSubType );
    3222         [ #  # ]:          0 :             aLine.append( "/BaseFont/" );
    3223 [ #  # ][ #  # ]:          0 :             appendName( aInfo.m_aPSName, aLine );
    3224         [ #  # ]:          0 :             aLine.append( "\n" );
    3225         [ #  # ]:          0 :             if( !pFont->mbSymbolFlag )
    3226         [ #  # ]:          0 :                 aLine.append( "/Encoding/WinAnsiEncoding\n" );
    3227                 :            :             aLine.append( "/FirstChar 32 /LastChar 255\n"
    3228         [ #  # ]:          0 :                           "/Widths[" );
    3229         [ #  # ]:          0 :             for( int i = 32; i < 256; i++ )
    3230                 :            :             {
    3231         [ #  # ]:          0 :                 aLine.append( pWidths[i] );
    3232 [ #  # ][ #  # ]:          0 :                 aLine.append( ((i&15) == 15) ? "\n" : " " );
    3233                 :            :             }
    3234                 :            :             aLine.append( "]\n"
    3235         [ #  # ]:          0 :                           "/FontDescriptor " );
    3236         [ #  # ]:          0 :             aLine.append( nFontDescriptor );
    3237                 :            :             aLine.append( " 0 R>>\n"
    3238         [ #  # ]:          0 :                           "endobj\n\n" );
    3239         [ #  # ]:          0 :             writeBuffer( aLine.getStr(), aLine.getLength() );
    3240                 :            : 
    3241         [ #  # ]:          0 :             aRet[ rEmbed.m_nNormalFontID ] = nObject;
    3242                 :            :         }
    3243                 :            :     }
    3244                 :            : 
    3245         [ #  # ]:          0 :     return aRet;
    3246                 :            : }
    3247                 :            : 
    3248                 :            : typedef int ThreeInts[3];
    3249                 :          0 : static bool getPfbSegmentLengths( const unsigned char* pFontBytes, int nByteLen,
    3250                 :            :     ThreeInts& rSegmentLengths )
    3251                 :            : {
    3252 [ #  # ][ #  # ]:          0 :     if( !pFontBytes || (nByteLen < 0) )
    3253                 :          0 :         return false;
    3254                 :          0 :     const unsigned char* pPtr = pFontBytes;
    3255                 :          0 :     const unsigned char* pEnd = pFontBytes + nByteLen;
    3256                 :            : 
    3257         [ #  # ]:          0 :     for( int i = 0; i < 3; ++i) {
    3258                 :            :         // read segment1 header
    3259         [ #  # ]:          0 :         if( pPtr+6 >= pEnd )
    3260                 :          0 :             return false;
    3261 [ #  # ][ #  # ]:          0 :         if( (pPtr[0] != 0x80) || (pPtr[1] >= 0x03) )
    3262                 :          0 :             return false;
    3263                 :          0 :         const int nLen = (pPtr[5]<<24) + (pPtr[4]<<16) + (pPtr[3]<<8) + pPtr[2];
    3264         [ #  # ]:          0 :         if( nLen <= 0)
    3265                 :          0 :             return false;
    3266                 :          0 :         rSegmentLengths[i] = nLen;
    3267                 :          0 :         pPtr += nLen + 6;
    3268                 :            :     }
    3269                 :            : 
    3270                 :            :     // read segment-end header
    3271         [ #  # ]:          0 :     if( pPtr+2 >= pEnd )
    3272                 :          0 :         return false;
    3273 [ #  # ][ #  # ]:          0 :     if( (pPtr[0] != 0x80) || (pPtr[1] != 0x03) )
    3274                 :          0 :         return false;
    3275                 :            : 
    3276                 :          0 :     return true;
    3277                 :            : }
    3278                 :            : 
    3279         [ #  # ]:          0 : struct FontException : public std::exception
    3280                 :            : {
    3281                 :            : };
    3282                 :            : 
    3283                 :            : // TODO: always subset instead of embedding the full font => this method becomes obsolete then
    3284                 :          0 : std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const PhysicalFontFace* pFont, EmbedFont& rEmbed )
    3285                 :            : {
    3286         [ #  # ]:          0 :     std::map< sal_Int32, sal_Int32 > aRet;
    3287         [ #  # ]:          0 :     if( isBuiltinFont( pFont ) )
    3288                 :            :     {
    3289 [ #  # ][ #  # ]:          0 :         aRet[ rEmbed.m_nNormalFontID ] = emitBuiltinFont( pFont );
    3290                 :            :         return aRet;
    3291                 :            :     }
    3292                 :            : 
    3293                 :          0 :     sal_Int32 nStreamObject = 0;
    3294                 :          0 :     sal_Int32 nFontDescriptor = 0;
    3295                 :            : 
    3296                 :            :     // prepare font encoding
    3297         [ #  # ]:          0 :     const Ucs2SIntMap* pEncoding = m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pFont, NULL );
    3298                 :          0 :     sal_Int32 nToUnicodeStream = 0;
    3299                 :            :     sal_uInt8 nEncoding[256];
    3300                 :            :     sal_Ucs nEncodedCodes[256];
    3301         [ #  # ]:          0 :     std::vector<sal_Ucs> aUnicodes;
    3302         [ #  # ]:          0 :     aUnicodes.reserve( 256 );
    3303                 :            :     sal_Int32 pUnicodesPerGlyph[256];
    3304                 :            :     sal_Int32 pEncToUnicodeIndex[256];
    3305         [ #  # ]:          0 :     if( pEncoding )
    3306                 :            :     {
    3307                 :          0 :         memset( nEncoding, 0, sizeof(nEncoding) );
    3308                 :          0 :         memset( nEncodedCodes, 0, sizeof(nEncodedCodes) );
    3309                 :          0 :         memset( pUnicodesPerGlyph, 0, sizeof(pUnicodesPerGlyph) );
    3310                 :          0 :         memset( pEncToUnicodeIndex, 0, sizeof(pEncToUnicodeIndex) );
    3311 [ #  # ][ #  # ]:          0 :         for( Ucs2SIntMap::const_iterator it = pEncoding->begin(); it != pEncoding->end(); ++it )
                 [ #  # ]
    3312                 :            :         {
    3313 [ #  # ][ #  # ]:          0 :             if( it->second != -1 )
    3314                 :            :             {
    3315         [ #  # ]:          0 :                 sal_Int32 nCode = (sal_Int32)(it->second & 0x000000ff);
    3316                 :          0 :                 nEncoding[ nCode ] = static_cast<sal_uInt8>( nCode );
    3317         [ #  # ]:          0 :                 nEncodedCodes[ nCode ] = it->first;
    3318                 :          0 :                 pEncToUnicodeIndex[ nCode ] = static_cast<sal_Int32>(aUnicodes.size());
    3319 [ #  # ][ #  # ]:          0 :                 aUnicodes.push_back( it->first );
    3320                 :          0 :                 pUnicodesPerGlyph[ nCode ] = 1;
    3321                 :            :             }
    3322                 :            :         }
    3323                 :            :     }
    3324                 :            : 
    3325         [ #  # ]:          0 :     FontSubsetInfo aInfo;
    3326                 :            :     sal_Int32 pWidths[256];
    3327                 :          0 :     const unsigned char* pFontData = NULL;
    3328                 :          0 :     long nFontLen = 0;
    3329                 :            :     sal_Int32 nLength1, nLength2;
    3330                 :            :     try
    3331                 :            :     {
    3332 [ #  # ][ #  # ]:          0 :         if( (pFontData = (const unsigned char*)m_pReferenceDevice->mpGraphics->GetEmbedFontData( pFont, nEncodedCodes, pWidths, aInfo, &nFontLen )) != NULL )
    3333                 :            :         {
    3334         [ #  # ]:          0 :             if( (aInfo.m_nFontType & FontSubsetInfo::ANY_TYPE1) == 0 )
    3335                 :          0 :                 throw FontException();
    3336                 :            :             // see whether it is pfb or pfa; if it is a pfb, fill ranges
    3337                 :            :             // of 6 bytes that are not part of the font program
    3338         [ #  # ]:          0 :             std::list< int > aSections;
    3339         [ #  # ]:          0 :             std::list< int >::const_iterator it;
    3340                 :          0 :             int nIndex = 0;
    3341 [ #  # ][ #  # ]:          0 :             while( (nIndex < nFontLen-1) && pFontData[nIndex] == 0x80 )
                 [ #  # ]
    3342                 :            :             {
    3343         [ #  # ]:          0 :                 aSections.push_back( nIndex );
    3344         [ #  # ]:          0 :                 if( pFontData[nIndex+1] == 0x03 )
    3345                 :          0 :                     break;
    3346                 :            :                 sal_Int32 nBytes =
    3347                 :          0 :                 ((sal_Int32)pFontData[nIndex+2])            |
    3348                 :          0 :                 ((sal_Int32)pFontData[nIndex+3]) << 8       |
    3349                 :          0 :                 ((sal_Int32)pFontData[nIndex+4]) << 16      |
    3350                 :          0 :                 ((sal_Int32)pFontData[nIndex+5]) << 24;
    3351                 :          0 :                 nIndex += nBytes+6;
    3352                 :            :             }
    3353                 :            : 
    3354                 :            :             // search for eexec
    3355                 :            :             // TODO: use getPfbSegmentLengths() if possible to skip the search thingies below
    3356                 :          0 :             nIndex = 0;
    3357                 :            :             int nEndAsciiIndex;
    3358                 :            :             int nBeginBinaryIndex;
    3359                 :            :             int nEndBinaryIndex;
    3360 [ #  # ][ #  # ]:          0 :             do
                 [ #  # ]
    3361                 :            :             {
    3362 [ #  # ][ #  # ]:          0 :                 while( nIndex < nFontLen-4 &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    3363                 :          0 :                     ( pFontData[nIndex] != 'e'  ||
    3364                 :          0 :                         pFontData[nIndex+1] != 'e' ||
    3365                 :          0 :                         pFontData[nIndex+2] != 'x' ||
    3366                 :          0 :                         pFontData[nIndex+3] != 'e' ||
    3367                 :          0 :                         pFontData[nIndex+4] != 'c'
    3368                 :            :                         )
    3369                 :            :                     )
    3370                 :          0 :                 nIndex++;
    3371                 :            :                 // check whether we are in a excluded section
    3372 [ #  # ][ #  # ]:          0 :                 for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3373                 :            :                     ;
    3374 [ #  # ][ #  # ]:          0 :             } while( it != aSections.end() && nIndex < nFontLen-4 );
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    3375                 :            :             // this should end the ascii part
    3376         [ #  # ]:          0 :             if( nIndex > nFontLen-5 )
    3377                 :          0 :                 throw FontException();
    3378                 :            : 
    3379                 :          0 :             nEndAsciiIndex = nIndex+4;
    3380                 :            :             // now count backwards until we can account for 512 '0'
    3381                 :            :             // which is the endmarker of the (hopefully) binary data
    3382                 :            :             // do not count the pfb header sections
    3383                 :          0 :             int nFound = 0;
    3384                 :          0 :             nIndex =  nFontLen-1;
    3385 [ #  # ][ #  # ]:          0 :             while( nIndex > 0 && nFound < 512 )
                 [ #  # ]
    3386                 :            :             {
    3387 [ #  # ][ #  # ]:          0 :                 for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3388                 :            :                     ;
    3389 [ #  # ][ #  # ]:          0 :                 if( it == aSections.end() )
                 [ #  # ]
    3390                 :            :                 {
    3391                 :            :                     // inside the 512 '0' block there may only be whitespace
    3392                 :            :                     // according to T1 spec; probably it would be to simple
    3393                 :            :                     // if all fonts complied
    3394         [ #  # ]:          0 :                     if( pFontData[nIndex] == '0' )
    3395                 :          0 :                         nFound++;
    3396 [ #  # ][ #  # ]:          0 :                         else if( nFound > 0                 &&
         [ #  # ][ #  # ]
                 [ #  # ]
    3397                 :          0 :                             pFontData[nIndex] != '\r'       &&
    3398                 :          0 :                         pFontData[nIndex] != '\t'       &&
    3399                 :          0 :                         pFontData[nIndex] != '\n'       &&
    3400                 :          0 :                         pFontData[nIndex] != ' ' )
    3401                 :          0 :                         break;
    3402                 :            :                 }
    3403                 :          0 :                 nIndex--;
    3404                 :            :             }
    3405                 :            : 
    3406 [ #  # ][ #  # ]:          0 :             if( nIndex < 1 || nIndex <= nEndAsciiIndex )
    3407                 :          0 :                 throw FontException();
    3408                 :            : 
    3409                 :            :             // nLength3 is the rest of the file - excluding any section headers
    3410                 :            :             // nIndex now points before the first of the 512 '0' characters marking the
    3411                 :            :             // fixed content portion
    3412                 :          0 :             sal_Int32 nLength3 = nFontLen - nIndex - 1;
    3413 [ #  # ][ #  # ]:          0 :             for( it = aSections.begin(); it != aSections.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
    3414                 :            :             {
    3415 [ #  # ][ #  # ]:          0 :                 if( *it >= nIndex  )
    3416                 :            :                 {
    3417                 :            :                 // special case: nIndex inside a section marker
    3418 [ #  # ][ #  # ]:          0 :                     if( nIndex >= (*it) && (*it)+5 > nIndex )
         [ #  # ][ #  # ]
                 [ #  # ]
    3419         [ #  # ]:          0 :                         nLength3 -= (*it)+5 - nIndex;
    3420                 :            :                     else
    3421                 :            :                     {
    3422 [ #  # ][ #  # ]:          0 :                         if( *it < nFontLen - 6 )
    3423                 :          0 :                             nLength3 -= 6;
    3424                 :            :                         else // the last section 0x8003 is only 2 bytes after all
    3425         [ #  # ]:          0 :                             nLength3 -= (nFontLen - *it);
    3426                 :            :                     }
    3427                 :            :                 }
    3428                 :            :             }
    3429                 :            : 
    3430                 :            :             // there may be whitespace to ignore before the 512 '0'
    3431 [ #  # ][ #  # ]:          0 :             while( pFontData[nIndex] == '\r' || pFontData[nIndex] == '\n' )
                 [ #  # ]
    3432                 :            :             {
    3433                 :          0 :                 nIndex--;
    3434 [ #  # ][ #  # ]:          0 :                 for( it = aSections.begin(); it != aSections.end() && (nIndex < *it || nIndex > ((*it) + 5) ); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3435                 :            :                     ;
    3436 [ #  # ][ #  # ]:          0 :                 if( it != aSections.end() )
                 [ #  # ]
    3437                 :            :                 {
    3438         [ #  # ]:          0 :                     nIndex = (*it)-1;
    3439                 :          0 :                     break; // this is surely a binary boundary, in ascii case it wouldn't matter
    3440                 :            :                 }
    3441                 :            :             }
    3442                 :          0 :             nEndBinaryIndex = nIndex;
    3443                 :            : 
    3444                 :            :             // search for beginning of binary section
    3445                 :          0 :             nBeginBinaryIndex = nEndAsciiIndex;
    3446 [ #  # ][ #  # ]:          0 :             do
         [ #  # ][ #  # ]
                 [ #  # ]
    3447                 :            :             {
    3448                 :          0 :                 nBeginBinaryIndex++;
    3449 [ #  # ][ #  # ]:          0 :                 for( it = aSections.begin(); it != aSections.end() && (nBeginBinaryIndex < *it || nBeginBinaryIndex > ((*it) + 5) ); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3450                 :            :                     ;
    3451                 :            :                     } while( nBeginBinaryIndex < nEndBinaryIndex &&
    3452                 :          0 :                         ( pFontData[nBeginBinaryIndex] == '\r'  ||
    3453                 :          0 :                             pFontData[nBeginBinaryIndex] == '\n'    ||
    3454 [ #  # ][ #  # ]:          0 :                             it != aSections.end() ) );
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    3455                 :            : 
    3456                 :            :                     // it seems to be vital to copy the exact whitespace between binary data
    3457                 :            :                     // and eexec, else a invalid font results. so make nEndAsciiIndex
    3458                 :            :                     // always immediate in front of nBeginBinaryIndex
    3459                 :          0 :                     nEndAsciiIndex = nBeginBinaryIndex-1;
    3460 [ #  # ][ #  # ]:          0 :                     for( it = aSections.begin(); it != aSections.end() && (nEndAsciiIndex < *it || nEndAsciiIndex > ((*it)+5)); ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3461                 :            :                         ;
    3462 [ #  # ][ #  # ]:          0 :                     if( it != aSections.end() )
                 [ #  # ]
    3463         [ #  # ]:          0 :                         nEndAsciiIndex = (*it)-1;
    3464                 :            : 
    3465                 :          0 :                     nLength1 = nEndAsciiIndex+1; // including the last character
    3466 [ #  # ][ #  # ]:          0 :                     for( it = aSections.begin(); it != aSections.end() && *it < nEndAsciiIndex; ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3467                 :          0 :                         nLength1 -= 6; // decrease by pfb section size
    3468                 :            : 
    3469                 :            :                     // if the first four bytes are all ascii hex characters, then binary data
    3470                 :            :                     // has to be converted to real binary data
    3471 [ #  # ][ #  # ]:          0 :                     for( nIndex = 0; nIndex < 4 &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3472                 :          0 :                         ( ( pFontData[ nBeginBinaryIndex+nIndex ] >= '0' && pFontData[ nBeginBinaryIndex+nIndex ] <= '9' ) ||
    3473                 :          0 :                             ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'a' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'f' ) ||
    3474                 :          0 :                             ( pFontData[ nBeginBinaryIndex+nIndex ] >= 'A' && pFontData[ nBeginBinaryIndex+nIndex ] <= 'F' )
    3475                 :            :                             ); ++nIndex )
    3476                 :            :                     ;
    3477                 :          0 :                     bool bConvertHexData = true;
    3478         [ #  # ]:          0 :                     if( nIndex < 4 )
    3479                 :            :                     {
    3480                 :          0 :                         bConvertHexData = false;
    3481                 :          0 :                         nLength2 = nEndBinaryIndex - nBeginBinaryIndex + 1; // include the last byte
    3482 [ #  # ][ #  # ]:          0 :                         for( it = aSections.begin(); it != aSections.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
    3483 [ #  # ][ #  # ]:          0 :                             if( *it > nBeginBinaryIndex && *it < nEndBinaryIndex )
         [ #  # ][ #  # ]
                 [ #  # ]
    3484                 :          0 :                             nLength2 -= 6;
    3485                 :            :                     }
    3486                 :            :                     else
    3487                 :            :                     {
    3488                 :            :                         // count the hex ascii characters to get nLength2
    3489                 :          0 :                         nLength2 = 0;
    3490                 :          0 :                         int nNextSectionIndex = 0;
    3491 [ #  # ][ #  # ]:          0 :                         for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3492                 :            :                             ;
    3493 [ #  # ][ #  # ]:          0 :                         if( it != aSections.end() )
                 [ #  # ]
    3494         [ #  # ]:          0 :                             nNextSectionIndex = *it;
    3495         [ #  # ]:          0 :                         for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
    3496                 :            :                         {
    3497         [ #  # ]:          0 :                             if( nIndex == nNextSectionIndex )
    3498                 :            :                             {
    3499                 :          0 :                                 nIndex += 6;
    3500         [ #  # ]:          0 :                                 ++it;
    3501 [ #  # ][ #  # ]:          0 :                                 nNextSectionIndex = (it == aSections.end() ? 0 : *it );
         [ #  # ][ #  # ]
    3502                 :            :                             }
    3503 [ #  # ][ #  # ]:          0 :                             if( ( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3504                 :          0 :                                 ( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' ) ||
    3505                 :          0 :                             ( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' ) )
    3506                 :          0 :                             nLength2++;
    3507                 :            :                         }
    3508                 :            :                         DBG_ASSERT( !(nLength2 & 1), "uneven number of hex chars in binary pfa section" );
    3509                 :          0 :                         nLength2 /= 2;
    3510                 :            :                     }
    3511                 :            : 
    3512                 :            :                     // now we can actually write the font stream !
    3513                 :            :                     #if OSL_DEBUG_LEVEL > 1
    3514                 :            :                     emitComment( " PDFWriterImpl::emitEmbeddedFont" );
    3515                 :            :                     #endif
    3516                 :          0 :                     OStringBuffer aLine( 512 );
    3517         [ #  # ]:          0 :                     nStreamObject = createObject();
    3518 [ #  # ][ #  # ]:          0 :                     if( !updateObject(nStreamObject))
    3519                 :          0 :                         throw FontException();
    3520         [ #  # ]:          0 :                     sal_Int32 nStreamLengthObject = createObject();
    3521         [ #  # ]:          0 :                     aLine.append( nStreamObject );
    3522                 :            :                     aLine.append( " 0 obj\n"
    3523         [ #  # ]:          0 :                         "<</Length " );
    3524         [ #  # ]:          0 :                     aLine.append( nStreamLengthObject );
    3525                 :            :                     aLine.append( " 0 R"
    3526                 :            :                         #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    3527                 :            :                         "/Filter/FlateDecode"
    3528                 :            :                         #endif
    3529         [ #  # ]:          0 :                         "/Length1 " );
    3530         [ #  # ]:          0 :                     aLine.append( nLength1 );
    3531         [ #  # ]:          0 :                     aLine.append( " /Length2 " );
    3532         [ #  # ]:          0 :                     aLine.append( nLength2 );
    3533         [ #  # ]:          0 :                     aLine.append( " /Length3 ");
    3534         [ #  # ]:          0 :                     aLine.append( nLength3 );
    3535                 :            :                     aLine.append( ">>\n"
    3536         [ #  # ]:          0 :                         "stream\n" );
    3537 [ #  # ][ #  # ]:          0 :                     if( !writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3538                 :          0 :                         throw FontException();
    3539                 :            : 
    3540                 :          0 :                     sal_uInt64 nBeginStreamPos = 0;
    3541         [ #  # ]:          0 :                     osl_getFilePos( m_aFile, &nBeginStreamPos );
    3542                 :            : 
    3543         [ #  # ]:          0 :                     beginCompression();
    3544         [ #  # ]:          0 :                     checkAndEnableStreamEncryption( nStreamObject );
    3545                 :            : 
    3546                 :            :                     // write ascii section
    3547 [ #  # ][ #  # ]:          0 :                     if( aSections.begin() == aSections.end() )
    3548                 :            :                     {
    3549 [ #  # ][ #  # ]:          0 :                         if( ! writeBuffer( pFontData, nEndAsciiIndex+1 ) )
    3550                 :          0 :                             throw FontException();
    3551                 :            :                     }
    3552                 :            :                     else
    3553                 :            :                     {
    3554                 :            :                         // first section always starts at 0
    3555         [ #  # ]:          0 :                         it = aSections.begin();
    3556         [ #  # ]:          0 :                         nIndex = (*it)+6;
    3557         [ #  # ]:          0 :                         ++it;
    3558 [ #  # ][ #  # ]:          0 :                         while( *it < nEndAsciiIndex )
    3559                 :            :                         {
    3560 [ #  # ][ #  # ]:          0 :                             if( ! writeBuffer( pFontData+nIndex, (*it)-nIndex ) )
                 [ #  # ]
    3561                 :          0 :                                 throw FontException();
    3562         [ #  # ]:          0 :                             nIndex = (*it)+6;
    3563         [ #  # ]:          0 :                             ++it;
    3564                 :            :                         }
    3565                 :            :                         // write partial last section
    3566 [ #  # ][ #  # ]:          0 :                         if( ! writeBuffer( pFontData+nIndex, nEndAsciiIndex-nIndex+1 ) )
    3567                 :          0 :                             throw FontException();
    3568                 :            :                     }
    3569                 :            : 
    3570                 :            :                     // write binary section
    3571         [ #  # ]:          0 :                     if( ! bConvertHexData )
    3572                 :            :                     {
    3573 [ #  # ][ #  # ]:          0 :                         if( aSections.begin() == aSections.end() )
    3574                 :            :                         {
    3575 [ #  # ][ #  # ]:          0 :                             if( ! writeBuffer( pFontData+nBeginBinaryIndex, nFontLen-nBeginBinaryIndex ) )
    3576                 :          0 :                                 throw FontException();
    3577                 :            :                         }
    3578                 :            :                         else
    3579                 :            :                         {
    3580 [ #  # ][ #  # ]:          0 :                             for( it = aSections.begin(); *it < nBeginBinaryIndex; ++it )
         [ #  # ][ #  # ]
    3581                 :            :                                 ;
    3582                 :            :                             // write first partial section
    3583 [ #  # ][ #  # ]:          0 :                             if( ! writeBuffer( pFontData+nBeginBinaryIndex, (*it) - nBeginBinaryIndex ) )
                 [ #  # ]
    3584                 :          0 :                                 throw FontException();
    3585                 :            :                             // write following sections
    3586 [ #  # ][ #  # ]:          0 :                             while( it != aSections.end() )
                 [ #  # ]
    3587                 :            :                             {
    3588         [ #  # ]:          0 :                                 nIndex = (*it)+6;
    3589         [ #  # ]:          0 :                                 ++it;
    3590         [ #  # ]:          0 :                                 if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
    3591                 :            :                                 {
    3592 [ #  # ][ #  # ]:          0 :                                     sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
         [ #  # ][ #  # ]
    3593 [ #  # ][ #  # ]:          0 :                                     if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
    3594                 :          0 :                                         throw FontException();
    3595                 :            :                                 }
    3596                 :            :                             }
    3597                 :            :                         }
    3598                 :            :                     }
    3599                 :            :                     else
    3600                 :            :                     {
    3601 [ #  # ][ #  # ]:          0 :                         boost::shared_array<unsigned char> pWriteBuffer( new unsigned char[ nLength2 ] );
    3602                 :          0 :                         memset( pWriteBuffer.get(), 0, nLength2 );
    3603                 :          0 :                         int nWriteIndex = 0;
    3604                 :            : 
    3605                 :          0 :                         int nNextSectionIndex = 0;
    3606 [ #  # ][ #  # ]:          0 :                         for( it = aSections.begin(); it != aSections.end() && *it < nBeginBinaryIndex; ++it )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
           #  # ][ #  # ]
    3607                 :            :                             ;
    3608 [ #  # ][ #  # ]:          0 :                         if( it != aSections.end() )
                 [ #  # ]
    3609         [ #  # ]:          0 :                             nNextSectionIndex = *it;
    3610         [ #  # ]:          0 :                         for( nIndex = nBeginBinaryIndex; nIndex <= nEndBinaryIndex; nIndex++ )
    3611                 :            :                         {
    3612         [ #  # ]:          0 :                             if( nIndex == nNextSectionIndex )
    3613                 :            :                             {
    3614                 :          0 :                                 nIndex += 6;
    3615         [ #  # ]:          0 :                                 ++it;
    3616 [ #  # ][ #  # ]:          0 :                                 nNextSectionIndex = (it == aSections.end() ? nFontLen : *it );
         [ #  # ][ #  # ]
    3617                 :            :                             }
    3618                 :          0 :                             unsigned char cNibble = 0x80;
    3619 [ #  # ][ #  # ]:          0 :                             if( pFontData[ nIndex ] >= '0' && pFontData[ nIndex ] <= '9' )
    3620                 :          0 :                                 cNibble = pFontData[nIndex] - '0';
    3621 [ #  # ][ #  # ]:          0 :                             else if( pFontData[ nIndex ] >= 'a' && pFontData[ nIndex ] <= 'f' )
    3622                 :          0 :                                 cNibble = pFontData[nIndex] - 'a' + 10;
    3623 [ #  # ][ #  # ]:          0 :                             else if( pFontData[ nIndex ] >= 'A' && pFontData[ nIndex ] <= 'F' )
    3624                 :          0 :                                 cNibble = pFontData[nIndex] - 'A' + 10;
    3625         [ #  # ]:          0 :                             if( cNibble != 0x80 )
    3626                 :            :                             {
    3627         [ #  # ]:          0 :                                 if( !(nWriteIndex & 1 ) )
    3628                 :          0 :                                     cNibble <<= 4;
    3629                 :          0 :                                 pWriteBuffer.get()[ nWriteIndex/2 ] |= cNibble;
    3630                 :          0 :                                 nWriteIndex++;
    3631                 :            :                             }
    3632                 :            :                         }
    3633 [ #  # ][ #  # ]:          0 :                         if( ! writeBuffer( pWriteBuffer.get(), nLength2 ) )
    3634                 :          0 :                             throw FontException();
    3635         [ #  # ]:          0 :                         if( aSections.empty() )
    3636                 :            :                         {
    3637 [ #  # ][ #  # ]:          0 :                             if( ! writeBuffer( pFontData+nIndex, nFontLen-nIndex ) )
    3638                 :          0 :                                 throw FontException();
    3639                 :            :                         }
    3640                 :            :                         else
    3641                 :            :                         {
    3642                 :            :                             // write rest of this section
    3643         [ #  # ]:          0 :                             if( nIndex < nNextSectionIndex )
    3644                 :            :                             {
    3645 [ #  # ][ #  # ]:          0 :                                 if( ! writeBuffer( pFontData+nIndex, nNextSectionIndex - nIndex ) )
    3646                 :          0 :                                     throw FontException();
    3647                 :            :                             }
    3648                 :            :                             // write following sections
    3649 [ #  # ][ #  # ]:          0 :                             while( it != aSections.end() )
                 [ #  # ]
    3650                 :            :                             {
    3651         [ #  # ]:          0 :                                 nIndex = (*it)+6;
    3652         [ #  # ]:          0 :                                 ++it;
    3653         [ #  # ]:          0 :                                 if( nIndex < nFontLen ) // last section marker is usually the EOF which has only 2 bytes
    3654                 :            :                                 {
    3655 [ #  # ][ #  # ]:          0 :                                     sal_Int32 nSectionLen = (it == aSections.end()) ? nFontLen - nIndex : (*it) - nIndex;
         [ #  # ][ #  # ]
    3656 [ #  # ][ #  # ]:          0 :                                     if( ! writeBuffer( pFontData+nIndex, nSectionLen ) )
    3657                 :          0 :                                         throw FontException();
    3658                 :            :                                 }
    3659                 :            :                             }
    3660         [ #  # ]:          0 :                         }
    3661                 :            :                     }
    3662         [ #  # ]:          0 :                     endCompression();
    3663                 :          0 :                     disableStreamEncryption();
    3664                 :            : 
    3665                 :            : 
    3666                 :          0 :                     sal_uInt64 nEndStreamPos = 0;
    3667         [ #  # ]:          0 :                     osl_getFilePos( m_aFile, &nEndStreamPos );
    3668                 :            : 
    3669                 :            :                     // and finally close the stream
    3670         [ #  # ]:          0 :                     aLine.setLength( 0 );
    3671         [ #  # ]:          0 :                     aLine.append( "\nendstream\nendobj\n\n" );
    3672 [ #  # ][ #  # ]:          0 :                     if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3673                 :          0 :                         throw FontException();
    3674                 :            : 
    3675                 :            :                     // write stream length object
    3676         [ #  # ]:          0 :                     aLine.setLength( 0 );
    3677 [ #  # ][ #  # ]:          0 :                     if( ! updateObject( nStreamLengthObject ) )
    3678                 :          0 :                         throw FontException();
    3679         [ #  # ]:          0 :                     aLine.append( nStreamLengthObject );
    3680         [ #  # ]:          0 :                     aLine.append( " 0 obj\n" );
    3681         [ #  # ]:          0 :                     aLine.append( (sal_Int64)(nEndStreamPos-nBeginStreamPos ) );
    3682         [ #  # ]:          0 :                     aLine.append( "\nendobj\n\n" );
    3683 [ #  # ][ #  # ]:          0 :                     if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3684                 :          0 :                         throw FontException();
    3685                 :            :         }
    3686                 :            :         else
    3687                 :            :         {
    3688                 :          0 :             rtl::OStringBuffer aErrorComment( 256 );
    3689         [ #  # ]:          0 :             aErrorComment.append( "GetEmbedFontData failed for font \"" );
    3690 [ #  # ][ #  # ]:          0 :             aErrorComment.append( OUStringToOString( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
                 [ #  # ]
    3691         [ #  # ]:          0 :             aErrorComment.append( '\"' );
    3692         [ #  # ]:          0 :             if( pFont->GetSlant() == ITALIC_NORMAL )
    3693         [ #  # ]:          0 :                 aErrorComment.append( " italic" );
    3694         [ #  # ]:          0 :             else if( pFont->GetSlant() == ITALIC_OBLIQUE )
    3695         [ #  # ]:          0 :                 aErrorComment.append( " oblique" );
    3696         [ #  # ]:          0 :             aErrorComment.append( " weight=" );
    3697         [ #  # ]:          0 :             aErrorComment.append( sal_Int32(pFont->GetWeight()) );
    3698         [ #  # ]:          0 :             emitComment( aErrorComment.getStr() );
    3699                 :            :         }
    3700                 :            : 
    3701         [ #  # ]:          0 :         if( nStreamObject )
    3702                 :            :             // write font descriptor
    3703         [ #  # ]:          0 :         nFontDescriptor = emitFontDescriptor( pFont, aInfo, 0, nStreamObject );
    3704                 :            : 
    3705         [ #  # ]:          0 :         if( nFontDescriptor )
    3706                 :            :         {
    3707         [ #  # ]:          0 :             if( pEncoding )
    3708 [ #  # ][ #  # ]:          0 :                 nToUnicodeStream = createToUnicodeCMap( nEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, SAL_N_ELEMENTS(nEncoding) );
    3709                 :            : 
    3710                 :            :             // write font object
    3711         [ #  # ]:          0 :             sal_Int32 nObject = createObject();
    3712 [ #  # ][ #  # ]:          0 :             if( ! updateObject( nObject ) )
    3713                 :          0 :                 throw FontException();
    3714                 :            : 
    3715                 :          0 :             OStringBuffer aLine( 1024 );
    3716         [ #  # ]:          0 :             aLine.append( nObject );
    3717                 :            :             aLine.append( " 0 obj\n"
    3718         [ #  # ]:          0 :                 "<</Type/Font/Subtype/Type1/BaseFont/" );
    3719 [ #  # ][ #  # ]:          0 :             appendName( aInfo.m_aPSName, aLine );
    3720         [ #  # ]:          0 :             aLine.append( "\n" );
    3721 [ #  # ][ #  # ]:          0 :             if( !pFont->mbSymbolFlag &&  pEncoding == 0 )
    3722         [ #  # ]:          0 :                 aLine.append( "/Encoding/WinAnsiEncoding\n" );
    3723         [ #  # ]:          0 :             if( nToUnicodeStream )
    3724                 :            :             {
    3725         [ #  # ]:          0 :                 aLine.append( "/ToUnicode " );
    3726         [ #  # ]:          0 :                 aLine.append( nToUnicodeStream );
    3727         [ #  # ]:          0 :                 aLine.append( " 0 R\n" );
    3728                 :            :             }
    3729                 :            :             aLine.append( "/FirstChar 0 /LastChar 255\n"
    3730         [ #  # ]:          0 :                 "/Widths[" );
    3731         [ #  # ]:          0 :             for( int i = 0; i < 256; i++ )
    3732                 :            :             {
    3733         [ #  # ]:          0 :                 aLine.append( pWidths[i] );
    3734 [ #  # ][ #  # ]:          0 :                 aLine.append( ((i&15) == 15) ? "\n" : " " );
    3735                 :            :             }
    3736                 :            :             aLine.append( "]\n"
    3737         [ #  # ]:          0 :                 "/FontDescriptor " );
    3738         [ #  # ]:          0 :             aLine.append( nFontDescriptor );
    3739                 :            :             aLine.append( " 0 R>>\n"
    3740         [ #  # ]:          0 :                 "endobj\n\n" );
    3741 [ #  # ][ #  # ]:          0 :             if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3742                 :          0 :                 throw FontException();
    3743                 :            : 
    3744         [ #  # ]:          0 :             aRet[ rEmbed.m_nNormalFontID ] = nObject;
    3745                 :            : 
    3746                 :            :             // write additional encodings
    3747         [ #  # ]:          0 :             for( std::list< EmbedEncoding >::iterator enc_it = rEmbed.m_aExtendedEncodings.begin(); enc_it != rEmbed.m_aExtendedEncodings.end(); ++enc_it )
    3748                 :            :             {
    3749                 :            :                 sal_Int32 aEncWidths[ 256 ];
    3750                 :            :                 // emit encoding dict
    3751         [ #  # ]:          0 :                 sal_Int32 nEncObject = createObject();
    3752 [ #  # ][ #  # ]:          0 :                 if( ! updateObject( nEncObject ) )
    3753                 :          0 :                     throw FontException();
    3754                 :            : 
    3755         [ #  # ]:          0 :                 OutputDevice* pRef = getReferenceDevice();
    3756         [ #  # ]:          0 :                 pRef->Push( PUSH_FONT | PUSH_MAPMODE );
    3757 [ #  # ][ #  # ]:          0 :                 pRef->SetMapMode( MapMode( MAP_PIXEL ) );
                 [ #  # ]
    3758         [ #  # ]:          0 :                 Font aFont( pFont->GetFamilyName(), pFont->GetStyleName(), Size( 0, 1000 ) );
    3759         [ #  # ]:          0 :                 aFont.SetWeight( pFont->GetWeight() );
    3760         [ #  # ]:          0 :                 aFont.SetItalic( pFont->GetSlant() );
    3761         [ #  # ]:          0 :                 aFont.SetPitch( pFont->GetPitch() );
    3762         [ #  # ]:          0 :                 pRef->SetFont( aFont );
    3763         [ #  # ]:          0 :                 pRef->ImplNewFont();
    3764                 :            : 
    3765         [ #  # ]:          0 :                 aLine.setLength( 0 );
    3766         [ #  # ]:          0 :                 aLine.append( nEncObject );
    3767                 :            :                 aLine.append( " 0 obj\n"
    3768         [ #  # ]:          0 :                     "<</Type/Encoding/Differences[ 0\n" );
    3769                 :          0 :                 int nEncoded = 0;
    3770                 :          0 :                 aUnicodes.clear();
    3771 [ #  # ][ #  # ]:          0 :                 for( std::vector< EmbedCode >::iterator str_it = enc_it->m_aEncVector.begin(); str_it != enc_it->m_aEncVector.end(); ++str_it )
    3772                 :            :                 {
    3773                 :          0 :                     rtl::OUString aStr( str_it->m_aUnicode );
    3774 [ #  # ][ #  # ]:          0 :                     aEncWidths[nEncoded] = pRef->GetTextWidth( aStr );
                 [ #  # ]
    3775                 :          0 :                     nEncodedCodes[nEncoded] = str_it->m_aUnicode;
    3776                 :          0 :                     nEncoding[nEncoded] = sal::static_int_cast<sal_uInt8>(nEncoded);
    3777                 :          0 :                     pEncToUnicodeIndex[nEncoded] = static_cast<sal_Int32>(aUnicodes.size());
    3778         [ #  # ]:          0 :                     aUnicodes.push_back( nEncodedCodes[nEncoded] );
    3779                 :          0 :                     pUnicodesPerGlyph[nEncoded] = 1;
    3780                 :            : 
    3781         [ #  # ]:          0 :                     aLine.append( " /" );
    3782         [ #  # ]:          0 :                     aLine.append( str_it->m_aName );
    3783         [ #  # ]:          0 :                     if( !((++nEncoded) & 15) )
    3784         [ #  # ]:          0 :                         aLine.append( "\n" );
    3785                 :          0 :                 }
    3786                 :            :                 aLine.append( "]>>\n"
    3787         [ #  # ]:          0 :                     "endobj\n\n" );
    3788                 :            : 
    3789         [ #  # ]:          0 :                 pRef->Pop();
    3790                 :            : 
    3791 [ #  # ][ #  # ]:          0 :                 if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3792                 :          0 :                     throw FontException();
    3793                 :            : 
    3794 [ #  # ][ #  # ]:          0 :                 nToUnicodeStream = createToUnicodeCMap( nEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, nEncoded );
    3795                 :            : 
    3796         [ #  # ]:          0 :                 nObject = createObject();
    3797 [ #  # ][ #  # ]:          0 :                 if( ! updateObject( nObject ) )
    3798                 :          0 :                     throw FontException();
    3799                 :            : 
    3800         [ #  # ]:          0 :                 aLine.setLength( 0 );
    3801         [ #  # ]:          0 :                 aLine.append( nObject );
    3802                 :            :                 aLine.append( " 0 obj\n"
    3803         [ #  # ]:          0 :                     "<</Type/Font/Subtype/Type1/BaseFont/" );
    3804 [ #  # ][ #  # ]:          0 :                 appendName( aInfo.m_aPSName, aLine );
    3805         [ #  # ]:          0 :                 aLine.append( "\n" );
    3806         [ #  # ]:          0 :                 aLine.append( "/Encoding " );
    3807         [ #  # ]:          0 :                 aLine.append( nEncObject );
    3808         [ #  # ]:          0 :                 aLine.append( " 0 R\n" );
    3809         [ #  # ]:          0 :                 if( nToUnicodeStream )
    3810                 :            :                 {
    3811         [ #  # ]:          0 :                     aLine.append( "/ToUnicode " );
    3812         [ #  # ]:          0 :                     aLine.append( nToUnicodeStream );
    3813         [ #  # ]:          0 :                     aLine.append( " 0 R\n" );
    3814                 :            :                 }
    3815                 :            :                 aLine.append( "/FirstChar 0\n"
    3816         [ #  # ]:          0 :                     "/LastChar " );
    3817         [ #  # ]:          0 :                 aLine.append( (sal_Int32)(nEncoded-1) );
    3818                 :            :                 aLine.append( "\n"
    3819         [ #  # ]:          0 :                     "/Widths[" );
    3820         [ #  # ]:          0 :                 for( int i = 0; i < nEncoded; i++ )
    3821                 :            :                 {
    3822         [ #  # ]:          0 :                     aLine.append( aEncWidths[i] );
    3823 [ #  # ][ #  # ]:          0 :                     aLine.append( ((i&15) == 15) ? "\n" : " " );
    3824                 :            :                 }
    3825                 :            :                 aLine.append( " ]\n"
    3826         [ #  # ]:          0 :                     "/FontDescriptor " );
    3827         [ #  # ]:          0 :                 aLine.append( nFontDescriptor );
    3828                 :            :                 aLine.append( " 0 R>>\n"
    3829         [ #  # ]:          0 :                     "endobj\n\n" );
    3830 [ #  # ][ #  # ]:          0 :                 if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    3831                 :          0 :                     throw FontException();
    3832                 :            : 
    3833         [ #  # ]:          0 :                 aRet[ enc_it->m_nFontID ] = nObject;
    3834         [ #  # ]:          0 :             }
    3835                 :            :         }
    3836                 :            :     }
    3837   [ #  #  #  # ]:          0 :     catch( FontException& )
    3838                 :            :     {
    3839                 :            :         // these do nothing in case there was no compression or encryption ongoing
    3840         [ #  # ]:          0 :         endCompression();
    3841                 :          0 :         disableStreamEncryption();
    3842                 :            :     }
    3843                 :            : 
    3844         [ #  # ]:          0 :     if( pFontData )
    3845         [ #  # ]:          0 :         m_pReferenceDevice->mpGraphics->FreeEmbedFontData( pFontData, nFontLen );
    3846                 :            : 
    3847         [ #  # ]:          0 :     return aRet;
    3848                 :            : }
    3849                 :            : 
    3850                 :          0 : static void appendSubsetName( int nSubsetID, const OUString& rPSName, OStringBuffer& rBuffer )
    3851                 :            : {
    3852         [ #  # ]:          0 :     if( nSubsetID )
    3853                 :            :     {
    3854         [ #  # ]:          0 :         for( int i = 0; i < 6; i++ )
    3855                 :            :         {
    3856                 :          0 :             int nOffset = (nSubsetID % 26);
    3857                 :          0 :             nSubsetID /= 26;
    3858                 :          0 :             rBuffer.append( (sal_Char)('A'+nOffset) );
    3859                 :            :         }
    3860                 :          0 :         rBuffer.append( '+' );
    3861                 :            :     }
    3862                 :          0 :     appendName( rPSName, rBuffer );
    3863                 :          0 : }
    3864                 :            : 
    3865                 :          0 : sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding,
    3866                 :            :                                               sal_Ucs* pUnicodes,
    3867                 :            :                                               sal_Int32* pUnicodesPerGlyph,
    3868                 :            :                                               sal_Int32* pEncToUnicodeIndex,
    3869                 :            :                                               int nGlyphs )
    3870                 :            : {
    3871                 :          0 :     int nMapped = 0, n = 0;
    3872         [ #  # ]:          0 :     for( n = 0; n < nGlyphs; n++ )
    3873 [ #  # ][ #  # ]:          0 :         if( pUnicodes[pEncToUnicodeIndex[n]] && pUnicodesPerGlyph[n] )
    3874                 :          0 :             nMapped++;
    3875                 :            : 
    3876         [ #  # ]:          0 :     if( nMapped == 0 )
    3877                 :          0 :         return 0;
    3878                 :            : 
    3879         [ #  # ]:          0 :     sal_Int32 nStream = createObject();
    3880 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nStream ) );
    3881                 :            : 
    3882                 :          0 :     OStringBuffer aContents( 1024 );
    3883                 :            :     aContents.append(
    3884                 :            :                      "/CIDInit/ProcSet findresource begin\n"
    3885                 :            :                      "12 dict begin\n"
    3886                 :            :                      "begincmap\n"
    3887                 :            :                      "/CIDSystemInfo<<\n"
    3888                 :            :                      "/Registry (Adobe)\n"
    3889                 :            :                      "/Ordering (UCS)\n"
    3890                 :            :                      "/Supplement 0\n"
    3891                 :            :                      ">> def\n"
    3892                 :            :                      "/CMapName/Adobe-Identity-UCS def\n"
    3893                 :            :                      "/CMapType 2 def\n"
    3894                 :            :                      "1 begincodespacerange\n"
    3895                 :            :                      "<00> <FF>\n"
    3896                 :            :                      "endcodespacerange\n"
    3897         [ #  # ]:          0 :                      );
    3898                 :          0 :     int nCount = 0;
    3899         [ #  # ]:          0 :     for( n = 0; n < nGlyphs; n++ )
    3900                 :            :     {
    3901 [ #  # ][ #  # ]:          0 :         if( pUnicodes[pEncToUnicodeIndex[n]] && pUnicodesPerGlyph[n] )
    3902                 :            :         {
    3903         [ #  # ]:          0 :             if( (nCount % 100) == 0 )
    3904                 :            :             {
    3905         [ #  # ]:          0 :                 if( nCount )
    3906         [ #  # ]:          0 :                     aContents.append( "endbfchar\n" );
    3907         [ #  # ]:          0 :                 aContents.append( (sal_Int32)((nMapped-nCount > 100) ? 100 : nMapped-nCount ) );
    3908         [ #  # ]:          0 :                 aContents.append( " beginbfchar\n" );
    3909                 :            :             }
    3910         [ #  # ]:          0 :             aContents.append( '<' );
    3911         [ #  # ]:          0 :             appendHex( (sal_Int8)pEncoding[n], aContents );
    3912         [ #  # ]:          0 :             aContents.append( "> <" );
    3913                 :            :             // TODO: handle unicodes>U+FFFF
    3914                 :          0 :             sal_Int32 nIndex = pEncToUnicodeIndex[n];
    3915         [ #  # ]:          0 :             for( sal_Int32 j = 0; j < pUnicodesPerGlyph[n]; j++ )
    3916                 :            :             {
    3917         [ #  # ]:          0 :                 appendHex( (sal_Int8)(pUnicodes[nIndex + j] / 256), aContents );
    3918         [ #  # ]:          0 :                 appendHex( (sal_Int8)(pUnicodes[nIndex + j] & 255), aContents );
    3919                 :            :             }
    3920         [ #  # ]:          0 :             aContents.append( ">\n" );
    3921                 :          0 :             nCount++;
    3922                 :            :         }
    3923                 :            :     }
    3924                 :            :     aContents.append( "endbfchar\n"
    3925                 :            :                       "endcmap\n"
    3926                 :            :                       "CMapName currentdict /CMap defineresource pop\n"
    3927                 :            :                       "end\n"
    3928         [ #  # ]:          0 :                       "end\n" );
    3929                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    3930 [ #  # ][ #  # ]:          0 :     ZCodec* pCodec = new ZCodec( 0x4000, 0x4000 );
    3931         [ #  # ]:          0 :     SvMemoryStream aStream;
    3932         [ #  # ]:          0 :     pCodec->BeginCompression();
    3933         [ #  # ]:          0 :     pCodec->Write( aStream, (const sal_uInt8*)aContents.getStr(), aContents.getLength() );
    3934         [ #  # ]:          0 :     pCodec->EndCompression();
    3935 [ #  # ][ #  # ]:          0 :     delete pCodec;
    3936                 :            : #endif
    3937                 :            : 
    3938                 :            :     #if OSL_DEBUG_LEVEL > 1
    3939                 :            :     emitComment( "PDFWriterImpl::createToUnicodeCMap" );
    3940                 :            :     #endif
    3941                 :          0 :     OStringBuffer aLine( 40 );
    3942                 :            : 
    3943         [ #  # ]:          0 :     aLine.append( nStream );
    3944         [ #  # ]:          0 :     aLine.append( " 0 obj\n<</Length " );
    3945                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    3946                 :          0 :     sal_Int32 nLen = (sal_Int32)aStream.Tell();
    3947         [ #  # ]:          0 :     aStream.Seek( 0 );
    3948         [ #  # ]:          0 :     aLine.append( nLen );
    3949         [ #  # ]:          0 :     aLine.append( "/Filter/FlateDecode" );
    3950                 :            : #else
    3951                 :            :     aLine.append( aContents.getLength() );
    3952                 :            : #endif
    3953         [ #  # ]:          0 :     aLine.append( ">>\nstream\n" );
    3954 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    3955         [ #  # ]:          0 :     checkAndEnableStreamEncryption( nStream );
    3956                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    3957 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aStream.GetData(), nLen ) );
                 [ #  # ]
    3958                 :            : #else
    3959                 :            :     CHECK_RETURN( writeBuffer( aContents.getStr(), aContents.getLength() ) );
    3960                 :            : #endif
    3961                 :          0 :     disableStreamEncryption();
    3962         [ #  # ]:          0 :     aLine.setLength( 0 );
    3963                 :            :     aLine.append( "\nendstream\n"
    3964         [ #  # ]:          0 :                   "endobj\n\n" );
    3965 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    3966         [ #  # ]:          0 :     return nStream;
    3967                 :            : }
    3968                 :            : 
    3969                 :          0 : sal_Int32 PDFWriterImpl::emitFontDescriptor( const PhysicalFontFace* pFont, FontSubsetInfo& rInfo, sal_Int32 nSubsetID, sal_Int32 nFontStream )
    3970                 :            : {
    3971                 :          0 :     OStringBuffer aLine( 1024 );
    3972                 :            :     // get font flags, see PDF reference 1.4 p. 358
    3973                 :            :     // possibly characters outside Adobe standard encoding
    3974                 :            :     // so set Symbolic flag
    3975                 :          0 :     sal_Int32 nFontFlags = (1<<2);
    3976 [ #  # ][ #  # ]:          0 :     if( pFont->GetSlant() == ITALIC_NORMAL || pFont->GetSlant() == ITALIC_OBLIQUE )
                 [ #  # ]
    3977                 :          0 :         nFontFlags |= (1 << 6);
    3978         [ #  # ]:          0 :     if( pFont->GetPitch() == PITCH_FIXED )
    3979                 :          0 :         nFontFlags |= 1;
    3980         [ #  # ]:          0 :     if( pFont->GetFamilyType() == FAMILY_SCRIPT )
    3981                 :          0 :         nFontFlags |= (1 << 3);
    3982         [ #  # ]:          0 :     else if( pFont->GetFamilyType() == FAMILY_ROMAN )
    3983                 :          0 :         nFontFlags |= (1 << 1);
    3984                 :            : 
    3985         [ #  # ]:          0 :     sal_Int32 nFontDescriptor = createObject();
    3986 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nFontDescriptor ) );
    3987         [ #  # ]:          0 :     aLine.setLength( 0 );
    3988         [ #  # ]:          0 :     aLine.append( nFontDescriptor );
    3989                 :            :     aLine.append( " 0 obj\n"
    3990         [ #  # ]:          0 :                   "<</Type/FontDescriptor/FontName/" );
    3991 [ #  # ][ #  # ]:          0 :     appendSubsetName( nSubsetID, rInfo.m_aPSName, aLine );
    3992                 :            :     aLine.append( "\n"
    3993         [ #  # ]:          0 :                   "/Flags " );
    3994         [ #  # ]:          0 :     aLine.append( nFontFlags );
    3995                 :            :     aLine.append( "\n"
    3996         [ #  # ]:          0 :                   "/FontBBox[" );
    3997                 :            :     // note: Top and Bottom are reversed in VCL and PDF rectangles
    3998         [ #  # ]:          0 :     aLine.append( (sal_Int32)rInfo.m_aFontBBox.TopLeft().X() );
    3999         [ #  # ]:          0 :     aLine.append( ' ' );
    4000         [ #  # ]:          0 :     aLine.append( (sal_Int32)rInfo.m_aFontBBox.TopLeft().Y() );
    4001         [ #  # ]:          0 :     aLine.append( ' ' );
    4002 [ #  # ][ #  # ]:          0 :     aLine.append( (sal_Int32)rInfo.m_aFontBBox.BottomRight().X() );
    4003         [ #  # ]:          0 :     aLine.append( ' ' );
    4004 [ #  # ][ #  # ]:          0 :     aLine.append( (sal_Int32)(rInfo.m_aFontBBox.BottomRight().Y()+1) );
    4005         [ #  # ]:          0 :     aLine.append( "]/ItalicAngle " );
    4006 [ #  # ][ #  # ]:          0 :     if( pFont->GetSlant() == ITALIC_OBLIQUE || pFont->GetSlant() == ITALIC_NORMAL )
                 [ #  # ]
    4007         [ #  # ]:          0 :         aLine.append( "-30" );
    4008                 :            :     else
    4009         [ #  # ]:          0 :         aLine.append( "0" );
    4010                 :            :     aLine.append( "\n"
    4011         [ #  # ]:          0 :                   "/Ascent " );
    4012         [ #  # ]:          0 :     aLine.append( (sal_Int32)rInfo.m_nAscent );
    4013                 :            :     aLine.append( "\n"
    4014         [ #  # ]:          0 :                   "/Descent " );
    4015         [ #  # ]:          0 :     aLine.append( (sal_Int32)-rInfo.m_nDescent );
    4016                 :            :     aLine.append( "\n"
    4017         [ #  # ]:          0 :                   "/CapHeight " );
    4018         [ #  # ]:          0 :     aLine.append( (sal_Int32)rInfo.m_nCapHeight );
    4019                 :            :     // According to PDF reference 1.4 StemV is required
    4020                 :            :     // seems a tad strange to me, but well ...
    4021                 :            :     aLine.append( "\n"
    4022         [ #  # ]:          0 :                   "/StemV 80\n" );
    4023         [ #  # ]:          0 :     if( nFontStream )
    4024                 :            :     {
    4025         [ #  # ]:          0 :         aLine.append( "/FontFile" );
    4026      [ #  #  # ]:          0 :         switch( rInfo.m_nFontType )
    4027                 :            :         {
    4028                 :            :             case FontSubsetInfo::SFNT_TTF:
    4029         [ #  # ]:          0 :                 aLine.append( '2' );
    4030                 :          0 :                 break;
    4031                 :            :             case FontSubsetInfo::TYPE1_PFA:
    4032                 :            :             case FontSubsetInfo::TYPE1_PFB:
    4033                 :            :             case FontSubsetInfo::ANY_TYPE1:
    4034                 :          0 :                 break;
    4035                 :            :             default:
    4036                 :            :                 OSL_FAIL( "unknown fonttype in PDF font descriptor" );
    4037                 :          0 :                 return 0;
    4038                 :            :         }
    4039         [ #  # ]:          0 :         aLine.append( ' ' );
    4040         [ #  # ]:          0 :         aLine.append( nFontStream );
    4041         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    4042                 :            :     }
    4043                 :            :     aLine.append( ">>\n"
    4044         [ #  # ]:          0 :                   "endobj\n\n" );
    4045 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4046                 :            : 
    4047                 :          0 :     return nFontDescriptor;
    4048                 :            : }
    4049                 :            : 
    4050                 :          0 : void PDFWriterImpl::appendBuiltinFontsToDict( OStringBuffer& rDict ) const
    4051                 :            : {
    4052   [ #  #  #  # ]:          0 :     for( std::map< sal_Int32, sal_Int32 >::const_iterator it =
                 [ #  # ]
    4053                 :          0 :          m_aBuiltinFontToObjectMap.begin(); it != m_aBuiltinFontToObjectMap.end(); ++it )
    4054                 :            :     {
    4055 [ #  # ][ #  # ]:          0 :         rDict.append( m_aBuiltinFonts[it->first].getNameObject() );
                 [ #  # ]
    4056         [ #  # ]:          0 :         rDict.append( ' ' );
    4057 [ #  # ][ #  # ]:          0 :         rDict.append( it->second );
    4058         [ #  # ]:          0 :         rDict.append( " 0 R" );
    4059                 :            :     }
    4060                 :          0 : }
    4061                 :            : 
    4062                 :          0 : bool PDFWriterImpl::emitFonts()
    4063                 :            : {
    4064 [ #  # ][ #  # ]:          0 :     if( ! m_pReferenceDevice->ImplGetGraphics() )
    4065                 :          0 :         return false;
    4066                 :            : 
    4067                 :          0 :     OStringBuffer aLine( 1024 );
    4068                 :            : 
    4069         [ #  # ]:          0 :     std::map< sal_Int32, sal_Int32 > aFontIDToObject;
    4070                 :            : 
    4071                 :          0 :     OUString aTmpName;
    4072         [ #  # ]:          0 :     osl_createTempFile( NULL, NULL, &aTmpName.pData );
    4073         [ #  # ]:          0 :     for( FontSubsetData::iterator it = m_aSubsets.begin(); it != m_aSubsets.end(); ++it )
    4074                 :            :     {
    4075         [ #  # ]:          0 :         for( FontEmitList::iterator lit = it->second.m_aSubsets.begin(); lit != it->second.m_aSubsets.end(); ++lit )
    4076                 :            :         {
    4077                 :            :             sal_Int32 pGlyphIDs[ 256 ];
    4078                 :            :             sal_Int32 pWidths[ 256 ];
    4079                 :            :             sal_uInt8 pEncoding[ 256 ];
    4080                 :            :             sal_Int32 pEncToUnicodeIndex[ 256 ];
    4081                 :            :             sal_Int32 pUnicodesPerGlyph[ 256 ];
    4082         [ #  # ]:          0 :             std::vector<sal_Ucs> aUnicodes;
    4083         [ #  # ]:          0 :             aUnicodes.reserve( 256 );
    4084                 :          0 :             int nGlyphs = 1;
    4085                 :            :             // fill arrays and prepare encoding index map
    4086                 :          0 :             sal_Int32 nToUnicodeStream = 0;
    4087                 :            : 
    4088                 :          0 :             memset( pGlyphIDs, 0, sizeof( pGlyphIDs ) );
    4089                 :          0 :             memset( pEncoding, 0, sizeof( pEncoding ) );
    4090                 :          0 :             memset( pUnicodesPerGlyph, 0, sizeof( pUnicodesPerGlyph ) );
    4091                 :          0 :             memset( pEncToUnicodeIndex, 0, sizeof( pEncToUnicodeIndex ) );
    4092         [ #  # ]:          0 :             for( FontEmitMapping::iterator fit = lit->m_aMapping.begin(); fit != lit->m_aMapping.end();++fit )
    4093                 :            :             {
    4094                 :          0 :                 sal_uInt8 nEnc = fit->second.getGlyphId();
    4095                 :            : 
    4096                 :            :                 DBG_ASSERT( pGlyphIDs[nEnc] == 0 && pEncoding[nEnc] == 0, "duplicate glyph" );
    4097                 :            :                 DBG_ASSERT( nEnc <= lit->m_aMapping.size(), "invalid glyph encoding" );
    4098                 :            : 
    4099                 :          0 :                 pGlyphIDs[ nEnc ] = fit->first;
    4100                 :          0 :                 pEncoding[ nEnc ] = nEnc;
    4101                 :          0 :                 pEncToUnicodeIndex[ nEnc ] = static_cast<sal_Int32>(aUnicodes.size());
    4102                 :          0 :                 pUnicodesPerGlyph[ nEnc ] = fit->second.countCodes();
    4103         [ #  # ]:          0 :                 for( sal_Int32 n = 0; n < pUnicodesPerGlyph[ nEnc ]; n++ )
    4104 [ #  # ][ #  # ]:          0 :                     aUnicodes.push_back( fit->second.getCode( n ) );
    4105 [ #  # ][ #  # ]:          0 :                 if( fit->second.getCode(0) )
    4106                 :          0 :                     nToUnicodeStream = 1;
    4107         [ #  # ]:          0 :                 if( nGlyphs < 256 )
    4108                 :          0 :                     nGlyphs++;
    4109                 :            :                 else
    4110                 :            :                 {
    4111                 :            :                     OSL_FAIL( "too many glyphs for subset" );
    4112                 :            :                 }
    4113                 :            :             }
    4114         [ #  # ]:          0 :             FontSubsetInfo aSubsetInfo;
    4115 [ #  # ][ #  # ]:          0 :             if( m_pReferenceDevice->mpGraphics->CreateFontSubset( aTmpName, it->first, pGlyphIDs, pEncoding, pWidths, nGlyphs, aSubsetInfo ) )
    4116                 :            :             {
    4117                 :            :                 // create font stream
    4118                 :            :                 oslFileHandle aFontFile;
    4119 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( (osl_File_E_None == osl_openFile( aTmpName.pData, &aFontFile, osl_File_OpenFlag_Read ) ) );
    4120                 :            :                 // get file size
    4121                 :            :                 sal_uInt64 nLength1;
    4122 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_End, 0 ) ) );
    4123 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( (osl_File_E_None == osl_getFilePos( aFontFile, &nLength1 ) ) );
    4124 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
    4125                 :            : 
    4126                 :            :                 #if OSL_DEBUG_LEVEL > 1
    4127                 :            :                 emitComment( "PDFWriterImpl::emitFonts" );
    4128                 :            :                 #endif
    4129         [ #  # ]:          0 :                 sal_Int32 nFontStream = createObject();
    4130         [ #  # ]:          0 :                 sal_Int32 nStreamLengthObject = createObject();
    4131 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( updateObject( nFontStream ) );
    4132         [ #  # ]:          0 :                 aLine.setLength( 0 );
    4133         [ #  # ]:          0 :                 aLine.append( nFontStream );
    4134                 :            :                 aLine.append( " 0 obj\n"
    4135         [ #  # ]:          0 :                              "<</Length " );
    4136         [ #  # ]:          0 :                 aLine.append( (sal_Int32)nStreamLengthObject );
    4137                 :            :                 aLine.append( " 0 R"
    4138                 :            :                              #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    4139                 :            :                              "/Filter/FlateDecode"
    4140                 :            :                              #endif
    4141         [ #  # ]:          0 :                              "/Length1 " );
    4142                 :            : 
    4143                 :          0 :                 sal_uInt64 nStartPos = 0;
    4144         [ #  # ]:          0 :                 if( aSubsetInfo.m_nFontType == FontSubsetInfo::SFNT_TTF )
    4145                 :            :                 {
    4146         [ #  # ]:          0 :                     aLine.append( (sal_Int32)nLength1 );
    4147                 :            : 
    4148                 :            :                     aLine.append( ">>\n"
    4149         [ #  # ]:          0 :                                  "stream\n" );
    4150 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4151 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
    4152                 :            : 
    4153                 :            :                     // copy font file
    4154         [ #  # ]:          0 :                     beginCompression();
    4155         [ #  # ]:          0 :                     checkAndEnableStreamEncryption( nFontStream );
    4156                 :          0 :                     sal_Bool bEOF = sal_False;
    4157         [ #  # ]:          0 :                     do
    4158                 :            :                     {
    4159                 :            :                         char buf[8192];
    4160                 :            :                         sal_uInt64 nRead;
    4161 [ #  # ][ #  # ]:          0 :                         CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, buf, sizeof( buf ), &nRead ) ) );
    4162 [ #  # ][ #  # ]:          0 :                         CHECK_RETURN( writeBuffer( buf, nRead ) );
    4163 [ #  # ][ #  # ]:          0 :                         CHECK_RETURN( (osl_File_E_None == osl_isEndOfFile( aFontFile, &bEOF ) ) );
    4164                 :          0 :                     } while( ! bEOF );
    4165                 :            :                 }
    4166         [ #  # ]:          0 :                 else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::CFF_FONT) != 0 )
    4167                 :            :                 {
    4168                 :            :                     // TODO: implement
    4169                 :            :                     OSL_FAIL( "PDFWriterImpl does not support CFF-font subsets yet!" );
    4170                 :            :                 }
    4171         [ #  # ]:          0 :                 else if( (aSubsetInfo.m_nFontType & FontSubsetInfo::TYPE1_PFB) != 0 ) // TODO: also support PFA?
    4172                 :            :                 {
    4173 [ #  # ][ #  # ]:          0 :                     boost::shared_array<unsigned char> pBuffer( new unsigned char[ nLength1 ] );
    4174                 :            : 
    4175                 :          0 :                     sal_uInt64 nBytesRead = 0;
    4176 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( (osl_File_E_None == osl_readFile( aFontFile, pBuffer.get(), nLength1, &nBytesRead ) ) );
    4177                 :            :                     DBG_ASSERT( nBytesRead==nLength1, "PDF-FontSubset read incomplete!" );
    4178 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
    4179                 :            :                     // get the PFB-segment lengths
    4180                 :          0 :                     ThreeInts aSegmentLengths = {0,0,0};
    4181                 :          0 :                     getPfbSegmentLengths( pBuffer.get(), (int)nBytesRead, aSegmentLengths );
    4182                 :            :                     // the lengths below are mandatory for PDF-exported Type1 fonts
    4183                 :            :                     // because the PFB segment headers get stripped! WhyOhWhy.
    4184         [ #  # ]:          0 :                     aLine.append( (sal_Int32)aSegmentLengths[0] );
    4185         [ #  # ]:          0 :                     aLine.append( "/Length2 " );
    4186         [ #  # ]:          0 :                     aLine.append( (sal_Int32)aSegmentLengths[1] );
    4187         [ #  # ]:          0 :                     aLine.append( "/Length3 " );
    4188         [ #  # ]:          0 :                     aLine.append( (sal_Int32)aSegmentLengths[2] );
    4189                 :            : 
    4190                 :            :                     aLine.append( ">>\n"
    4191         [ #  # ]:          0 :                                  "stream\n" );
    4192 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4193 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos ) ) );
    4194                 :            : 
    4195                 :            :                     // emit PFB-sections without section headers
    4196         [ #  # ]:          0 :                     beginCompression();
    4197         [ #  # ]:          0 :                     checkAndEnableStreamEncryption( nFontStream );
    4198 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( writeBuffer( &pBuffer[6], aSegmentLengths[0] ) );
    4199 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( writeBuffer( &pBuffer[12] + aSegmentLengths[0], aSegmentLengths[1] ) );
    4200 [ #  # ][ #  # ]:          0 :                     CHECK_RETURN( writeBuffer( &pBuffer[18] + aSegmentLengths[0] + aSegmentLengths[1], aSegmentLengths[2] ) );
         [ #  # ][ #  # ]
    4201                 :            :                 }
    4202                 :            :                 else
    4203                 :            :                 {
    4204         [ #  # ]:          0 :                     fprintf( stderr, "PDF: CreateFontSubset result in not yet supported format=%d\n",aSubsetInfo.m_nFontType);
    4205         [ #  # ]:          0 :                     aLine.append( "0 >>\nstream\n" );
    4206                 :            :                 }
    4207                 :            : 
    4208         [ #  # ]:          0 :                 endCompression();
    4209                 :          0 :                 disableStreamEncryption();
    4210                 :            :                 // close the file
    4211         [ #  # ]:          0 :                 osl_closeFile( aFontFile );
    4212                 :            : 
    4213                 :          0 :                 sal_uInt64 nEndPos = 0;
    4214 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nEndPos ) ) );
    4215                 :            :                 // end the stream
    4216         [ #  # ]:          0 :                 aLine.setLength( 0 );
    4217         [ #  # ]:          0 :                 aLine.append( "\nendstream\nendobj\n\n" );
    4218 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4219                 :            : 
    4220                 :            :                 // emit stream length object
    4221 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( updateObject( nStreamLengthObject ) );
    4222         [ #  # ]:          0 :                 aLine.setLength( 0 );
    4223         [ #  # ]:          0 :                 aLine.append( nStreamLengthObject );
    4224         [ #  # ]:          0 :                 aLine.append( " 0 obj\n" );
    4225         [ #  # ]:          0 :                 aLine.append( (sal_Int64)(nEndPos-nStartPos) );
    4226         [ #  # ]:          0 :                 aLine.append( "\nendobj\n\n" );
    4227 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4228                 :            : 
    4229                 :            :                 // write font descriptor
    4230         [ #  # ]:          0 :                 sal_Int32 nFontDescriptor = emitFontDescriptor( it->first, aSubsetInfo, lit->m_nFontID, nFontStream );
    4231                 :            : 
    4232         [ #  # ]:          0 :                 if( nToUnicodeStream )
    4233 [ #  # ][ #  # ]:          0 :                     nToUnicodeStream = createToUnicodeCMap( pEncoding, &aUnicodes[0], pUnicodesPerGlyph, pEncToUnicodeIndex, nGlyphs );
    4234                 :            : 
    4235         [ #  # ]:          0 :                 sal_Int32 nFontObject = createObject();
    4236 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( updateObject( nFontObject ) );
    4237         [ #  # ]:          0 :                 aLine.setLength( 0 );
    4238         [ #  # ]:          0 :                 aLine.append( nFontObject );
    4239                 :            : 
    4240         [ #  # ]:          0 :                 aLine.append( " 0 obj\n" );
    4241                 :            :                 aLine.append( ((aSubsetInfo.m_nFontType & FontSubsetInfo::ANY_TYPE1) != 0) ?
    4242                 :            :                              "<</Type/Font/Subtype/Type1/BaseFont/" :
    4243 [ #  # ][ #  # ]:          0 :                              "<</Type/Font/Subtype/TrueType/BaseFont/" );
    4244 [ #  # ][ #  # ]:          0 :                 appendSubsetName( lit->m_nFontID, aSubsetInfo.m_aPSName, aLine );
    4245                 :            :                 aLine.append( "\n"
    4246                 :            :                              "/FirstChar 0\n"
    4247         [ #  # ]:          0 :                              "/LastChar " );
    4248         [ #  # ]:          0 :                 aLine.append( (sal_Int32)(nGlyphs-1) );
    4249                 :            :                 aLine.append( "\n"
    4250         [ #  # ]:          0 :                              "/Widths[" );
    4251         [ #  # ]:          0 :                 for( int i = 0; i < nGlyphs; i++ )
    4252                 :            :                 {
    4253         [ #  # ]:          0 :                     aLine.append( pWidths[ i ] );
    4254 [ #  # ][ #  # ]:          0 :                     aLine.append( ((i & 15) == 15) ? "\n" : " " );
    4255                 :            :                 }
    4256                 :            :                 aLine.append( "]\n"
    4257         [ #  # ]:          0 :                              "/FontDescriptor " );
    4258         [ #  # ]:          0 :                 aLine.append( nFontDescriptor );
    4259         [ #  # ]:          0 :                 aLine.append( " 0 R\n" );
    4260         [ #  # ]:          0 :                 if( nToUnicodeStream )
    4261                 :            :                 {
    4262         [ #  # ]:          0 :                     aLine.append( "/ToUnicode " );
    4263         [ #  # ]:          0 :                     aLine.append( nToUnicodeStream );
    4264         [ #  # ]:          0 :                     aLine.append( " 0 R\n" );
    4265                 :            :                 }
    4266                 :            :                 aLine.append( ">>\n"
    4267         [ #  # ]:          0 :                              "endobj\n\n" );
    4268 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4269                 :            : 
    4270         [ #  # ]:          0 :                 aFontIDToObject[ lit->m_nFontID ] = nFontObject;
    4271                 :            :             }
    4272                 :            :             else
    4273                 :            :             {
    4274                 :          0 :                 const PhysicalFontFace* pFont = it->first;
    4275                 :          0 :                 rtl::OStringBuffer aErrorComment( 256 );
    4276         [ #  # ]:          0 :                 aErrorComment.append( "CreateFontSubset failed for font \"" );
    4277 [ #  # ][ #  # ]:          0 :                 aErrorComment.append( OUStringToOString( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 ) );
                 [ #  # ]
    4278         [ #  # ]:          0 :                 aErrorComment.append( '\"' );
    4279         [ #  # ]:          0 :                 if( pFont->GetSlant() == ITALIC_NORMAL )
    4280         [ #  # ]:          0 :                     aErrorComment.append( " italic" );
    4281         [ #  # ]:          0 :                 else if( pFont->GetSlant() == ITALIC_OBLIQUE )
    4282         [ #  # ]:          0 :                     aErrorComment.append( " oblique" );
    4283         [ #  # ]:          0 :                 aErrorComment.append( " weight=" );
    4284         [ #  # ]:          0 :                 aErrorComment.append( sal_Int32(pFont->GetWeight()) );
    4285         [ #  # ]:          0 :                 emitComment( aErrorComment.getStr() );
    4286                 :            :             }
    4287 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    4288                 :            :     }
    4289         [ #  # ]:          0 :     osl_removeFile( aTmpName.pData );
    4290                 :            : 
    4291                 :            :     // emit embedded fonts
    4292         [ #  # ]:          0 :     for( FontEmbedData::iterator eit = m_aEmbeddedFonts.begin(); eit != m_aEmbeddedFonts.end(); ++eit )
    4293                 :            :     {
    4294         [ #  # ]:          0 :         std::map< sal_Int32, sal_Int32 > aObjects = emitEmbeddedFont( eit->first, eit->second );
    4295 [ #  # ][ #  # ]:          0 :         for( std::map< sal_Int32, sal_Int32 >::iterator fit = aObjects.begin(); fit != aObjects.end(); ++fit )
                 [ #  # ]
    4296                 :            :         {
    4297 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( fit->second );
    4298 [ #  # ][ #  # ]:          0 :             aFontIDToObject[ fit->first ] = fit->second;
                 [ #  # ]
    4299                 :            :         }
    4300         [ #  # ]:          0 :     }
    4301                 :            : 
    4302                 :            :     // emit system fonts
    4303         [ #  # ]:          0 :     for( FontEmbedData::iterator sit = m_aSystemFonts.begin(); sit != m_aSystemFonts.end(); ++sit )
    4304                 :            :     {
    4305         [ #  # ]:          0 :         std::map< sal_Int32, sal_Int32 > aObjects = emitSystemFont( sit->first, sit->second );
    4306 [ #  # ][ #  # ]:          0 :         for( std::map< sal_Int32, sal_Int32 >::iterator fit = aObjects.begin(); fit != aObjects.end(); ++fit )
                 [ #  # ]
    4307                 :            :         {
    4308 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( fit->second );
    4309 [ #  # ][ #  # ]:          0 :             aFontIDToObject[ fit->first ] = fit->second;
                 [ #  # ]
    4310                 :            :         }
    4311         [ #  # ]:          0 :     }
    4312                 :            : 
    4313                 :          0 :     OStringBuffer aFontDict( 1024 );
    4314 [ #  # ][ #  # ]:          0 :     aFontDict.append( getFontDictObject() );
    4315                 :            :     aFontDict.append( " 0 obj\n"
    4316         [ #  # ]:          0 :                      "<<" );
    4317                 :          0 :     int ni = 0;
    4318 [ #  # ][ #  # ]:          0 :     for( std::map< sal_Int32, sal_Int32 >::iterator mit = aFontIDToObject.begin(); mit != aFontIDToObject.end(); ++mit )
                 [ #  # ]
    4319                 :            :     {
    4320         [ #  # ]:          0 :         aFontDict.append( "/F" );
    4321 [ #  # ][ #  # ]:          0 :         aFontDict.append( mit->first );
    4322         [ #  # ]:          0 :         aFontDict.append( ' ' );
    4323 [ #  # ][ #  # ]:          0 :         aFontDict.append( mit->second );
    4324         [ #  # ]:          0 :         aFontDict.append( " 0 R" );
    4325         [ #  # ]:          0 :         if( ((++ni) & 7) == 0 )
    4326         [ #  # ]:          0 :             aFontDict.append( '\n' );
    4327                 :            :     }
    4328                 :            :     // emit builtin font for widget apperances / variable text
    4329   [ #  #  #  # ]:          0 :     for( std::map< sal_Int32, sal_Int32 >::iterator it = m_aBuiltinFontToObjectMap.begin();
                 [ #  # ]
    4330                 :          0 :         it != m_aBuiltinFontToObjectMap.end(); ++it )
    4331                 :            :     {
    4332 [ #  # ][ #  # ]:          0 :         ImplPdfBuiltinFontData aData(m_aBuiltinFonts[it->first]);
    4333 [ #  # ][ #  # ]:          0 :         it->second = emitBuiltinFont( &aData, it->second );
                 [ #  # ]
    4334         [ #  # ]:          0 :     }
    4335         [ #  # ]:          0 :     appendBuiltinFontsToDict( aFontDict );
    4336         [ #  # ]:          0 :     aFontDict.append( "\n>>\nendobj\n\n" );
    4337                 :            : 
    4338 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( getFontDictObject() ) );
                 [ #  # ]
    4339 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aFontDict.getStr(), aFontDict.getLength() ) );
    4340                 :          0 :     return true;
    4341                 :            : }
    4342                 :            : 
    4343                 :          0 : sal_Int32 PDFWriterImpl::emitResources()
    4344                 :            : {
    4345                 :            :     // emit shadings
    4346         [ #  # ]:          0 :     if( ! m_aGradients.empty() )
    4347 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( emitGradients() );
    4348                 :            :     // emit tilings
    4349         [ #  # ]:          0 :     if( ! m_aTilings.empty() )
    4350 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( emitTilings() );
    4351                 :            : 
    4352                 :            :     // emit font dict
    4353 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( emitFonts() );
    4354                 :            : 
    4355                 :            :     // emit Resource dict
    4356                 :          0 :     OStringBuffer aLine( 512 );
    4357         [ #  # ]:          0 :     sal_Int32 nResourceDict = getResourceDictObj();
    4358 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nResourceDict ) );
    4359         [ #  # ]:          0 :     aLine.setLength( 0 );
    4360         [ #  # ]:          0 :     aLine.append( nResourceDict );
    4361         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    4362 [ #  # ][ #  # ]:          0 :     m_aGlobalResourceDict.append( aLine, getFontDictObject() );
    4363         [ #  # ]:          0 :     aLine.append( "endobj\n\n" );
    4364 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4365                 :          0 :     return nResourceDict;
    4366                 :            : }
    4367                 :            : 
    4368                 :          0 : sal_Int32 PDFWriterImpl::updateOutlineItemCount( std::vector< sal_Int32 >& rCounts,
    4369                 :            :                                                  sal_Int32 nItemLevel,
    4370                 :            :                                                  sal_Int32 nCurrentItemId )
    4371                 :            : {
    4372                 :            :     /* The /Count number of an item is
    4373                 :            :        positive: the number of visible subitems
    4374                 :            :        negative: the negative number of subitems that will become visible if
    4375                 :            :                  the item gets opened
    4376                 :            :        see PDF ref 1.4 p 478
    4377                 :            :     */
    4378                 :            : 
    4379                 :          0 :     sal_Int32 nCount = 0;
    4380                 :            : 
    4381 [ #  # ][ #  # ]:          0 :     if( m_aContext.OpenBookmarkLevels < 0           || // all levels arevisible
    4382                 :            :         m_aContext.OpenBookmarkLevels >= nItemLevel    // this level is visible
    4383                 :            :       )
    4384                 :            :     {
    4385                 :          0 :         PDFOutlineEntry& rItem = m_aOutline[ nCurrentItemId ];
    4386                 :          0 :         sal_Int32 nChildren = rItem.m_aChildren.size();
    4387         [ #  # ]:          0 :         for( sal_Int32 i = 0; i < nChildren; i++ )
    4388                 :          0 :             nCount += updateOutlineItemCount( rCounts, nItemLevel+1, rItem.m_aChildren[i] );
    4389                 :          0 :         rCounts[nCurrentItemId] = nCount;
    4390                 :            :         // return 1 (this item) + visible sub items
    4391         [ #  # ]:          0 :         if( nCount < 0 )
    4392                 :          0 :             nCount = 0;
    4393                 :          0 :         nCount++;
    4394                 :            :     }
    4395                 :            :     else
    4396                 :            :     {
    4397                 :            :         // this bookmark level is invisible
    4398                 :          0 :         PDFOutlineEntry& rItem = m_aOutline[ nCurrentItemId ];
    4399                 :          0 :         sal_Int32 nChildren = rItem.m_aChildren.size();
    4400                 :          0 :         rCounts[ nCurrentItemId ] = -sal_Int32(rItem.m_aChildren.size());
    4401         [ #  # ]:          0 :         for( sal_Int32 i = 0; i < nChildren; i++ )
    4402                 :          0 :             updateOutlineItemCount( rCounts, nItemLevel+1, rItem.m_aChildren[i] );
    4403                 :          0 :         nCount = -1;
    4404                 :            :     }
    4405                 :            : 
    4406                 :          0 :     return nCount;
    4407                 :            : }
    4408                 :            : 
    4409                 :          0 : sal_Int32 PDFWriterImpl::emitOutline()
    4410                 :            : {
    4411                 :          0 :     int i, nItems = m_aOutline.size();
    4412                 :            : 
    4413                 :            :     // do we have an outline at all ?
    4414         [ #  # ]:          0 :     if( nItems < 2 )
    4415                 :          0 :         return 0;
    4416                 :            : 
    4417                 :            :     // reserve object numbers for all outline items
    4418         [ #  # ]:          0 :     for( i = 0; i < nItems; ++i )
    4419         [ #  # ]:          0 :         m_aOutline[i].m_nObject = createObject();
    4420                 :            : 
    4421                 :            :     // update all parent, next and prev object ids
    4422         [ #  # ]:          0 :     for( i = 0; i < nItems; ++i )
    4423                 :            :     {
    4424                 :          0 :         PDFOutlineEntry& rItem = m_aOutline[i];
    4425                 :          0 :         int nChildren = rItem.m_aChildren.size();
    4426                 :            : 
    4427         [ #  # ]:          0 :         if( nChildren )
    4428                 :            :         {
    4429         [ #  # ]:          0 :             for( int n = 0; n < nChildren; ++n )
    4430                 :            :             {
    4431         [ #  # ]:          0 :                 PDFOutlineEntry& rChild = m_aOutline[ rItem.m_aChildren[n] ];
    4432                 :            : 
    4433                 :          0 :                 rChild.m_nParentObject = rItem.m_nObject;
    4434 [ #  # ][ #  # ]:          0 :                 rChild.m_nPrevObject = (n > 0) ? m_aOutline[ rItem.m_aChildren[n-1] ].m_nObject : 0;
    4435 [ #  # ][ #  # ]:          0 :                 rChild.m_nNextObject = (n < nChildren-1) ? m_aOutline[ rItem.m_aChildren[n+1] ].m_nObject : 0;
    4436                 :            :             }
    4437                 :            : 
    4438                 :            :         }
    4439                 :            :     }
    4440                 :            : 
    4441                 :            :     // calculate Count entries for all items
    4442         [ #  # ]:          0 :     std::vector< sal_Int32 > aCounts( nItems );
    4443         [ #  # ]:          0 :     updateOutlineItemCount( aCounts, 0, 0 );
    4444                 :            : 
    4445                 :            :     // emit hierarchy
    4446         [ #  # ]:          0 :     for( i = 0; i < nItems; ++i )
    4447                 :            :     {
    4448                 :          0 :         PDFOutlineEntry& rItem = m_aOutline[i];
    4449                 :          0 :         OStringBuffer aLine( 1024 );
    4450                 :            : 
    4451 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( updateObject( rItem.m_nObject ) );
    4452         [ #  # ]:          0 :         aLine.append( rItem.m_nObject );
    4453         [ #  # ]:          0 :         aLine.append( " 0 obj\n" );
    4454         [ #  # ]:          0 :         aLine.append( "<<" );
    4455                 :            :         // number of visible children (all levels)
    4456 [ #  # ][ #  # ]:          0 :         if( i > 0 || aCounts[0] > 0 )
         [ #  # ][ #  # ]
    4457                 :            :         {
    4458         [ #  # ]:          0 :             aLine.append( "/Count " );
    4459 [ #  # ][ #  # ]:          0 :             aLine.append( aCounts[i] );
    4460                 :            :         }
    4461         [ #  # ]:          0 :         if( ! rItem.m_aChildren.empty() )
    4462                 :            :         {
    4463                 :            :             // children list: First, Last
    4464         [ #  # ]:          0 :             aLine.append( "/First " );
    4465 [ #  # ][ #  # ]:          0 :             aLine.append( m_aOutline[rItem.m_aChildren.front()].m_nObject );
    4466         [ #  # ]:          0 :             aLine.append( " 0 R/Last " );
    4467 [ #  # ][ #  # ]:          0 :             aLine.append( m_aOutline[rItem.m_aChildren.back()].m_nObject );
    4468         [ #  # ]:          0 :             aLine.append( " 0 R\n" );
    4469                 :            :         }
    4470         [ #  # ]:          0 :         if( i > 0 )
    4471                 :            :         {
    4472                 :            :             // Title, Dest, Parent, Prev, Next
    4473         [ #  # ]:          0 :             aLine.append( "/Title" );
    4474         [ #  # ]:          0 :             appendUnicodeTextStringEncrypt( rItem.m_aTitle, rItem.m_nObject, aLine );
    4475         [ #  # ]:          0 :             aLine.append( "\n" );
    4476                 :            :             // Dest is not required
    4477 [ #  # ][ #  # ]:          0 :             if( rItem.m_nDestID >= 0 && rItem.m_nDestID < (sal_Int32)m_aDests.size() )
                 [ #  # ]
    4478                 :            :             {
    4479         [ #  # ]:          0 :                 aLine.append( "/Dest" );
    4480         [ #  # ]:          0 :                 appendDest( rItem.m_nDestID, aLine );
    4481                 :            :             }
    4482         [ #  # ]:          0 :             aLine.append( "/Parent " );
    4483         [ #  # ]:          0 :             aLine.append( rItem.m_nParentObject );
    4484         [ #  # ]:          0 :             aLine.append( " 0 R" );
    4485         [ #  # ]:          0 :             if( rItem.m_nPrevObject )
    4486                 :            :             {
    4487         [ #  # ]:          0 :                 aLine.append( "/Prev " );
    4488         [ #  # ]:          0 :                 aLine.append( rItem.m_nPrevObject );
    4489         [ #  # ]:          0 :                 aLine.append( " 0 R" );
    4490                 :            :             }
    4491         [ #  # ]:          0 :             if( rItem.m_nNextObject )
    4492                 :            :             {
    4493         [ #  # ]:          0 :                 aLine.append( "/Next " );
    4494         [ #  # ]:          0 :                 aLine.append( rItem.m_nNextObject );
    4495         [ #  # ]:          0 :                 aLine.append( " 0 R" );
    4496                 :            :             }
    4497                 :            :         }
    4498         [ #  # ]:          0 :         aLine.append( ">>\nendobj\n\n" );
    4499 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4500         [ #  # ]:          0 :     }
    4501                 :            : 
    4502                 :          0 :     return m_aOutline[0].m_nObject;
    4503                 :            : }
    4504                 :            : 
    4505                 :            : #undef CHECK_RETURN
    4506                 :            : #define CHECK_RETURN( x ) if( !x ) return false
    4507                 :            : 
    4508                 :          0 : bool PDFWriterImpl::appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer )
    4509                 :            : {
    4510 [ #  # ][ #  # ]:          0 :     if( nDestID < 0 || nDestID >= (sal_Int32)m_aDests.size() )
                 [ #  # ]
    4511                 :            :     {
    4512                 :            : #if OSL_DEBUG_LEVEL > 1
    4513                 :            :         fprintf( stderr, "ERROR: invalid dest %d requested\n", (int)nDestID );
    4514                 :            : #endif
    4515                 :          0 :         return false;
    4516                 :            :     }
    4517                 :            : 
    4518                 :            : 
    4519                 :          0 :     const PDFDest& rDest        = m_aDests[ nDestID ];
    4520                 :          0 :     const PDFPage& rDestPage    = m_aPages[ rDest.m_nPage ];
    4521                 :            : 
    4522                 :          0 :     rBuffer.append( '[' );
    4523                 :          0 :     rBuffer.append( rDestPage.m_nPageObject );
    4524                 :          0 :     rBuffer.append( " 0 R" );
    4525                 :            : 
    4526   [ #  #  #  #  :          0 :     switch( rDest.m_eType )
             #  #  #  # ]
    4527                 :            :     {
    4528                 :            :         case PDFWriter::XYZ:
    4529                 :            :         default:
    4530                 :          0 :             rBuffer.append( "/XYZ " );
    4531                 :          0 :             appendFixedInt( rDest.m_aRect.Left(), rBuffer );
    4532                 :          0 :             rBuffer.append( ' ' );
    4533                 :          0 :             appendFixedInt( rDest.m_aRect.Bottom(), rBuffer );
    4534                 :          0 :             rBuffer.append( " 0" );
    4535                 :          0 :             break;
    4536                 :            :         case PDFWriter::Fit:
    4537                 :          0 :             rBuffer.append( "/Fit" );
    4538                 :          0 :             break;
    4539                 :            :         case PDFWriter::FitRectangle:
    4540                 :          0 :             rBuffer.append( "/FitR " );
    4541                 :          0 :             appendFixedInt( rDest.m_aRect.Left(), rBuffer );
    4542                 :          0 :             rBuffer.append( ' ' );
    4543                 :          0 :             appendFixedInt( rDest.m_aRect.Top(), rBuffer );
    4544                 :          0 :             rBuffer.append( ' ' );
    4545                 :          0 :             appendFixedInt( rDest.m_aRect.Right(), rBuffer );
    4546                 :          0 :             rBuffer.append( ' ' );
    4547                 :          0 :             appendFixedInt( rDest.m_aRect.Bottom(), rBuffer );
    4548                 :          0 :             break;
    4549                 :            :         case PDFWriter::FitHorizontal:
    4550                 :          0 :             rBuffer.append( "/FitH " );
    4551                 :          0 :             appendFixedInt( rDest.m_aRect.Bottom(), rBuffer );
    4552                 :          0 :             break;
    4553                 :            :         case PDFWriter::FitVertical:
    4554                 :          0 :             rBuffer.append( "/FitV " );
    4555                 :          0 :             appendFixedInt( rDest.m_aRect.Left(), rBuffer );
    4556                 :          0 :             break;
    4557                 :            :         case PDFWriter::FitPageBoundingBox:
    4558                 :          0 :             rBuffer.append( "/FitB" );
    4559                 :          0 :             break;
    4560                 :            :         case PDFWriter::FitPageBoundingBoxHorizontal:
    4561                 :          0 :             rBuffer.append( "/FitBH " );
    4562                 :          0 :             appendFixedInt( rDest.m_aRect.Bottom(), rBuffer );
    4563                 :          0 :             break;
    4564                 :            :         case PDFWriter::FitPageBoundingBoxVertical:
    4565                 :          0 :             rBuffer.append( "/FitBV " );
    4566                 :          0 :             appendFixedInt( rDest.m_aRect.Left(), rBuffer );
    4567                 :          0 :             break;
    4568                 :            :     }
    4569                 :          0 :     rBuffer.append( ']' );
    4570                 :            : 
    4571                 :          0 :     return true;
    4572                 :            : }
    4573                 :            : 
    4574                 :          0 : bool PDFWriterImpl::emitLinkAnnotations()
    4575                 :            : {
    4576                 :          0 :     int nAnnots = m_aLinks.size();
    4577         [ #  # ]:          0 :     for( int i = 0; i < nAnnots; i++ )
    4578                 :            :     {
    4579                 :          0 :         const PDFLink& rLink            = m_aLinks[i];
    4580 [ #  # ][ #  # ]:          0 :         if( ! updateObject( rLink.m_nObject ) )
    4581                 :          0 :             continue;
    4582                 :            : 
    4583                 :          0 :         OStringBuffer aLine( 1024 );
    4584         [ #  # ]:          0 :         aLine.append( rLink.m_nObject );
    4585         [ #  # ]:          0 :         aLine.append( " 0 obj\n" );
    4586                 :            : //i59651  key /F set bits Print to 1 rest to 0. We don't set NoZoom NoRotate to 1, since it's a 'should'
    4587                 :            : // see PDF 8.4.2 and ISO 19005-1:2005 6.5.3
    4588         [ #  # ]:          0 :         aLine.append( "<</Type/Annot" );
    4589         [ #  # ]:          0 :         if( m_bIsPDF_A1 )
    4590         [ #  # ]:          0 :             aLine.append( "/F 4" );
    4591         [ #  # ]:          0 :         aLine.append( "/Subtype/Link/Border[0 0 0]/Rect[" );
    4592                 :            : 
    4593         [ #  # ]:          0 :         appendFixedInt( rLink.m_aRect.Left()-7, aLine );//the +7 to have a better shape of the border rectangle
    4594         [ #  # ]:          0 :         aLine.append( ' ' );
    4595         [ #  # ]:          0 :         appendFixedInt( rLink.m_aRect.Top(), aLine );
    4596         [ #  # ]:          0 :         aLine.append( ' ' );
    4597         [ #  # ]:          0 :         appendFixedInt( rLink.m_aRect.Right()+7, aLine );//the +7 to have a better shape of the border rectangle
    4598         [ #  # ]:          0 :         aLine.append( ' ' );
    4599         [ #  # ]:          0 :         appendFixedInt( rLink.m_aRect.Bottom(), aLine );
    4600         [ #  # ]:          0 :         aLine.append( "]" );
    4601         [ #  # ]:          0 :         if( rLink.m_nDest >= 0 )
    4602                 :            :         {
    4603         [ #  # ]:          0 :             aLine.append( "/Dest" );
    4604         [ #  # ]:          0 :             appendDest( rLink.m_nDest, aLine );
    4605                 :            :         }
    4606                 :            :         else
    4607                 :            :         {
    4608                 :            : /*--->i56629
    4609                 :            : destination is external to the document, so
    4610                 :            : we check in the following sequence:
    4611                 :            : 
    4612                 :            :  if target type is neither .pdf, nor .od[tpgs], then
    4613                 :            :           check if relative or absolute and act accordingly (use URI or 'launch application' as requested)
    4614                 :            :                              end processing
    4615                 :            :  else if target is .od[tpgs]: then
    4616                 :            :       if conversion of type from od[tpgs]  to pdf is requested, convert it and this becomes the new target file
    4617                 :            :       processing continue
    4618                 :            : 
    4619                 :            :  if (new)target is .pdf : then
    4620                 :            :      if GotToR is requested, then
    4621                 :            :            convert the target in GoToR where the fragment of the URI is
    4622                 :            :            considered the named destination in the target file, set relative or absolute as requested
    4623                 :            :      else strip the fragment from URL and then set URI or 'launch application' as requested
    4624                 :            : */
    4625                 :            : //
    4626                 :            : // FIXME: check if the decode mechanisms for URL processing throughout this implementation
    4627                 :            : // are the correct one!!
    4628                 :            : //
    4629                 :            : // extract target file type
    4630         [ #  # ]:          0 :             INetURLObject aDocumentURL( m_aContext.BaseURL );
    4631         [ #  # ]:          0 :             INetURLObject aTargetURL( rLink.m_aURL );
    4632                 :          0 :             sal_Int32   nSetGoToRMode = 0;
    4633                 :          0 :             sal_Bool    bTargetHasPDFExtension = sal_False;
    4634                 :          0 :             INetProtocol eTargetProtocol = aTargetURL.GetProtocol();
    4635                 :          0 :             sal_Bool    bIsUNCPath = sal_False;
    4636                 :            : // check if the protocol is a known one, or if there is no protocol at all (on target only)
    4637                 :            : // if there is no protocol, make the target relative to the current document directory
    4638                 :            : // getting the needed URL information from the current document path
    4639         [ #  # ]:          0 :             if( eTargetProtocol == INET_PROT_NOT_VALID )
    4640                 :            :             {
    4641 [ #  # ][ #  # ]:          0 :                 if( rLink.m_aURL.getLength() > 4 && rLink.m_aURL.compareToAscii( "\\\\\\\\", 4 ) == 0)
                 [ #  # ]
    4642                 :            :                 {
    4643                 :          0 :                     bIsUNCPath = sal_True;
    4644                 :            :                 }
    4645                 :            :                 else
    4646                 :            :                 {
    4647         [ #  # ]:          0 :                     INetURLObject aNewBase( aDocumentURL );//duplicate document URL
    4648         [ #  # ]:          0 :                     aNewBase.removeSegment(); //remove last segment from it, obtaining the base URL of the
    4649                 :            :                                               //target document
    4650         [ #  # ]:          0 :                     aNewBase.insertName( rLink.m_aURL );
    4651         [ #  # ]:          0 :                     aTargetURL = aNewBase;//reassign the new target URL
    4652                 :            : //recompute the target protocol, with the new URL
    4653                 :            : //normal URL processing resumes
    4654         [ #  # ]:          0 :                     eTargetProtocol = aTargetURL.GetProtocol();
    4655                 :            :                 }
    4656                 :            :             }
    4657                 :            : 
    4658         [ #  # ]:          0 :             rtl::OUString aFileExtension = aTargetURL.GetFileExtension();
    4659                 :            : 
    4660                 :            : // Check if the URL ends in '/': if yes it's a directory,
    4661                 :            : // it will be forced to a URI link.
    4662                 :            : // possibly a malformed URI, leave it as it is, force as URI
    4663 [ #  # ][ #  # ]:          0 :             if( aTargetURL.hasFinalSlash() )
    4664                 :          0 :                 m_aContext.DefaultLinkAction = PDFWriter::URIAction;
    4665                 :            : 
    4666         [ #  # ]:          0 :             if( !aFileExtension.isEmpty() )
    4667                 :            :             {
    4668         [ #  # ]:          0 :                 if( m_aContext.ConvertOOoTargetToPDFTarget )
    4669                 :            :                 {
    4670                 :          0 :                     sal_Int32 bChangeFileExtensionToPDF = false;
    4671                 :            :                     //examine the file type (.odm .odt. .odp, odg, ods)
    4672         [ #  # ]:          0 :                     if( aFileExtension.equalsIgnoreAsciiCase(rtl::OUString( "odm"  ) ) )
    4673                 :          0 :                         bChangeFileExtensionToPDF = true;
    4674         [ #  # ]:          0 :                     if( aFileExtension.equalsIgnoreAsciiCase(rtl::OUString( "odt"  ) ) )
    4675                 :          0 :                         bChangeFileExtensionToPDF = true;
    4676         [ #  # ]:          0 :                     else if( aFileExtension.equalsIgnoreAsciiCase(rtl::OUString( "odp"  ) ) )
    4677                 :          0 :                         bChangeFileExtensionToPDF = true;
    4678         [ #  # ]:          0 :                     else if( aFileExtension.equalsIgnoreAsciiCase(rtl::OUString( "odg"  ) ) )
    4679                 :          0 :                         bChangeFileExtensionToPDF = true;
    4680         [ #  # ]:          0 :                     else if( aFileExtension.equalsIgnoreAsciiCase(rtl::OUString( "ods"  ) ) )
    4681                 :          0 :                         bChangeFileExtensionToPDF = true;
    4682         [ #  # ]:          0 :                     if( bChangeFileExtensionToPDF )
    4683         [ #  # ]:          0 :                         aTargetURL.setExtension(rtl::OUString( "pdf"  ) );
    4684                 :            :                 }
    4685                 :            : //check if extension is pdf, see if GoToR should be forced
    4686         [ #  # ]:          0 :                 bTargetHasPDFExtension = aTargetURL.GetFileExtension().equalsIgnoreAsciiCase(rtl::OUString( "pdf"  ) );
    4687 [ #  # ][ #  # ]:          0 :                 if( m_aContext.ForcePDFAction && bTargetHasPDFExtension )
    4688                 :          0 :                     nSetGoToRMode++;
    4689                 :            :             }
    4690                 :            : //prepare the URL, if relative or not
    4691                 :          0 :             INetProtocol eBaseProtocol = aDocumentURL.GetProtocol();
    4692                 :            : //queue the string common to all types of actions
    4693         [ #  # ]:          0 :             aLine.append( "/A<</Type/Action/S");
    4694         [ #  # ]:          0 :             if( bIsUNCPath ) // handle Win UNC paths
    4695                 :            :             {
    4696         [ #  # ]:          0 :                 aLine.append( "/Launch/Win<</F" );
    4697                 :            :                 // INetURLObject is not good with UNC paths, use original path
    4698 [ #  # ][ #  # ]:          0 :                 appendLiteralStringEncrypt(  rLink.m_aURL, rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
    4699         [ #  # ]:          0 :                 aLine.append( ">>" );
    4700                 :            :             }
    4701                 :            :             else
    4702                 :            :             {
    4703                 :          0 :                 bool bSetRelative = false;
    4704                 :          0 :                 bool bFileSpec = false;
    4705                 :            : //check if relative file link is requested and if the protocol is 'file://'
    4706 [ #  # ][ #  # ]:          0 :                 if( m_aContext.RelFsys && eBaseProtocol == eTargetProtocol && eTargetProtocol == INET_PROT_FILE )
                 [ #  # ]
    4707                 :          0 :                     bSetRelative = true;
    4708                 :            : 
    4709         [ #  # ]:          0 :                 rtl::OUString aFragment = aTargetURL.GetMark( INetURLObject::NO_DECODE /*DECODE_WITH_CHARSET*/ ); //fragment as is,
    4710         [ #  # ]:          0 :                 if( nSetGoToRMode == 0 )
    4711                 :            :                 {
    4712         [ #  # ]:          0 :                     switch( m_aContext.DefaultLinkAction )
    4713                 :            :                     {
    4714                 :            :                     default:
    4715                 :            :                     case PDFWriter::URIAction :
    4716                 :            :                     case PDFWriter::URIActionDestination :
    4717         [ #  # ]:          0 :                         aLine.append( "/URI/URI" );
    4718                 :          0 :                         break;
    4719                 :            :                     case PDFWriter::LaunchAction:
    4720                 :            : // now:
    4721                 :            : // if a launch action is requested and the hyperlink target has a fragment
    4722                 :            : // and the target file does not have a pdf extension, or it's not a 'file:://' protocol
    4723                 :            : // then force the uri action on it
    4724                 :            : // This code will permit the correct opening of application on web pages, the one that
    4725                 :            : // normally have fragments (but I may be wrong...)
    4726                 :            : // and will force the use of URI when the protocol is not file://
    4727 [ #  # ][ #  # ]:          0 :                         if( (!aFragment.isEmpty() && !bTargetHasPDFExtension) ||
         [ #  # ][ #  # ]
    4728                 :            :                                         eTargetProtocol != INET_PROT_FILE )
    4729                 :            :                         {
    4730         [ #  # ]:          0 :                             aLine.append( "/URI/URI" );
    4731                 :            :                         }
    4732                 :            :                         else
    4733                 :            :                         {
    4734         [ #  # ]:          0 :                             aLine.append( "/Launch/F" );
    4735                 :          0 :                             bFileSpec = true;
    4736                 :            :                         }
    4737                 :          0 :                         break;
    4738                 :            :                     }
    4739                 :            :                 }
    4740                 :            : //fragment are encoded in the same way as in the named destination processing
    4741         [ #  # ]:          0 :                 if( nSetGoToRMode )
    4742                 :            :                 {
    4743                 :            :                     //add the fragment
    4744         [ #  # ]:          0 :                     rtl::OUString aURLNoMark = aTargetURL.GetURLNoMark( INetURLObject::DECODE_WITH_CHARSET );
    4745         [ #  # ]:          0 :                     aLine.append("/GoToR");
    4746         [ #  # ]:          0 :                     aLine.append("/F");
    4747                 :          0 :                     bFileSpec = true;
    4748                 :            :                     appendLiteralStringEncrypt( bSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURLNoMark,
    4749                 :            :                                                                                          INetURLObject::WAS_ENCODED,
    4750                 :            :                                                                                          INetURLObject::DECODE_WITH_CHARSET ) :
    4751 [ #  # ][ #  # ]:          0 :                                                                    aURLNoMark, rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
         [ #  # ][ #  # ]
    4752         [ #  # ]:          0 :                     if( !aFragment.isEmpty() )
    4753                 :            :                     {
    4754         [ #  # ]:          0 :                         aLine.append("/D/");
    4755         [ #  # ]:          0 :                         appendDestinationName( aFragment , aLine );
    4756                 :          0 :                     }
    4757                 :            :                 }
    4758                 :            :                 else
    4759                 :            :                 {
    4760                 :            : // change the fragment to accomodate the bookmark (only if the file extension is PDF and
    4761                 :            : // the requested action is of the correct type)
    4762         [ #  # ]:          0 :                     if(m_aContext.DefaultLinkAction == PDFWriter::URIActionDestination &&
           [ #  #  #  # ]
                 [ #  # ]
    4763                 :          0 :                                bTargetHasPDFExtension && !aFragment.isEmpty() )
    4764                 :            :                     {
    4765                 :          0 :                         OStringBuffer aLineLoc( 1024 );
    4766         [ #  # ]:          0 :                         appendDestinationName( aFragment , aLineLoc );
    4767                 :            : //substitute the fragment
    4768         [ #  # ]:          0 :                         aTargetURL.SetMark( aLineLoc.getStr() );
    4769                 :            :                     }
    4770 [ #  # ][ #  # ]:          0 :                     rtl::OUString aURL = aTargetURL.GetMainURL( bFileSpec ? INetURLObject::DECODE_WITH_CHARSET : INetURLObject::NO_DECODE );
    4771                 :            :                     appendLiteralStringEncrypt(bSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURL,
    4772                 :            :                                                                                         INetURLObject::WAS_ENCODED,
    4773                 :            :                                                                                             bFileSpec ? INetURLObject::DECODE_WITH_CHARSET : INetURLObject::NO_DECODE
    4774                 :            :                                                                                             ) :
    4775 [ #  # ][ #  # ]:          0 :                                                                                aURL , rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
         [ #  # ][ #  # ]
                 [ #  # ]
    4776                 :          0 :                 }
    4777                 :            : //<--- i56629
    4778                 :            :             }
    4779 [ #  # ][ #  # ]:          0 :             aLine.append( ">>\n" );
                 [ #  # ]
    4780                 :            :         }
    4781         [ #  # ]:          0 :         if( rLink.m_nStructParent > 0 )
    4782                 :            :         {
    4783         [ #  # ]:          0 :             aLine.append( "/StructParent " );
    4784         [ #  # ]:          0 :             aLine.append( rLink.m_nStructParent );
    4785                 :            :         }
    4786         [ #  # ]:          0 :         aLine.append( ">>\nendobj\n\n" );
    4787 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4788         [ #  # ]:          0 :     }
    4789                 :            : 
    4790                 :          0 :     return true;
    4791                 :            : }
    4792                 :            : 
    4793                 :          0 : bool PDFWriterImpl::emitNoteAnnotations()
    4794                 :            : {
    4795                 :            :     // emit note annotations
    4796                 :          0 :     int nAnnots = m_aNotes.size();
    4797         [ #  # ]:          0 :     for( int i = 0; i < nAnnots; i++ )
    4798                 :            :     {
    4799                 :          0 :         const PDFNoteEntry& rNote       = m_aNotes[i];
    4800 [ #  # ][ #  # ]:          0 :         if( ! updateObject( rNote.m_nObject ) )
    4801                 :          0 :             return false;
    4802                 :            : 
    4803                 :          0 :         OStringBuffer aLine( 1024 );
    4804         [ #  # ]:          0 :         aLine.append( rNote.m_nObject );
    4805         [ #  # ]:          0 :         aLine.append( " 0 obj\n" );
    4806                 :            : //i59651  key /F set bits Print to 1 rest to 0. We don't set NoZoom NoRotate to 1, since it's a 'should'
    4807                 :            : // see PDF 8.4.2 and ISO 19005-1:2005 6.5.3
    4808         [ #  # ]:          0 :         aLine.append( "<</Type/Annot" );
    4809         [ #  # ]:          0 :         if( m_bIsPDF_A1 )
    4810         [ #  # ]:          0 :             aLine.append( "/F 4" );
    4811         [ #  # ]:          0 :         aLine.append( "/Subtype/Text/Rect[" );
    4812                 :            : 
    4813         [ #  # ]:          0 :         appendFixedInt( rNote.m_aRect.Left(), aLine );
    4814         [ #  # ]:          0 :         aLine.append( ' ' );
    4815         [ #  # ]:          0 :         appendFixedInt( rNote.m_aRect.Top(), aLine );
    4816         [ #  # ]:          0 :         aLine.append( ' ' );
    4817         [ #  # ]:          0 :         appendFixedInt( rNote.m_aRect.Right(), aLine );
    4818         [ #  # ]:          0 :         aLine.append( ' ' );
    4819         [ #  # ]:          0 :         appendFixedInt( rNote.m_aRect.Bottom(), aLine );
    4820         [ #  # ]:          0 :         aLine.append( "]" );
    4821                 :            : 
    4822                 :            :         // contents of the note (type text string)
    4823         [ #  # ]:          0 :         aLine.append( "/Contents\n" );
    4824 [ #  # ][ #  # ]:          0 :         appendUnicodeTextStringEncrypt( rNote.m_aContents.Contents, rNote.m_nObject, aLine );
    4825         [ #  # ]:          0 :         aLine.append( "\n" );
    4826                 :            : 
    4827                 :            :         // optional title
    4828         [ #  # ]:          0 :         if( rNote.m_aContents.Title.Len() )
    4829                 :            :         {
    4830         [ #  # ]:          0 :             aLine.append( "/T" );
    4831 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( rNote.m_aContents.Title, rNote.m_nObject, aLine );
    4832         [ #  # ]:          0 :             aLine.append( "\n" );
    4833                 :            :         }
    4834                 :            : 
    4835         [ #  # ]:          0 :         aLine.append( ">>\nendobj\n\n" );
    4836 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    4837         [ #  # ]:          0 :     }
    4838                 :          0 :     return true;
    4839                 :            : }
    4840                 :            : 
    4841                 :          0 : Font PDFWriterImpl::replaceFont( const Font& rControlFont, const Font&  rAppSetFont )
    4842                 :            : {
    4843                 :          0 :     bool bAdjustSize = false;
    4844                 :            : 
    4845                 :          0 :     Font aFont( rControlFont );
    4846 [ #  # ][ #  # ]:          0 :     if( ! aFont.GetName().Len() )
    4847                 :            :     {
    4848         [ #  # ]:          0 :         aFont = rAppSetFont;
    4849 [ #  # ][ #  # ]:          0 :         if( rControlFont.GetHeight() )
    4850 [ #  # ][ #  # ]:          0 :             aFont.SetSize( Size( 0, rControlFont.GetHeight() ) );
    4851                 :            :         else
    4852                 :          0 :             bAdjustSize = true;
    4853 [ #  # ][ #  # ]:          0 :         if( rControlFont.GetItalic() != ITALIC_DONTKNOW )
    4854 [ #  # ][ #  # ]:          0 :             aFont.SetItalic( rControlFont.GetItalic() );
    4855 [ #  # ][ #  # ]:          0 :         if( rControlFont.GetWeight() != WEIGHT_DONTKNOW )
    4856 [ #  # ][ #  # ]:          0 :             aFont.SetWeight( rControlFont.GetWeight() );
    4857                 :            :     }
    4858 [ #  # ][ #  # ]:          0 :     else if( ! aFont.GetHeight() )
    4859                 :            :     {
    4860 [ #  # ][ #  # ]:          0 :         aFont.SetSize( rAppSetFont.GetSize() );
    4861                 :          0 :         bAdjustSize = true;
    4862                 :            :     }
    4863         [ #  # ]:          0 :     if( bAdjustSize )
    4864                 :            :     {
    4865         [ #  # ]:          0 :         Size aFontSize = aFont.GetSize();
    4866         [ #  # ]:          0 :         OutputDevice* pDefDev = Application::GetDefaultDevice();
    4867 [ #  # ][ #  # ]:          0 :         aFontSize = OutputDevice::LogicToLogic( aFontSize, pDefDev->GetMapMode(), getMapMode() );
    4868         [ #  # ]:          0 :         aFont.SetSize( aFontSize );
    4869                 :            :     }
    4870                 :          0 :     return aFont;
    4871                 :            : }
    4872                 :            : 
    4873                 :          0 : sal_Int32 PDFWriterImpl::getBestBuiltinFont( const Font& rFont )
    4874                 :            : {
    4875                 :          0 :     sal_Int32 nBest = 4; // default to Helvetica
    4876 [ #  # ][ #  # ]:          0 :     OUString aFontName( rFont.GetName() );
    4877                 :          0 :     aFontName = aFontName.toAsciiLowerCase();
    4878                 :            : 
    4879         [ #  # ]:          0 :     if( aFontName.indexOf( "times" ) != -1 )
    4880                 :          0 :         nBest = 8;
    4881         [ #  # ]:          0 :     else if( aFontName.indexOf( "courier" ) != -1 )
    4882                 :          0 :         nBest = 0;
    4883         [ #  # ]:          0 :     else if( aFontName.indexOf( "dingbats" ) != -1 )
    4884                 :          0 :         nBest = 13;
    4885         [ #  # ]:          0 :     else if( aFontName.indexOf( "symbol" ) != -1 )
    4886                 :          0 :         nBest = 12;
    4887         [ #  # ]:          0 :     if( nBest < 12 )
    4888                 :            :     {
    4889 [ #  # ][ #  # ]:          0 :         if( rFont.GetItalic() == ITALIC_OBLIQUE || rFont.GetItalic() == ITALIC_NORMAL )
         [ #  # ][ #  # ]
                 [ #  # ]
    4890                 :          0 :             nBest += 1;
    4891 [ #  # ][ #  # ]:          0 :         if( rFont.GetWeight() > WEIGHT_MEDIUM )
    4892                 :          0 :             nBest += 2;
    4893                 :            :     }
    4894                 :            : 
    4895 [ #  # ][ #  # ]:          0 :     if( m_aBuiltinFontToObjectMap.find( nBest ) == m_aBuiltinFontToObjectMap.end() )
                 [ #  # ]
    4896 [ #  # ][ #  # ]:          0 :         m_aBuiltinFontToObjectMap[ nBest ] = createObject();
    4897                 :            : 
    4898                 :          0 :     return nBest;
    4899                 :            : }
    4900                 :            : 
    4901                 :          0 : static inline const Color& replaceColor( const Color& rCol1, const Color& rCol2 )
    4902                 :            : {
    4903         [ #  # ]:          0 :     return (rCol1 == Color( COL_TRANSPARENT )) ? rCol2 : rCol1;
    4904                 :            : }
    4905                 :            : 
    4906                 :          0 : void PDFWriterImpl::createDefaultPushButtonAppearance( PDFWidget& rButton, const PDFWriter::PushButtonWidget& rWidget )
    4907                 :            : {
    4908         [ #  # ]:          0 :     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    4909                 :            : 
    4910                 :            :     // save graphics state
    4911         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    4912                 :            : 
    4913                 :            :     // transform relative to control's coordinates since an
    4914                 :            :     // appearance stream is a form XObject
    4915                 :            :     // this relies on the m_aRect member of rButton NOT already being transformed
    4916                 :            :     // to default user space
    4917 [ #  # ][ #  # ]:          0 :     if( rWidget.Background || rWidget.Border )
    4918                 :            :     {
    4919 [ #  # ][ #  # ]:          0 :         setLineColor( rWidget.Border ? replaceColor( rWidget.BorderColor, rSettings.GetLightColor() ) : Color( COL_TRANSPARENT ) );
    4920 [ #  # ][ #  # ]:          0 :         setFillColor( rWidget.Background ? replaceColor( rWidget.BackgroundColor, rSettings.GetDialogColor() ) : Color( COL_TRANSPARENT ) );
    4921         [ #  # ]:          0 :         drawRectangle( rWidget.Location );
    4922                 :            :     }
    4923                 :            :     // prepare font to use
    4924         [ #  # ]:          0 :     Font aFont = replaceFont( rWidget.TextFont, rSettings.GetPushButtonFont() );
    4925         [ #  # ]:          0 :     setFont( aFont );
    4926         [ #  # ]:          0 :     setTextColor( replaceColor( rWidget.TextColor, rSettings.GetButtonTextColor() ) );
    4927                 :            : 
    4928 [ #  # ][ #  # ]:          0 :     drawText( rButton.m_aRect, rButton.m_aText, rButton.m_nTextStyle );
                 [ #  # ]
    4929                 :            : 
    4930                 :            :     // create DA string while local mapmode is still in place
    4931                 :            :     // (that is before endRedirect())
    4932                 :          0 :     OStringBuffer aDA( 256 );
    4933         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetButtonTextColor() ), aDA );
    4934 [ #  # ][ #  # ]:          0 :     Font aDummyFont( String( RTL_CONSTASCII_USTRINGPARAM( "Helvetica" ) ), aFont.GetSize() );
         [ #  # ][ #  # ]
    4935         [ #  # ]:          0 :     sal_Int32 nDummyBuiltin = getBestBuiltinFont( aDummyFont );
    4936         [ #  # ]:          0 :     aDA.append( ' ' );
    4937 [ #  # ][ #  # ]:          0 :     aDA.append( m_aBuiltinFonts[nDummyBuiltin].getNameObject() );
    4938         [ #  # ]:          0 :     aDA.append( ' ' );
    4939 [ #  # ][ #  # ]:          0 :     m_aPages[m_nCurrentPage].appendMappedLength( sal_Int32( aFont.GetHeight() ), aDA );
    4940         [ #  # ]:          0 :     aDA.append( " Tf" );
    4941                 :          0 :     rButton.m_aDAString = aDA.makeStringAndClear();
    4942                 :            : 
    4943         [ #  # ]:          0 :     pop();
    4944                 :            : 
    4945 [ #  # ][ #  # ]:          0 :     rButton.m_aAppearances[ "N" ][ "Standard" ] = new SvMemoryStream();
         [ #  # ][ #  # ]
    4946                 :            : 
    4947                 :            :     /* seems like a bad hack but at least works in both AR5 and 6:
    4948                 :            :        we draw the button ourselves and tell AR
    4949                 :            :        the button would be totally transparent with no text
    4950                 :            : 
    4951                 :            :        One would expect that simply setting a normal appearance
    4952                 :            :        should suffice, but no, as soon as the user actually presses
    4953                 :            :        the button and an action is tied to it (gasp! a button that
    4954                 :            :        does something) the appearance gets replaced by some crap that AR
    4955                 :            :        creates on the fly even if no DA or MK is given. On AR6 at least
    4956                 :            :        the DA and MK work as expected, but on AR5 this creates a region
    4957                 :            :        filled with the background color but nor text. Urgh.
    4958                 :            :     */
    4959                 :          0 :     rButton.m_aMKDict = "/BC [] /BG [] /CA";
    4960 [ #  # ][ #  # ]:          0 :     rButton.m_aMKDictCAString = "";
    4961                 :          0 : }
    4962                 :            : 
    4963                 :          0 : Font PDFWriterImpl::drawFieldBorder( PDFWidget& rIntern,
    4964                 :            :                                      const PDFWriter::AnyWidget& rWidget,
    4965                 :            :                                      const StyleSettings& rSettings )
    4966                 :            : {
    4967                 :          0 :     Font aFont = replaceFont( rWidget.TextFont, rSettings.GetFieldFont() );
    4968                 :            : 
    4969 [ #  # ][ #  # ]:          0 :     if( rWidget.Background || rWidget.Border )
    4970                 :            :     {
    4971 [ #  # ][ #  # ]:          0 :         if( rWidget.Border && rWidget.BorderColor == Color( COL_TRANSPARENT ) )
         [ #  # ][ #  # ]
    4972                 :            :         {
    4973         [ #  # ]:          0 :             sal_Int32 nDelta = getReferenceDevice()->ImplGetDPIX() / 500;
    4974         [ #  # ]:          0 :             if( nDelta < 1 )
    4975                 :          0 :                 nDelta = 1;
    4976         [ #  # ]:          0 :             setLineColor( Color( COL_TRANSPARENT ) );
    4977                 :          0 :             Rectangle aRect = rIntern.m_aRect;
    4978         [ #  # ]:          0 :             setFillColor( rSettings.GetLightBorderColor() );
    4979         [ #  # ]:          0 :             drawRectangle( aRect );
    4980                 :          0 :             aRect.Left()  += nDelta; aRect.Top()     += nDelta;
    4981                 :          0 :             aRect.Right() -= nDelta; aRect.Bottom()  -= nDelta;
    4982         [ #  # ]:          0 :             setFillColor( rSettings.GetFieldColor() );
    4983         [ #  # ]:          0 :             drawRectangle( aRect );
    4984         [ #  # ]:          0 :             setFillColor( rSettings.GetLightColor() );
    4985 [ #  # ][ #  # ]:          0 :             drawRectangle( Rectangle( Point( aRect.Left(), aRect.Bottom()-nDelta ), aRect.BottomRight() ) );
                 [ #  # ]
    4986 [ #  # ][ #  # ]:          0 :             drawRectangle( Rectangle( Point( aRect.Right()-nDelta, aRect.Top() ), aRect.BottomRight() ) );
                 [ #  # ]
    4987         [ #  # ]:          0 :             setFillColor( rSettings.GetDarkShadowColor() );
    4988 [ #  # ][ #  # ]:          0 :             drawRectangle( Rectangle( aRect.TopLeft(), Point( aRect.Left()+nDelta, aRect.Bottom() ) ) );
    4989 [ #  # ][ #  # ]:          0 :             drawRectangle( Rectangle( aRect.TopLeft(), Point( aRect.Right(), aRect.Top()+nDelta ) ) );
    4990                 :            :         }
    4991                 :            :         else
    4992                 :            :         {
    4993 [ #  # ][ #  # ]:          0 :             setLineColor( rWidget.Border ? replaceColor( rWidget.BorderColor, rSettings.GetShadowColor() ) : Color( COL_TRANSPARENT ) );
    4994 [ #  # ][ #  # ]:          0 :             setFillColor( rWidget.Background ? replaceColor( rWidget.BackgroundColor, rSettings.GetFieldColor() ) : Color( COL_TRANSPARENT ) );
    4995         [ #  # ]:          0 :             drawRectangle( rIntern.m_aRect );
    4996                 :            :         }
    4997                 :            : 
    4998         [ #  # ]:          0 :         if( rWidget.Border )
    4999                 :            :         {
    5000                 :            :             // adjust edit area accounting for border
    5001         [ #  # ]:          0 :             sal_Int32 nDelta = aFont.GetHeight()/4;
    5002         [ #  # ]:          0 :             if( nDelta < 1 )
    5003                 :          0 :                 nDelta = 1;
    5004                 :          0 :             rIntern.m_aRect.Left()  += nDelta;
    5005                 :          0 :             rIntern.m_aRect.Top()   += nDelta;
    5006                 :          0 :             rIntern.m_aRect.Right() -= nDelta;
    5007                 :          0 :             rIntern.m_aRect.Bottom()-= nDelta;
    5008                 :            :         }
    5009                 :            :     }
    5010                 :          0 :     return aFont;
    5011                 :            : }
    5012                 :            : 
    5013                 :          0 : void PDFWriterImpl::createDefaultEditAppearance( PDFWidget& rEdit, const PDFWriter::EditWidget& rWidget )
    5014                 :            : {
    5015         [ #  # ]:          0 :     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    5016 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pEditStream = new SvMemoryStream( 1024, 1024 );
    5017                 :            : 
    5018         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    5019                 :            : 
    5020                 :            :     // prepare font to use, draw field border
    5021         [ #  # ]:          0 :     Font aFont = drawFieldBorder( rEdit, rWidget, rSettings );
    5022 [ #  # ][ #  # ]:          0 :     sal_Int32 nBest = m_aContext.FieldsUseSystemFonts ? getSystemFont( aFont ): getBestBuiltinFont( aFont );
                 [ #  # ]
    5023                 :            : 
    5024                 :            :     // prepare DA string
    5025                 :          0 :     OStringBuffer aDA( 32 );
    5026         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetFieldTextColor() ), aDA );
    5027         [ #  # ]:          0 :     aDA.append( ' ' );
    5028         [ #  # ]:          0 :     if( m_aContext.FieldsUseSystemFonts )
    5029                 :            :     {
    5030         [ #  # ]:          0 :         aDA.append( "/F" );
    5031         [ #  # ]:          0 :         aDA.append( nBest );
    5032                 :            : 
    5033                 :          0 :         OStringBuffer aDR( 32 );
    5034         [ #  # ]:          0 :         aDR.append( "/Font " );
    5035 [ #  # ][ #  # ]:          0 :         aDR.append( getFontDictObject() );
    5036         [ #  # ]:          0 :         aDR.append( " 0 R" );
    5037                 :          0 :         rEdit.m_aDRDict = aDR.makeStringAndClear();
    5038                 :            :     }
    5039                 :            :     else
    5040 [ #  # ][ #  # ]:          0 :         aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5041         [ #  # ]:          0 :     aDA.append( ' ' );
    5042 [ #  # ][ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( sal_Int32( aFont.GetHeight() ), aDA );
    5043         [ #  # ]:          0 :     aDA.append( " Tf" );
    5044                 :            : 
    5045                 :            :     /*  create an empty appearance stream, let the viewer create
    5046                 :            :         the appearance at runtime. This is because AR5 seems to
    5047                 :            :         paint the widget appearance always, and a dynamically created
    5048                 :            :         appearance on top of it. AR6 is well behaved in that regard, so
    5049                 :            :         that behaviour seems to be a bug. Anyway this empty appearance
    5050                 :            :         relies on /NeedAppearances in the AcroForm dictionary set to "true"
    5051                 :            :      */
    5052         [ #  # ]:          0 :     beginRedirect( pEditStream, rEdit.m_aRect );
    5053                 :          0 :     OStringBuffer aAppearance( 32 );
    5054         [ #  # ]:          0 :     aAppearance.append( "/Tx BMC\nEMC\n" );
    5055         [ #  # ]:          0 :     writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
    5056                 :            : 
    5057         [ #  # ]:          0 :     endRedirect();
    5058         [ #  # ]:          0 :     pop();
    5059                 :            : 
    5060 [ #  # ][ #  # ]:          0 :     rEdit.m_aAppearances[ "N" ][ "Standard" ] = pEditStream;
    5061                 :            : 
    5062         [ #  # ]:          0 :     rEdit.m_aDAString = aDA.makeStringAndClear();
    5063                 :          0 : }
    5064                 :            : 
    5065                 :          0 : void PDFWriterImpl::createDefaultListBoxAppearance( PDFWidget& rBox, const PDFWriter::ListBoxWidget& rWidget )
    5066                 :            : {
    5067         [ #  # ]:          0 :     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    5068 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pListBoxStream = new SvMemoryStream( 1024, 1024 );
    5069                 :            : 
    5070         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    5071                 :            : 
    5072                 :            :     // prepare font to use, draw field border
    5073         [ #  # ]:          0 :     Font aFont = drawFieldBorder( rBox, rWidget, rSettings );
    5074 [ #  # ][ #  # ]:          0 :     sal_Int32 nBest = m_aContext.FieldsUseSystemFonts ? getSystemFont( aFont ): getBestBuiltinFont( aFont );
                 [ #  # ]
    5075                 :            : 
    5076         [ #  # ]:          0 :     beginRedirect( pListBoxStream, rBox.m_aRect );
    5077                 :          0 :     OStringBuffer aAppearance( 64 );
    5078                 :            : 
    5079         [ #  # ]:          0 :     setLineColor( Color( COL_TRANSPARENT ) );
    5080         [ #  # ]:          0 :     setFillColor( replaceColor( rWidget.BackgroundColor, rSettings.GetFieldColor() ) );
    5081         [ #  # ]:          0 :     drawRectangle( rBox.m_aRect );
    5082                 :            : 
    5083                 :            :     // empty appearance, see createDefaultEditAppearance for reference
    5084         [ #  # ]:          0 :     aAppearance.append( "/Tx BMC\nEMC\n" );
    5085         [ #  # ]:          0 :     writeBuffer( aAppearance.getStr(), aAppearance.getLength() );
    5086                 :            : 
    5087         [ #  # ]:          0 :     endRedirect();
    5088         [ #  # ]:          0 :     pop();
    5089                 :            : 
    5090 [ #  # ][ #  # ]:          0 :     rBox.m_aAppearances[ "N" ][ "Standard" ] = pListBoxStream;
    5091                 :            : 
    5092                 :            :     // prepare DA string
    5093                 :          0 :     OStringBuffer aDA( 256 );
    5094                 :            :     // prepare DA string
    5095         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetFieldTextColor() ), aDA );
    5096         [ #  # ]:          0 :     aDA.append( ' ' );
    5097         [ #  # ]:          0 :     if( m_aContext.FieldsUseSystemFonts )
    5098                 :            :     {
    5099         [ #  # ]:          0 :         aDA.append( "/F" );
    5100         [ #  # ]:          0 :         aDA.append( nBest );
    5101                 :            : 
    5102                 :          0 :         OStringBuffer aDR( 32 );
    5103         [ #  # ]:          0 :         aDR.append( "/Font " );
    5104 [ #  # ][ #  # ]:          0 :         aDR.append( getFontDictObject() );
    5105         [ #  # ]:          0 :         aDR.append( " 0 R" );
    5106                 :          0 :         rBox.m_aDRDict = aDR.makeStringAndClear();
    5107                 :            :     }
    5108                 :            :     else
    5109 [ #  # ][ #  # ]:          0 :         aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5110         [ #  # ]:          0 :     aDA.append( ' ' );
    5111 [ #  # ][ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( sal_Int32( aFont.GetHeight() ), aDA );
    5112         [ #  # ]:          0 :     aDA.append( " Tf" );
    5113         [ #  # ]:          0 :     rBox.m_aDAString = aDA.makeStringAndClear();
    5114                 :          0 : }
    5115                 :            : 
    5116                 :          0 : void PDFWriterImpl::createDefaultCheckBoxAppearance( PDFWidget& rBox, const PDFWriter::CheckBoxWidget& rWidget )
    5117                 :            : {
    5118         [ #  # ]:          0 :     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    5119                 :            : 
    5120                 :            :     // save graphics state
    5121         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    5122                 :            : 
    5123 [ #  # ][ #  # ]:          0 :     if( rWidget.Background || rWidget.Border )
    5124                 :            :     {
    5125 [ #  # ][ #  # ]:          0 :         setLineColor( rWidget.Border ? replaceColor( rWidget.BorderColor, rSettings.GetCheckedColor() ) : Color( COL_TRANSPARENT ) );
    5126 [ #  # ][ #  # ]:          0 :         setFillColor( rWidget.Background ? replaceColor( rWidget.BackgroundColor, rSettings.GetFieldColor() ) : Color( COL_TRANSPARENT ) );
    5127         [ #  # ]:          0 :         drawRectangle( rBox.m_aRect );
    5128                 :            :     }
    5129                 :            : 
    5130         [ #  # ]:          0 :     Font aFont = replaceFont( rWidget.TextFont, rSettings.GetRadioCheckFont() );
    5131         [ #  # ]:          0 :     setFont( aFont );
    5132         [ #  # ]:          0 :     Size aFontSize = aFont.GetSize();
    5133 [ #  # ][ #  # ]:          0 :     if( aFontSize.Height() > rBox.m_aRect.GetHeight() )
    5134         [ #  # ]:          0 :         aFontSize.Height() = rBox.m_aRect.GetHeight();
    5135                 :          0 :     sal_Int32 nDelta = aFontSize.Height()/10;
    5136         [ #  # ]:          0 :     if( nDelta < 1 )
    5137                 :          0 :         nDelta = 1;
    5138                 :            : 
    5139 [ #  # ][ #  # ]:          0 :     Rectangle aCheckRect, aTextRect;
    5140         [ #  # ]:          0 :     if( rWidget.ButtonIsLeft )
    5141                 :            :     {
    5142                 :          0 :         aCheckRect.Left()   = rBox.m_aRect.Left() + nDelta;
    5143         [ #  # ]:          0 :         aCheckRect.Top()    = rBox.m_aRect.Top() + (rBox.m_aRect.GetHeight()-aFontSize.Height())/2;
    5144                 :          0 :         aCheckRect.Right()  = aCheckRect.Left() + aFontSize.Height();
    5145                 :          0 :         aCheckRect.Bottom() = aCheckRect.Top() + aFontSize.Height();
    5146                 :            : 
    5147                 :            :         // #i74206# handle small controls without text area
    5148 [ #  # ][ #  # ]:          0 :         while( aCheckRect.GetWidth() > rBox.m_aRect.GetWidth() && aCheckRect.GetWidth() > nDelta )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5149                 :            :         {
    5150                 :          0 :             aCheckRect.Right()  -= nDelta;
    5151                 :          0 :             aCheckRect.Top()    += nDelta/2;
    5152                 :          0 :             aCheckRect.Bottom() -= nDelta - (nDelta/2);
    5153                 :            :         }
    5154                 :            : 
    5155         [ #  # ]:          0 :         aTextRect.Left()    = rBox.m_aRect.Left() + aCheckRect.GetWidth()+5*nDelta;
    5156                 :          0 :         aTextRect.Top()     = rBox.m_aRect.Top();
    5157 [ #  # ][ #  # ]:          0 :         aTextRect.Right()   = aTextRect.Left() + rBox.m_aRect.GetWidth() - aCheckRect.GetWidth()-6*nDelta;
    5158                 :          0 :         aTextRect.Bottom()  = rBox.m_aRect.Bottom();
    5159                 :            :     }
    5160                 :            :     else
    5161                 :            :     {
    5162                 :          0 :         aCheckRect.Left()   = rBox.m_aRect.Right() - nDelta - aFontSize.Height();
    5163         [ #  # ]:          0 :         aCheckRect.Top()    = rBox.m_aRect.Top() + (rBox.m_aRect.GetHeight()-aFontSize.Height())/2;
    5164                 :          0 :         aCheckRect.Right()  = aCheckRect.Left() + aFontSize.Height();
    5165                 :          0 :         aCheckRect.Bottom() = aCheckRect.Top() + aFontSize.Height();
    5166                 :            : 
    5167                 :            :         // #i74206# handle small controls without text area
    5168 [ #  # ][ #  # ]:          0 :         while( aCheckRect.GetWidth() > rBox.m_aRect.GetWidth() && aCheckRect.GetWidth() > nDelta )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5169                 :            :         {
    5170                 :          0 :             aCheckRect.Left()   += nDelta;
    5171                 :          0 :             aCheckRect.Top()    += nDelta/2;
    5172                 :          0 :             aCheckRect.Bottom() -= nDelta - (nDelta/2);
    5173                 :            :         }
    5174                 :            : 
    5175                 :          0 :         aTextRect.Left()    = rBox.m_aRect.Left();
    5176                 :          0 :         aTextRect.Top()     = rBox.m_aRect.Top();
    5177 [ #  # ][ #  # ]:          0 :         aTextRect.Right()   = aTextRect.Left() + rBox.m_aRect.GetWidth() - aCheckRect.GetWidth()-6*nDelta;
    5178                 :          0 :         aTextRect.Bottom()  = rBox.m_aRect.Bottom();
    5179                 :            :     }
    5180         [ #  # ]:          0 :     setLineColor( Color( COL_BLACK ) );
    5181         [ #  # ]:          0 :     setFillColor( Color( COL_TRANSPARENT ) );
    5182                 :          0 :     OStringBuffer aLW( 32 );
    5183         [ #  # ]:          0 :     aLW.append( "q " );
    5184         [ #  # ]:          0 :     m_aPages[m_nCurrentPage].appendMappedLength( nDelta, aLW );
    5185         [ #  # ]:          0 :     aLW.append( " w " );
    5186         [ #  # ]:          0 :     writeBuffer( aLW.getStr(), aLW.getLength() );
    5187         [ #  # ]:          0 :     drawRectangle( aCheckRect );
    5188         [ #  # ]:          0 :     writeBuffer( " Q\n", 3 );
    5189         [ #  # ]:          0 :     setTextColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ) );
    5190 [ #  # ][ #  # ]:          0 :     drawText( aTextRect, rBox.m_aText, rBox.m_nTextStyle );
                 [ #  # ]
    5191                 :            : 
    5192         [ #  # ]:          0 :     pop();
    5193                 :            : 
    5194                 :          0 :     OStringBuffer aDA( 256 );
    5195         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
    5196 [ #  # ][ #  # ]:          0 :     sal_Int32 nBest = getBestBuiltinFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "ZapfDingbats" ) ), aFont.GetSize() ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5197         [ #  # ]:          0 :     aDA.append( ' ' );
    5198 [ #  # ][ #  # ]:          0 :     aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5199         [ #  # ]:          0 :     aDA.append( " 0 Tf" );
    5200                 :          0 :     rBox.m_aDAString = aDA.makeStringAndClear();
    5201                 :          0 :     rBox.m_aMKDict = "/CA";
    5202                 :          0 :     rBox.m_aMKDictCAString = "8";
    5203                 :          0 :     rBox.m_aRect = aCheckRect;
    5204                 :            : 
    5205                 :            :     // create appearance streams
    5206                 :          0 :     sal_Char cMark = '8';
    5207                 :          0 :     sal_Int32 nCharXOffset = 1000-m_aBuiltinFonts[13].m_aWidths[sal_Int32(cMark)];
    5208         [ #  # ]:          0 :     nCharXOffset *= aCheckRect.GetHeight();
    5209                 :          0 :     nCharXOffset /= 2000;
    5210                 :            :     sal_Int32 nCharYOffset = 1000-
    5211                 :          0 :         (m_aBuiltinFonts[13].m_nAscent+m_aBuiltinFonts[13].m_nDescent); // descent is negative
    5212         [ #  # ]:          0 :     nCharYOffset *= aCheckRect.GetHeight();
    5213                 :          0 :     nCharYOffset /= 2000;
    5214                 :            : 
    5215 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pCheckStream = new SvMemoryStream( 256, 256 );
    5216         [ #  # ]:          0 :     beginRedirect( pCheckStream, aCheckRect );
    5217         [ #  # ]:          0 :     aDA.append( "/Tx BMC\nq BT\n" );
    5218         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
    5219         [ #  # ]:          0 :     aDA.append( ' ' );
    5220 [ #  # ][ #  # ]:          0 :     aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5221         [ #  # ]:          0 :     aDA.append( ' ' );
    5222 [ #  # ][ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( sal_Int32( aCheckRect.GetHeight() ), aDA );
    5223         [ #  # ]:          0 :     aDA.append( " Tf\n" );
    5224         [ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( nCharXOffset, aDA );
    5225         [ #  # ]:          0 :     aDA.append( " " );
    5226         [ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( nCharYOffset, aDA );
    5227         [ #  # ]:          0 :     aDA.append( " Td (" );
    5228         [ #  # ]:          0 :     aDA.append( cMark );
    5229         [ #  # ]:          0 :     aDA.append( ") Tj\nET\nQ\nEMC\n" );
    5230         [ #  # ]:          0 :     writeBuffer( aDA.getStr(), aDA.getLength() );
    5231         [ #  # ]:          0 :     endRedirect();
    5232 [ #  # ][ #  # ]:          0 :     rBox.m_aAppearances[ "N" ][ "Yes" ] = pCheckStream;
    5233                 :            : 
    5234 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pUncheckStream = new SvMemoryStream( 256, 256 );
    5235         [ #  # ]:          0 :     beginRedirect( pUncheckStream, aCheckRect );
    5236         [ #  # ]:          0 :     writeBuffer( "/Tx BMC\nEMC\n", 12 );
    5237         [ #  # ]:          0 :     endRedirect();
    5238 [ #  # ][ #  # ]:          0 :     rBox.m_aAppearances[ "N" ][ "Off" ] = pUncheckStream;
                 [ #  # ]
    5239                 :          0 : }
    5240                 :            : 
    5241                 :          0 : void PDFWriterImpl::createDefaultRadioButtonAppearance( PDFWidget& rBox, const PDFWriter::RadioButtonWidget& rWidget )
    5242                 :            : {
    5243         [ #  # ]:          0 :     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    5244                 :            : 
    5245                 :            :     // save graphics state
    5246         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    5247                 :            : 
    5248 [ #  # ][ #  # ]:          0 :     if( rWidget.Background || rWidget.Border )
    5249                 :            :     {
    5250 [ #  # ][ #  # ]:          0 :         setLineColor( rWidget.Border ? replaceColor( rWidget.BorderColor, rSettings.GetCheckedColor() ) : Color( COL_TRANSPARENT ) );
    5251 [ #  # ][ #  # ]:          0 :         setFillColor( rWidget.Background ? replaceColor( rWidget.BackgroundColor, rSettings.GetFieldColor() ) : Color( COL_TRANSPARENT ) );
    5252         [ #  # ]:          0 :         drawRectangle( rBox.m_aRect );
    5253                 :            :     }
    5254                 :            : 
    5255         [ #  # ]:          0 :     Font aFont = replaceFont( rWidget.TextFont, rSettings.GetRadioCheckFont() );
    5256         [ #  # ]:          0 :     setFont( aFont );
    5257         [ #  # ]:          0 :     Size aFontSize = aFont.GetSize();
    5258 [ #  # ][ #  # ]:          0 :     if( aFontSize.Height() > rBox.m_aRect.GetHeight() )
    5259         [ #  # ]:          0 :         aFontSize.Height() = rBox.m_aRect.GetHeight();
    5260                 :          0 :     sal_Int32 nDelta = aFontSize.Height()/10;
    5261         [ #  # ]:          0 :     if( nDelta < 1 )
    5262                 :          0 :         nDelta = 1;
    5263                 :            : 
    5264 [ #  # ][ #  # ]:          0 :     Rectangle aCheckRect, aTextRect;
    5265         [ #  # ]:          0 :     if( rWidget.ButtonIsLeft )
    5266                 :            :     {
    5267                 :          0 :         aCheckRect.Left()   = rBox.m_aRect.Left() + nDelta;
    5268         [ #  # ]:          0 :         aCheckRect.Top()    = rBox.m_aRect.Top() + (rBox.m_aRect.GetHeight()-aFontSize.Height())/2;
    5269                 :          0 :         aCheckRect.Right()  = aCheckRect.Left() + aFontSize.Height();
    5270                 :          0 :         aCheckRect.Bottom() = aCheckRect.Top() + aFontSize.Height();
    5271                 :            : 
    5272                 :            :         // #i74206# handle small controls without text area
    5273 [ #  # ][ #  # ]:          0 :         while( aCheckRect.GetWidth() > rBox.m_aRect.GetWidth() && aCheckRect.GetWidth() > nDelta )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5274                 :            :         {
    5275                 :          0 :             aCheckRect.Right()  -= nDelta;
    5276                 :          0 :             aCheckRect.Top()    += nDelta/2;
    5277                 :          0 :             aCheckRect.Bottom() -= nDelta - (nDelta/2);
    5278                 :            :         }
    5279                 :            : 
    5280         [ #  # ]:          0 :         aTextRect.Left()    = rBox.m_aRect.Left() + aCheckRect.GetWidth()+5*nDelta;
    5281                 :          0 :         aTextRect.Top()     = rBox.m_aRect.Top();
    5282 [ #  # ][ #  # ]:          0 :         aTextRect.Right()   = aTextRect.Left() + rBox.m_aRect.GetWidth() - aCheckRect.GetWidth()-6*nDelta;
    5283                 :          0 :         aTextRect.Bottom()  = rBox.m_aRect.Bottom();
    5284                 :            :     }
    5285                 :            :     else
    5286                 :            :     {
    5287                 :          0 :         aCheckRect.Left()   = rBox.m_aRect.Right() - nDelta - aFontSize.Height();
    5288         [ #  # ]:          0 :         aCheckRect.Top()    = rBox.m_aRect.Top() + (rBox.m_aRect.GetHeight()-aFontSize.Height())/2;
    5289                 :          0 :         aCheckRect.Right()  = aCheckRect.Left() + aFontSize.Height();
    5290                 :          0 :         aCheckRect.Bottom() = aCheckRect.Top() + aFontSize.Height();
    5291                 :            : 
    5292                 :            :         // #i74206# handle small controls without text area
    5293 [ #  # ][ #  # ]:          0 :         while( aCheckRect.GetWidth() > rBox.m_aRect.GetWidth() && aCheckRect.GetWidth() > nDelta )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5294                 :            :         {
    5295                 :          0 :             aCheckRect.Left()   += nDelta;
    5296                 :          0 :             aCheckRect.Top()    += nDelta/2;
    5297                 :          0 :             aCheckRect.Bottom() -= nDelta - (nDelta/2);
    5298                 :            :         }
    5299                 :            : 
    5300                 :          0 :         aTextRect.Left()    = rBox.m_aRect.Left();
    5301                 :          0 :         aTextRect.Top()     = rBox.m_aRect.Top();
    5302 [ #  # ][ #  # ]:          0 :         aTextRect.Right()   = aTextRect.Left() + rBox.m_aRect.GetWidth() - aCheckRect.GetWidth()-6*nDelta;
    5303                 :          0 :         aTextRect.Bottom()  = rBox.m_aRect.Bottom();
    5304                 :            :     }
    5305         [ #  # ]:          0 :     setLineColor( Color( COL_BLACK ) );
    5306         [ #  # ]:          0 :     setFillColor( Color( COL_TRANSPARENT ) );
    5307                 :          0 :     OStringBuffer aLW( 32 );
    5308         [ #  # ]:          0 :     aLW.append( "q " );
    5309         [ #  # ]:          0 :     m_aPages[ m_nCurrentPage ].appendMappedLength( nDelta, aLW );
    5310         [ #  # ]:          0 :     aLW.append( " w " );
    5311         [ #  # ]:          0 :     writeBuffer( aLW.getStr(), aLW.getLength() );
    5312         [ #  # ]:          0 :     drawEllipse( aCheckRect );
    5313         [ #  # ]:          0 :     writeBuffer( " Q\n", 3 );
    5314         [ #  # ]:          0 :     setTextColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ) );
    5315 [ #  # ][ #  # ]:          0 :     drawText( aTextRect, rBox.m_aText, rBox.m_nTextStyle );
                 [ #  # ]
    5316                 :            : 
    5317         [ #  # ]:          0 :     pop();
    5318                 :            : 
    5319                 :          0 :     OStringBuffer aDA( 256 );
    5320         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
    5321 [ #  # ][ #  # ]:          0 :     sal_Int32 nBest = getBestBuiltinFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "ZapfDingbats" ) ), aFont.GetSize() ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5322         [ #  # ]:          0 :     aDA.append( ' ' );
    5323 [ #  # ][ #  # ]:          0 :     aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5324         [ #  # ]:          0 :     aDA.append( " 0 Tf" );
    5325                 :          0 :     rBox.m_aDAString = aDA.makeStringAndClear();
    5326                 :            : //to encrypt this (el)
    5327                 :          0 :     rBox.m_aMKDict = "/CA";
    5328                 :            : //after this assignement, to m_aMKDic cannot be added anything
    5329                 :          0 :     rBox.m_aMKDictCAString = "l";
    5330                 :            : 
    5331                 :          0 :     rBox.m_aRect = aCheckRect;
    5332                 :            : 
    5333                 :            :     // create appearance streams
    5334         [ #  # ]:          0 :     push( sal::static_int_cast<sal_uInt16>(~0U) );
    5335 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pCheckStream = new SvMemoryStream( 256, 256 );
    5336                 :            : 
    5337         [ #  # ]:          0 :     beginRedirect( pCheckStream, aCheckRect );
    5338         [ #  # ]:          0 :     aDA.append( "/Tx BMC\nq BT\n" );
    5339         [ #  # ]:          0 :     appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ), aDA );
    5340         [ #  # ]:          0 :     aDA.append( ' ' );
    5341 [ #  # ][ #  # ]:          0 :     aDA.append( m_aBuiltinFonts[nBest].getNameObject() );
    5342         [ #  # ]:          0 :     aDA.append( ' ' );
    5343 [ #  # ][ #  # ]:          0 :     m_aPages[m_nCurrentPage].appendMappedLength( sal_Int32( aCheckRect.GetHeight() ), aDA );
    5344         [ #  # ]:          0 :     aDA.append( " Tf\n0 0 Td\nET\nQ\n" );
    5345         [ #  # ]:          0 :     writeBuffer( aDA.getStr(), aDA.getLength() );
    5346         [ #  # ]:          0 :     setFillColor( replaceColor( rWidget.TextColor, rSettings.GetRadioCheckTextColor() ) );
    5347         [ #  # ]:          0 :     setLineColor( Color( COL_TRANSPARENT ) );
    5348                 :          0 :     aCheckRect.Left()   += 3*nDelta;
    5349                 :          0 :     aCheckRect.Top()    += 3*nDelta;
    5350                 :          0 :     aCheckRect.Bottom() -= 3*nDelta;
    5351                 :          0 :     aCheckRect.Right()  -= 3*nDelta;
    5352         [ #  # ]:          0 :     drawEllipse( aCheckRect );
    5353         [ #  # ]:          0 :     writeBuffer( "\nEMC\n", 5 );
    5354         [ #  # ]:          0 :     endRedirect();
    5355                 :            : 
    5356         [ #  # ]:          0 :     pop();
    5357 [ #  # ][ #  # ]:          0 :     rBox.m_aAppearances[ "N" ][ "Yes" ] = pCheckStream;
    5358                 :            : 
    5359 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pUncheckStream = new SvMemoryStream( 256, 256 );
    5360         [ #  # ]:          0 :     beginRedirect( pUncheckStream, aCheckRect );
    5361         [ #  # ]:          0 :     writeBuffer( "/Tx BMC\nEMC\n", 12 );
    5362         [ #  # ]:          0 :     endRedirect();
    5363 [ #  # ][ #  # ]:          0 :     rBox.m_aAppearances[ "N" ][ "Off" ] = pUncheckStream;
                 [ #  # ]
    5364                 :          0 : }
    5365                 :            : 
    5366                 :          0 : bool PDFWriterImpl::emitAppearances( PDFWidget& rWidget, OStringBuffer& rAnnotDict )
    5367                 :            : {
    5368                 :            : 
    5369                 :            :     // TODO: check and insert default streams
    5370                 :          0 :     rtl::OString aStandardAppearance;
    5371         [ #  # ]:          0 :     switch( rWidget.m_eType )
    5372                 :            :     {
    5373                 :            :         case PDFWriter::CheckBox:
    5374         [ #  # ]:          0 :             aStandardAppearance = OUStringToOString( rWidget.m_aValue, RTL_TEXTENCODING_ASCII_US );
    5375                 :          0 :             break;
    5376                 :            :         default:
    5377                 :          0 :             break;
    5378                 :            :     }
    5379                 :            : 
    5380         [ #  # ]:          0 :     if( rWidget.m_aAppearances.size() )
    5381                 :            :     {
    5382         [ #  # ]:          0 :         rAnnotDict.append( "/AP<<\n" );
    5383 [ #  # ][ #  # ]:          0 :         for( PDFAppearanceMap::iterator dict_it = rWidget.m_aAppearances.begin(); dict_it != rWidget.m_aAppearances.end(); ++dict_it )
                 [ #  # ]
    5384                 :            :         {
    5385         [ #  # ]:          0 :             rAnnotDict.append( "/" );
    5386 [ #  # ][ #  # ]:          0 :             rAnnotDict.append( dict_it->first );
    5387         [ #  # ]:          0 :             bool bUseSubDict = (dict_it->second.size() > 1);
    5388 [ #  # ][ #  # ]:          0 :             rAnnotDict.append( bUseSubDict ? "<<" : " " );
    5389                 :            : 
    5390 [ #  # ][ #  # ]:          0 :             for( PDFAppearanceStreams::const_iterator stream_it = dict_it->second.begin();
                 [ #  # ]
    5391 [ #  # ][ #  # ]:          0 :                  stream_it != dict_it->second.end(); ++stream_it )
    5392                 :            :             {
    5393         [ #  # ]:          0 :                 SvMemoryStream* pApppearanceStream = stream_it->second;
    5394 [ #  # ][ #  # ]:          0 :                 dict_it->second[ stream_it->first ] = NULL;
                 [ #  # ]
    5395                 :            : 
    5396         [ #  # ]:          0 :                 bool bDeflate = compressStream( pApppearanceStream );
    5397                 :            : 
    5398         [ #  # ]:          0 :                 pApppearanceStream->Seek( STREAM_SEEK_TO_END );
    5399                 :          0 :                 sal_Int64 nStreamLen = pApppearanceStream->Tell();
    5400         [ #  # ]:          0 :                 pApppearanceStream->Seek( STREAM_SEEK_TO_BEGIN );
    5401         [ #  # ]:          0 :                 sal_Int32 nObject = createObject();
    5402 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( updateObject( nObject ) );
    5403                 :            :                 #if OSL_DEBUG_LEVEL > 1
    5404                 :            :                 emitComment( "PDFWriterImpl::emitAppearances" );
    5405                 :            :                 #endif
    5406                 :          0 :                 OStringBuffer aLine;
    5407         [ #  # ]:          0 :                 aLine.append( nObject );
    5408                 :            : 
    5409                 :            :                 aLine.append( " 0 obj\n"
    5410                 :            :                               "<</Type/XObject\n"
    5411                 :            :                               "/Subtype/Form\n"
    5412         [ #  # ]:          0 :                               "/BBox[0 0 " );
    5413 [ #  # ][ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.GetWidth()-1, aLine );
    5414         [ #  # ]:          0 :                 aLine.append( " " );
    5415 [ #  # ][ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.GetHeight()-1, aLine );
    5416                 :            :                 aLine.append( "]\n"
    5417         [ #  # ]:          0 :                               "/Resources " );
    5418 [ #  # ][ #  # ]:          0 :                 aLine.append( getResourceDictObj() );
    5419                 :            :                 aLine.append( " 0 R\n"
    5420         [ #  # ]:          0 :                               "/Length " );
    5421         [ #  # ]:          0 :                 aLine.append( nStreamLen );
    5422         [ #  # ]:          0 :                 aLine.append( "\n" );
    5423         [ #  # ]:          0 :                 if( bDeflate )
    5424         [ #  # ]:          0 :                     aLine.append( "/Filter/FlateDecode\n" );
    5425         [ #  # ]:          0 :                 aLine.append( ">>\nstream\n" );
    5426 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    5427         [ #  # ]:          0 :                 checkAndEnableStreamEncryption( nObject );
    5428 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( pApppearanceStream->GetData(), nStreamLen ) );
                 [ #  # ]
    5429                 :          0 :                 disableStreamEncryption();
    5430 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( "\nendstream\nendobj\n\n", 19 ) );
    5431                 :            : 
    5432         [ #  # ]:          0 :                 if( bUseSubDict )
    5433                 :            :                 {
    5434         [ #  # ]:          0 :                     rAnnotDict.append( " /" );
    5435 [ #  # ][ #  # ]:          0 :                     rAnnotDict.append( stream_it->first );
    5436         [ #  # ]:          0 :                     rAnnotDict.append( " " );
    5437                 :            :                 }
    5438         [ #  # ]:          0 :                 rAnnotDict.append( nObject );
    5439         [ #  # ]:          0 :                 rAnnotDict.append( " 0 R" );
    5440                 :            : 
    5441 [ #  # ][ #  # ]:          0 :                 delete pApppearanceStream;
    5442         [ #  # ]:          0 :             }
    5443                 :            : 
    5444 [ #  # ][ #  # ]:          0 :             rAnnotDict.append( bUseSubDict ? ">>\n" : "\n" );
    5445                 :            :         }
    5446         [ #  # ]:          0 :         rAnnotDict.append( ">>\n" );
    5447         [ #  # ]:          0 :         if( !aStandardAppearance.isEmpty() )
    5448                 :            :         {
    5449         [ #  # ]:          0 :             rAnnotDict.append( "/AS /" );
    5450         [ #  # ]:          0 :             rAnnotDict.append( aStandardAppearance );
    5451         [ #  # ]:          0 :             rAnnotDict.append( "\n" );
    5452                 :            :         }
    5453                 :            :     }
    5454                 :            : 
    5455                 :          0 :     return true;
    5456                 :            : }
    5457                 :            : 
    5458                 :          0 : bool PDFWriterImpl::emitWidgetAnnotations()
    5459                 :            : {
    5460                 :          0 :     ensureUniqueRadioOnValues();
    5461                 :            : 
    5462                 :          0 :     int nAnnots = m_aWidgets.size();
    5463         [ #  # ]:          0 :     for( int a = 0; a < nAnnots; a++ )
    5464                 :            :     {
    5465                 :          0 :         PDFWidget& rWidget = m_aWidgets[a];
    5466                 :            : 
    5467                 :          0 :         OStringBuffer aLine( 1024 );
    5468                 :          0 :         OStringBuffer aValue( 256 );
    5469         [ #  # ]:          0 :         aLine.append( rWidget.m_nObject );
    5470                 :            :         aLine.append( " 0 obj\n"
    5471         [ #  # ]:          0 :                       "<<" );
    5472         [ #  # ]:          0 :         if( rWidget.m_eType != PDFWriter::Hierarchy )
    5473                 :            :         {
    5474                 :            :             // emit widget annotation only for terminal fields
    5475         [ #  # ]:          0 :             if( rWidget.m_aKids.empty() )
    5476                 :            :             {
    5477                 :            :                 int iRectMargin;
    5478                 :            : 
    5479         [ #  # ]:          0 :                 aLine.append( "/Type/Annot/Subtype/Widget/F " );
    5480                 :            : 
    5481         [ #  # ]:          0 :                 if (rWidget.m_eType == PDFWriter::Signature)
    5482                 :            :                 {
    5483         [ #  # ]:          0 :                     aLine.append( "132\n" ); // Print & Locked
    5484                 :          0 :                     iRectMargin = 0;
    5485                 :            :                 }
    5486                 :            :                 else
    5487                 :            :                 {
    5488         [ #  # ]:          0 :                     aLine.append( "4\n" );
    5489                 :          0 :                     iRectMargin = 1;
    5490                 :            :                 }
    5491                 :            : 
    5492         [ #  # ]:          0 :                 aLine.append("/Rect[" );
    5493         [ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.Left()-iRectMargin, aLine );
    5494         [ #  # ]:          0 :                 aLine.append( ' ' );
    5495         [ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.Top()+iRectMargin, aLine );
    5496         [ #  # ]:          0 :                 aLine.append( ' ' );
    5497         [ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.Right()+iRectMargin, aLine );
    5498         [ #  # ]:          0 :                 aLine.append( ' ' );
    5499         [ #  # ]:          0 :                 appendFixedInt( rWidget.m_aRect.Bottom()-iRectMargin, aLine );
    5500         [ #  # ]:          0 :                 aLine.append( "]\n" );
    5501                 :            :             }
    5502         [ #  # ]:          0 :             aLine.append( "/FT/" );
    5503   [ #  #  #  #  :          0 :             switch( rWidget.m_eType )
             #  #  #  # ]
    5504                 :            :             {
    5505                 :            :                 case PDFWriter::RadioButton:
    5506                 :            :                 case PDFWriter::CheckBox:
    5507                 :            :                     // for radio buttons only the RadioButton field, not the
    5508                 :            :                     // CheckBox children should have a value, else acrobat reader
    5509                 :            :                     // does not always check the right button
    5510                 :            :                     // of course real check boxes (not belonging to a readio group)
    5511                 :            :                     // need their values, too
    5512 [ #  # ][ #  # ]:          0 :                     if( rWidget.m_eType == PDFWriter::RadioButton || rWidget.m_nRadioGroup < 0 )
    5513                 :            :                     {
    5514         [ #  # ]:          0 :                         aValue.append( "/" );
    5515                 :            :                         // check for radio group with all buttons unpressed
    5516         [ #  # ]:          0 :                         if( rWidget.m_aValue.isEmpty() )
    5517         [ #  # ]:          0 :                             aValue.append( "Off" );
    5518                 :            :                         else
    5519         [ #  # ]:          0 :                             appendName( rWidget.m_aValue, aValue );
    5520                 :            :                     }
    5521                 :            :                 case PDFWriter::PushButton:
    5522         [ #  # ]:          0 :                     aLine.append( "Btn" );
    5523                 :          0 :                     break;
    5524                 :            :                 case PDFWriter::ListBox:
    5525         [ #  # ]:          0 :                     if( rWidget.m_nFlags & 0x200000 ) // multiselect
    5526                 :            :                     {
    5527         [ #  # ]:          0 :                         aValue.append( "[" );
    5528         [ #  # ]:          0 :                         for( unsigned int i = 0; i < rWidget.m_aSelectedEntries.size(); i++ )
    5529                 :            :                         {
    5530         [ #  # ]:          0 :                             sal_Int32 nEntry = rWidget.m_aSelectedEntries[i];
    5531 [ #  # ][ #  # ]:          0 :                             if( nEntry >= 0 && nEntry < sal_Int32(rWidget.m_aListEntries.size()) )
                 [ #  # ]
    5532         [ #  # ]:          0 :                                 appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue );
    5533                 :            :                         }
    5534         [ #  # ]:          0 :                         aValue.append( "]" );
    5535                 :            :                     }
    5536         [ #  # ]:          0 :                     else if( rWidget.m_aSelectedEntries.size() > 0 &&
           [ #  #  #  # ]
                 [ #  # ]
    5537         [ #  # ]:          0 :                              rWidget.m_aSelectedEntries[0] >= 0 &&
    5538         [ #  # ]:          0 :                              rWidget.m_aSelectedEntries[0] < sal_Int32(rWidget.m_aListEntries.size()) )
    5539                 :            :                     {
    5540 [ #  # ][ #  # ]:          0 :                         appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue );
    5541                 :            :                     }
    5542                 :            :                     else
    5543         [ #  # ]:          0 :                         appendUnicodeTextStringEncrypt( rtl::OUString(), rWidget.m_nObject, aValue );
    5544         [ #  # ]:          0 :                     aLine.append( "Ch" );
    5545                 :          0 :                     break;
    5546                 :            :                 case PDFWriter::ComboBox:
    5547         [ #  # ]:          0 :                     appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue );
    5548         [ #  # ]:          0 :                     aLine.append( "Ch" );
    5549                 :          0 :                     break;
    5550                 :            :                 case PDFWriter::Edit:
    5551         [ #  # ]:          0 :                     aLine.append( "Tx" );
    5552         [ #  # ]:          0 :                     appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue );
    5553                 :          0 :                     break;
    5554                 :            :                 case PDFWriter::Signature:
    5555         [ #  # ]:          0 :                     aLine.append( "Sig" );
    5556 [ #  # ][ #  # ]:          0 :                     aValue.append(OUStringToOString(rWidget.m_aValue, RTL_TEXTENCODING_ASCII_US));
    5557                 :          0 :                     break;
    5558                 :            :                 case PDFWriter::Hierarchy: // make the compiler happy
    5559                 :          0 :                     break;
    5560                 :            :             }
    5561         [ #  # ]:          0 :             aLine.append( "\n" );
    5562         [ #  # ]:          0 :             aLine.append( "/P " );
    5563         [ #  # ]:          0 :             aLine.append( m_aPages[ rWidget.m_nPage ].m_nPageObject );
    5564         [ #  # ]:          0 :             aLine.append( " 0 R\n" );
    5565                 :            :         }
    5566         [ #  # ]:          0 :         if( rWidget.m_nParent )
    5567                 :            :         {
    5568         [ #  # ]:          0 :             aLine.append( "/Parent " );
    5569         [ #  # ]:          0 :             aLine.append( rWidget.m_nParent );
    5570         [ #  # ]:          0 :             aLine.append( " 0 R\n" );
    5571                 :            :         }
    5572         [ #  # ]:          0 :         if( rWidget.m_aKids.size() )
    5573                 :            :         {
    5574         [ #  # ]:          0 :             aLine.append( "/Kids[" );
    5575         [ #  # ]:          0 :             for( unsigned int i = 0; i < rWidget.m_aKids.size(); i++ )
    5576                 :            :             {
    5577 [ #  # ][ #  # ]:          0 :                 aLine.append( rWidget.m_aKids[i] );
    5578         [ #  # ]:          0 :                 aLine.append( " 0 R" );
    5579 [ #  # ][ #  # ]:          0 :                 aLine.append( ( (i&15) == 15 ) ? "\n" : " " );
    5580                 :            :             }
    5581         [ #  # ]:          0 :             aLine.append( "]\n" );
    5582                 :            :         }
    5583         [ #  # ]:          0 :         if( !rWidget.m_aName.isEmpty() )
    5584                 :            :         {
    5585         [ #  # ]:          0 :             aLine.append( "/T" );
    5586         [ #  # ]:          0 :             appendLiteralStringEncrypt( rWidget.m_aName, rWidget.m_nObject, aLine );
    5587         [ #  # ]:          0 :             aLine.append( "\n" );
    5588                 :            :         }
    5589 [ #  # ][ #  # ]:          0 :         if( m_aContext.Version > PDFWriter::PDF_1_2 && !rWidget.m_aDescription.isEmpty() )
                 [ #  # ]
    5590                 :            :         {
    5591                 :            :             // the alternate field name should be unicode able since it is
    5592                 :            :             // supposed to be used in UI
    5593         [ #  # ]:          0 :             aLine.append( "/TU" );
    5594         [ #  # ]:          0 :             appendUnicodeTextStringEncrypt( rWidget.m_aDescription, rWidget.m_nObject, aLine );
    5595         [ #  # ]:          0 :             aLine.append( "\n" );
    5596                 :            :         }
    5597                 :            : 
    5598         [ #  # ]:          0 :         if( rWidget.m_nFlags )
    5599                 :            :         {
    5600         [ #  # ]:          0 :             aLine.append( "/Ff " );
    5601         [ #  # ]:          0 :             aLine.append( rWidget.m_nFlags );
    5602         [ #  # ]:          0 :             aLine.append( "\n" );
    5603                 :            :         }
    5604         [ #  # ]:          0 :         if( aValue.getLength() )
    5605                 :            :         {
    5606                 :          0 :             OString aVal = aValue.makeStringAndClear();
    5607         [ #  # ]:          0 :             aLine.append( "/V " );
    5608         [ #  # ]:          0 :             aLine.append( aVal );
    5609                 :            :             aLine.append( "\n"
    5610         [ #  # ]:          0 :                           "/DV " );
    5611         [ #  # ]:          0 :             aLine.append( aVal );
    5612         [ #  # ]:          0 :             aLine.append( "\n" );
    5613                 :            :         }
    5614 [ #  # ][ #  # ]:          0 :         if( rWidget.m_eType == PDFWriter::ListBox || rWidget.m_eType == PDFWriter::ComboBox )
    5615                 :            :         {
    5616                 :          0 :             sal_Int32 nTI = -1;
    5617         [ #  # ]:          0 :             aLine.append( "/Opt[\n" );
    5618                 :          0 :             sal_Int32 i = 0;
    5619 [ #  # ][ #  # ]:          0 :             for( std::vector< OUString >::const_iterator it = rWidget.m_aListEntries.begin(); it != rWidget.m_aListEntries.end(); ++it, ++i )
                 [ #  # ]
    5620                 :            :             {
    5621         [ #  # ]:          0 :                 appendUnicodeTextStringEncrypt( *it, rWidget.m_nObject, aLine );
    5622         [ #  # ]:          0 :                 aLine.append( "\n" );
    5623         [ #  # ]:          0 :                 if( *it == rWidget.m_aValue )
    5624                 :          0 :                     nTI = i;
    5625                 :            :             }
    5626         [ #  # ]:          0 :             aLine.append( "]\n" );
    5627         [ #  # ]:          0 :             if( nTI > 0 )
    5628                 :            :             {
    5629         [ #  # ]:          0 :                 aLine.append( "/TI " );
    5630         [ #  # ]:          0 :                 aLine.append( nTI );
    5631         [ #  # ]:          0 :                 aLine.append( "\n" );
    5632         [ #  # ]:          0 :                 if( rWidget.m_nFlags & 0x200000 ) // Multiselect
    5633                 :            :                 {
    5634         [ #  # ]:          0 :                     aLine.append( "/I [" );
    5635         [ #  # ]:          0 :                     aLine.append( nTI );
    5636         [ #  # ]:          0 :                     aLine.append( "]\n" );
    5637                 :            :                 }
    5638                 :            :             }
    5639                 :            :         }
    5640 [ #  # ][ #  # ]:          0 :         if( rWidget.m_eType == PDFWriter::Edit && rWidget.m_nMaxLen > 0 )
    5641                 :            :         {
    5642         [ #  # ]:          0 :             aLine.append( "/MaxLen " );
    5643         [ #  # ]:          0 :             aLine.append( rWidget.m_nMaxLen );
    5644         [ #  # ]:          0 :             aLine.append( "\n" );
    5645                 :            :         }
    5646         [ #  # ]:          0 :         if( rWidget.m_eType == PDFWriter::PushButton )
    5647                 :            :         {
    5648         [ #  # ]:          0 :             if(!m_bIsPDF_A1)
    5649                 :            :             {
    5650                 :          0 :                 OStringBuffer aDest;
    5651 [ #  # ][ #  # ]:          0 :                 if( rWidget.m_nDest != -1 && appendDest( m_aDestinationIdTranslation[ rWidget.m_nDest ], aDest ) )
         [ #  # ][ #  # ]
                 [ #  # ]
    5652                 :            :                 {
    5653         [ #  # ]:          0 :                     aLine.append( "/AA<</D<</Type/Action/S/GoTo/D " );
    5654         [ #  # ]:          0 :                     aLine.append( aDest.makeStringAndClear() );
    5655         [ #  # ]:          0 :                     aLine.append( ">>>>\n" );
    5656                 :            :                 }
    5657         [ #  # ]:          0 :                 else if( rWidget.m_aListEntries.empty() )
    5658                 :            :                 {
    5659                 :            :                     // create a reset form action
    5660         [ #  # ]:          0 :                     aLine.append( "/AA<</D<</Type/Action/S/ResetForm>>>>\n" );
    5661                 :            :                 }
    5662         [ #  # ]:          0 :                 else if( rWidget.m_bSubmit )
    5663                 :            :                 {
    5664                 :            :                     // create a submit form action
    5665         [ #  # ]:          0 :                     aLine.append( "/AA<</D<</Type/Action/S/SubmitForm/F" );
    5666 [ #  # ][ #  # ]:          0 :                     appendLiteralStringEncrypt( rWidget.m_aListEntries.front(), rWidget.m_nObject, aLine, osl_getThreadTextEncoding() );
                 [ #  # ]
    5667         [ #  # ]:          0 :                     aLine.append( "/Flags " );
    5668                 :            : 
    5669                 :          0 :                     sal_Int32 nFlags = 0;
    5670   [ #  #  #  # ]:          0 :                     switch( m_aContext.SubmitFormat )
    5671                 :            :                     {
    5672                 :            :                     case PDFWriter::HTML:
    5673                 :          0 :                         nFlags |= 4;
    5674                 :          0 :                         break;
    5675                 :            :                     case PDFWriter::XML:
    5676         [ #  # ]:          0 :                         if( m_aContext.Version > PDFWriter::PDF_1_3 )
    5677                 :          0 :                             nFlags |= 32;
    5678                 :          0 :                         break;
    5679                 :            :                     case PDFWriter::PDF:
    5680         [ #  # ]:          0 :                         if( m_aContext.Version > PDFWriter::PDF_1_3 )
    5681                 :          0 :                             nFlags |= 256;
    5682                 :          0 :                         break;
    5683                 :            :                     case PDFWriter::FDF:
    5684                 :            :                     default:
    5685                 :          0 :                         break;
    5686                 :            :                     }
    5687         [ #  # ]:          0 :                     if( rWidget.m_bSubmitGet )
    5688                 :          0 :                         nFlags |= 8;
    5689         [ #  # ]:          0 :                     aLine.append( nFlags );
    5690         [ #  # ]:          0 :                     aLine.append( ">>>>\n" );
    5691                 :            :                 }
    5692                 :            :                 else
    5693                 :            :                 {
    5694                 :            :                     // create a URI action
    5695         [ #  # ]:          0 :                     aLine.append( "/AA<</D<</Type/Action/S/URI/URI(" );
    5696 [ #  # ][ #  # ]:          0 :                     aLine.append( OUStringToOString( rWidget.m_aListEntries.front(), RTL_TEXTENCODING_ASCII_US ) );
                 [ #  # ]
    5697         [ #  # ]:          0 :                     aLine.append( ")>>>>\n" );
    5698                 :          0 :                 }
    5699                 :            :             }
    5700                 :            :             else
    5701         [ #  # ]:          0 :                 m_aErrors.insert( PDFWriter::Warning_FormAction_Omitted_PDFA );
    5702                 :            :         }
    5703         [ #  # ]:          0 :         if( !rWidget.m_aDAString.isEmpty() )
    5704                 :            :         {
    5705         [ #  # ]:          0 :             if( !rWidget.m_aDRDict.isEmpty() )
    5706                 :            :             {
    5707         [ #  # ]:          0 :                 aLine.append( "/DR<<" );
    5708         [ #  # ]:          0 :                 aLine.append( rWidget.m_aDRDict );
    5709         [ #  # ]:          0 :                 aLine.append( ">>\n" );
    5710                 :            :             }
    5711                 :            :             else
    5712                 :            :             {
    5713         [ #  # ]:          0 :                 aLine.append( "/DR<</Font<<" );
    5714         [ #  # ]:          0 :                 appendBuiltinFontsToDict( aLine );
    5715         [ #  # ]:          0 :                 aLine.append( ">>>>\n" );
    5716                 :            :             }
    5717         [ #  # ]:          0 :             aLine.append( "/DA" );
    5718         [ #  # ]:          0 :             appendLiteralStringEncrypt( rWidget.m_aDAString, rWidget.m_nObject, aLine );
    5719         [ #  # ]:          0 :             aLine.append( "\n" );
    5720         [ #  # ]:          0 :             if( rWidget.m_nTextStyle & TEXT_DRAW_CENTER )
    5721         [ #  # ]:          0 :                 aLine.append( "/Q 1\n" );
    5722         [ #  # ]:          0 :             else if( rWidget.m_nTextStyle & TEXT_DRAW_RIGHT )
    5723         [ #  # ]:          0 :                 aLine.append( "/Q 2\n" );
    5724                 :            :         }
    5725                 :            :         // appearance charactristics for terminal fields
    5726                 :            :         // which are supposed to have an appearance constructed
    5727                 :            :         // by the viewer application
    5728         [ #  # ]:          0 :         if( !rWidget.m_aMKDict.isEmpty() )
    5729                 :            :         {
    5730         [ #  # ]:          0 :             aLine.append( "/MK<<" );
    5731         [ #  # ]:          0 :             aLine.append( rWidget.m_aMKDict );
    5732                 :            : //add the CA string, encrypting it
    5733         [ #  # ]:          0 :             appendLiteralStringEncrypt(rWidget.m_aMKDictCAString, rWidget.m_nObject, aLine);
    5734         [ #  # ]:          0 :             aLine.append( ">>\n" );
    5735                 :            :         }
    5736                 :            : 
    5737 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( emitAppearances( rWidget, aLine ) );
    5738                 :            : 
    5739                 :            :         aLine.append( ">>\n"
    5740         [ #  # ]:          0 :                       "endobj\n\n" );
    5741 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( updateObject( rWidget.m_nObject ) );
    5742 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    5743 [ #  # ][ #  # ]:          0 :     }
    5744                 :          0 :     return true;
    5745                 :            : }
    5746                 :            : 
    5747                 :          0 : bool PDFWriterImpl::emitAnnotations()
    5748                 :            : {
    5749         [ #  # ]:          0 :     if( m_aPages.size() < 1 )
    5750                 :          0 :         return false;
    5751                 :            : 
    5752         [ #  # ]:          0 :     CHECK_RETURN( emitLinkAnnotations() );
    5753                 :            : 
    5754         [ #  # ]:          0 :     CHECK_RETURN( emitNoteAnnotations() );
    5755                 :            : 
    5756         [ #  # ]:          0 :     CHECK_RETURN( emitWidgetAnnotations() );
    5757                 :            : 
    5758                 :          0 :     return true;
    5759                 :            : }
    5760                 :            : 
    5761                 :            : #undef CHECK_RETURN
    5762                 :            : #define CHECK_RETURN( x ) if( !x ) return false
    5763                 :            : 
    5764                 :          0 : bool PDFWriterImpl::emitCatalog()
    5765                 :            : {
    5766                 :            :     // build page tree
    5767                 :            :     // currently there is only one node that contains all leaves
    5768                 :            : 
    5769                 :            :     // first create a page tree node id
    5770         [ #  # ]:          0 :     sal_Int32 nTreeNode = createObject();
    5771                 :            : 
    5772                 :            :     // emit global resource dictionary (page emit needs it)
    5773 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( emitResources() );
    5774                 :            : 
    5775                 :            :     // emit all pages
    5776 [ #  # ][ #  # ]:          0 :     for( std::vector<PDFPage>::iterator it = m_aPages.begin(); it != m_aPages.end(); ++it )
    5777 [ #  # ][ #  # ]:          0 :         if( ! it->emit( nTreeNode ) )
    5778                 :          0 :             return false;
    5779                 :            : 
    5780         [ #  # ]:          0 :     sal_Int32 nNamedDestinationsDictionary = emitNamedDestinations();
    5781                 :            : 
    5782         [ #  # ]:          0 :     sal_Int32 nOutlineDict = emitOutline();
    5783                 :            : 
    5784                 :            :     //emit Output intent i59651
    5785         [ #  # ]:          0 :     sal_Int32 nOutputIntentObject = emitOutputIntent();
    5786                 :            : 
    5787                 :            :     //emit metadata
    5788         [ #  # ]:          0 :     sal_Int32 nMetadataObject = emitDocumentMetadata();
    5789                 :            : 
    5790                 :          0 :     sal_Int32 nStructureDict = 0;
    5791         [ #  # ]:          0 :     if(m_aStructure.size() > 1)
    5792                 :            :     {
    5793                 :            : ///check if dummy structure containers are needed
    5794         [ #  # ]:          0 :         addInternalStructureContainer(m_aStructure[0]);
    5795         [ #  # ]:          0 :         nStructureDict = m_aStructure[0].m_nObject = createObject();
    5796         [ #  # ]:          0 :         emitStructure( m_aStructure[ 0 ] );
    5797                 :            :     }
    5798                 :            : 
    5799                 :            :     // adjust tree node file offset
    5800 [ #  # ][ #  # ]:          0 :     if( ! updateObject( nTreeNode ) )
    5801                 :          0 :         return false;
    5802                 :            : 
    5803                 :            :     // emit tree node
    5804                 :          0 :     OStringBuffer aLine( 2048 );
    5805         [ #  # ]:          0 :     aLine.append( nTreeNode );
    5806         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    5807         [ #  # ]:          0 :     aLine.append( "<</Type/Pages\n" );
    5808         [ #  # ]:          0 :     aLine.append( "/Resources " );
    5809 [ #  # ][ #  # ]:          0 :     aLine.append( getResourceDictObj() );
    5810         [ #  # ]:          0 :     aLine.append( " 0 R\n" );
    5811                 :            : 
    5812      [ #  #  # ]:          0 :     switch( m_eInheritedOrientation )
    5813                 :            :     {
    5814         [ #  # ]:          0 :         case PDFWriter::Landscape: aLine.append( "/Rotate 90\n" );break;
    5815         [ #  # ]:          0 :         case PDFWriter::Seascape: aLine.append( "/Rotate -90\n" );break;
    5816                 :            : 
    5817                 :            :         case PDFWriter::Inherit: // actually Inherit would be a bug, but insignificant
    5818                 :            :         case PDFWriter::Portrait:
    5819                 :            :         default:
    5820                 :          0 :             break;
    5821                 :            :     }
    5822                 :          0 :     sal_Int32 nMediaBoxWidth = 0;
    5823                 :          0 :     sal_Int32 nMediaBoxHeight = 0;
    5824         [ #  # ]:          0 :     if( m_aPages.empty() ) // sanity check, this should not happen
    5825                 :            :     {
    5826                 :          0 :         nMediaBoxWidth = m_nInheritedPageWidth;
    5827                 :          0 :         nMediaBoxHeight = m_nInheritedPageHeight;
    5828                 :            :     }
    5829                 :            :     else
    5830                 :            :     {
    5831 [ #  # ][ #  # ]:          0 :         for( std::vector<PDFPage>::const_iterator iter = m_aPages.begin(); iter != m_aPages.end(); ++iter )
                 [ #  # ]
    5832                 :            :         {
    5833         [ #  # ]:          0 :             if( iter->m_nPageWidth > nMediaBoxWidth )
    5834                 :          0 :                 nMediaBoxWidth = iter->m_nPageWidth;
    5835         [ #  # ]:          0 :             if( iter->m_nPageHeight > nMediaBoxHeight )
    5836                 :          0 :                 nMediaBoxHeight = iter->m_nPageHeight;
    5837                 :            :         }
    5838                 :            :     }
    5839         [ #  # ]:          0 :     aLine.append( "/MediaBox[ 0 0 " );
    5840         [ #  # ]:          0 :     aLine.append( nMediaBoxWidth );
    5841         [ #  # ]:          0 :     aLine.append( ' ' );
    5842         [ #  # ]:          0 :     aLine.append( nMediaBoxHeight );
    5843                 :            :     aLine.append( " ]\n"
    5844         [ #  # ]:          0 :                   "/Kids[ " );
    5845                 :          0 :     unsigned int i = 0;
    5846 [ #  # ][ #  # ]:          0 :     for( std::vector<PDFPage>::const_iterator iter = m_aPages.begin(); iter != m_aPages.end(); ++iter, i++ )
                 [ #  # ]
    5847                 :            :     {
    5848         [ #  # ]:          0 :         aLine.append( iter->m_nPageObject );
    5849         [ #  # ]:          0 :         aLine.append( " 0 R" );
    5850 [ #  # ][ #  # ]:          0 :         aLine.append( ( (i&15) == 15 ) ? "\n" : " " );
    5851                 :            :     }
    5852                 :            :     aLine.append( "]\n"
    5853         [ #  # ]:          0 :                   "/Count " );
    5854         [ #  # ]:          0 :     aLine.append( (sal_Int32)m_aPages.size() );
    5855                 :            :     aLine.append( ">>\n"
    5856         [ #  # ]:          0 :                   "endobj\n\n" );
    5857 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    5858                 :            : 
    5859                 :            :     // emit annotation objects
    5860 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( emitAnnotations() );
    5861                 :            : 
    5862                 :            :     // emit Catalog
    5863         [ #  # ]:          0 :     m_nCatalogObject = createObject();
    5864 [ #  # ][ #  # ]:          0 :     if( ! updateObject( m_nCatalogObject ) )
    5865                 :          0 :         return false;
    5866         [ #  # ]:          0 :     aLine.setLength( 0 );
    5867         [ #  # ]:          0 :     aLine.append( m_nCatalogObject );
    5868                 :            :     aLine.append( " 0 obj\n"
    5869         [ #  # ]:          0 :                   "<</Type/Catalog/Pages " );
    5870         [ #  # ]:          0 :     aLine.append( nTreeNode );
    5871         [ #  # ]:          0 :     aLine.append( " 0 R\n" );
    5872                 :            : //--->i56629
    5873                 :            : //check if there are named destinations to emit (root must be inside the catalog)
    5874         [ #  # ]:          0 :     if( nNamedDestinationsDictionary )
    5875                 :            :     {
    5876         [ #  # ]:          0 :         aLine.append("/Dests ");
    5877         [ #  # ]:          0 :         aLine.append( nNamedDestinationsDictionary );
    5878         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    5879                 :            :     }
    5880                 :            : //<----
    5881         [ #  # ]:          0 :     if( m_aContext.PageLayout != PDFWriter::DefaultLayout )
    5882      [ #  #  # ]:          0 :         switch(  m_aContext.PageLayout )
    5883                 :            :         {
    5884                 :            :         default :
    5885                 :            :         case  PDFWriter::SinglePage :
    5886         [ #  # ]:          0 :             aLine.append( "/PageLayout/SinglePage\n" );
    5887                 :          0 :             break;
    5888                 :            :         case  PDFWriter::Continuous :
    5889         [ #  # ]:          0 :             aLine.append( "/PageLayout/OneColumn\n" );
    5890                 :          0 :             break;
    5891                 :            :         case  PDFWriter::ContinuousFacing :
    5892                 :            : //the flag m_aContext.FirstPageLeft below is used to set the page on the left side
    5893         [ #  # ]:          0 :             aLine.append( "/PageLayout/TwoColumnRight\n" );//odd page on the right side
    5894                 :          0 :             break;
    5895                 :            :         }
    5896 [ #  # ][ #  # ]:          0 :     if( m_aContext.PDFDocumentMode != PDFWriter::ModeDefault && !m_aContext.OpenInFullScreenMode )
    5897      [ #  #  # ]:          0 :         switch(  m_aContext.PDFDocumentMode )
    5898                 :            :         {
    5899                 :            :         default :
    5900         [ #  # ]:          0 :             aLine.append( "/PageMode/UseNone\n" );
    5901                 :          0 :             break;
    5902                 :            :         case PDFWriter::UseOutlines :
    5903         [ #  # ]:          0 :             aLine.append( "/PageMode/UseOutlines\n" ); //document is opened with outline pane open
    5904                 :          0 :             break;
    5905                 :            :         case PDFWriter::UseThumbs :
    5906         [ #  # ]:          0 :             aLine.append( "/PageMode/UseThumbs\n" ); //document is opened with thumbnails pane open
    5907                 :          0 :             break;
    5908                 :            :         }
    5909         [ #  # ]:          0 :     else if( m_aContext.OpenInFullScreenMode )
    5910         [ #  # ]:          0 :         aLine.append( "/PageMode/FullScreen\n" ); //document is opened full screen
    5911                 :            : 
    5912                 :          0 :     OStringBuffer aInitPageRef;
    5913 [ #  # ][ #  # ]:          0 :     if( m_aContext.InitialPage >= 0 && m_aContext.InitialPage < (sal_Int32)m_aPages.size() )
                 [ #  # ]
    5914                 :            :     {
    5915         [ #  # ]:          0 :         aInitPageRef.append( m_aPages[m_aContext.InitialPage].m_nPageObject );
    5916         [ #  # ]:          0 :         aInitPageRef.append( " 0 R" );
    5917                 :            :     }
    5918                 :            :     else
    5919         [ #  # ]:          0 :         aInitPageRef.append( "0" );
    5920                 :            : 
    5921                 :            : #if !defined(ANDROID) && !defined(IOS)
    5922         [ #  # ]:          0 :     if (m_nSignatureObject != -1) // Document will be signed
    5923                 :            :     {
    5924         [ #  # ]:          0 :         aLine.append("/Perms<</DocMDP ");
    5925         [ #  # ]:          0 :         aLine.append(m_nSignatureObject);
    5926         [ #  # ]:          0 :         aLine.append(" 0 R>>");
    5927                 :            :     }
    5928                 :            : #endif
    5929                 :            : 
    5930   [ #  #  #  #  :          0 :     switch( m_aContext.PDFDocumentAction )
                      # ]
    5931                 :            :     {
    5932                 :            :     case PDFWriter::ActionDefault :     //do nothing, this is the Acrobat default
    5933                 :            :     default:
    5934         [ #  # ]:          0 :         if( aInitPageRef.getLength() > 1 )
    5935                 :            :         {
    5936         [ #  # ]:          0 :             aLine.append( "/OpenAction[" );
    5937         [ #  # ]:          0 :             aLine.append( aInitPageRef.makeStringAndClear() );
    5938         [ #  # ]:          0 :             aLine.append( " /XYZ null null 0]\n" );
    5939                 :            :         }
    5940                 :          0 :         break;
    5941                 :            :     case PDFWriter::FitInWindow :
    5942         [ #  # ]:          0 :         aLine.append( "/OpenAction[" );
    5943         [ #  # ]:          0 :         aLine.append( aInitPageRef.makeStringAndClear() );
    5944         [ #  # ]:          0 :         aLine.append( " /Fit]\n" ); //Open fit page
    5945                 :          0 :         break;
    5946                 :            :     case PDFWriter::FitWidth :
    5947         [ #  # ]:          0 :         aLine.append( "/OpenAction[" );
    5948         [ #  # ]:          0 :         aLine.append( aInitPageRef.makeStringAndClear() );
    5949         [ #  # ]:          0 :         aLine.append( " /FitH " );
    5950         [ #  # ]:          0 :         aLine.append( m_nInheritedPageHeight );//Open fit width
    5951         [ #  # ]:          0 :         aLine.append( "]\n" );
    5952                 :          0 :         break;
    5953                 :            :     case PDFWriter::FitVisible :
    5954         [ #  # ]:          0 :         aLine.append( "/OpenAction[" );
    5955         [ #  # ]:          0 :         aLine.append( aInitPageRef.makeStringAndClear() );
    5956         [ #  # ]:          0 :         aLine.append( " /FitBH " );
    5957         [ #  # ]:          0 :         aLine.append( m_nInheritedPageHeight );//Open fit visible
    5958         [ #  # ]:          0 :         aLine.append( "]\n" );
    5959                 :          0 :         break;
    5960                 :            :     case PDFWriter::ActionZoom :
    5961         [ #  # ]:          0 :         aLine.append( "/OpenAction[" );
    5962         [ #  # ]:          0 :         aLine.append( aInitPageRef.makeStringAndClear() );
    5963         [ #  # ]:          0 :         aLine.append( " /XYZ null null " );
    5964 [ #  # ][ #  # ]:          0 :         if( m_aContext.Zoom >= 50 && m_aContext.Zoom <= 1600 )
    5965         [ #  # ]:          0 :             aLine.append( (double)m_aContext.Zoom/100.0 );
    5966                 :            :         else
    5967         [ #  # ]:          0 :             aLine.append( "0" );
    5968         [ #  # ]:          0 :         aLine.append( "]\n" );
    5969                 :          0 :         break;
    5970                 :            :     }
    5971                 :            : // viewer preferences, if we had some, then emit
    5972         [ #  # ]:          0 :     if( m_aContext.HideViewerToolbar ||
           [ #  #  #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5973                 :          0 :         ( m_aContext.Version > PDFWriter::PDF_1_3 && m_aContext.DocumentInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle ) ||
    5974                 :            :         m_aContext.HideViewerMenubar ||
    5975                 :            :         m_aContext.HideViewerWindowControls || m_aContext.FitWindow ||
    5976                 :            :         m_aContext.CenterWindow || (m_aContext.FirstPageLeft  &&  m_aContext.PageLayout == PDFWriter::ContinuousFacing ) ||
    5977                 :            :         m_aContext.OpenInFullScreenMode )
    5978                 :            :     {
    5979         [ #  # ]:          0 :         aLine.append( "/ViewerPreferences<<" );
    5980         [ #  # ]:          0 :         if( m_aContext.HideViewerToolbar )
    5981         [ #  # ]:          0 :             aLine.append( "/HideToolbar true\n" );
    5982         [ #  # ]:          0 :         if( m_aContext.HideViewerMenubar )
    5983         [ #  # ]:          0 :             aLine.append( "/HideMenubar true\n" );
    5984         [ #  # ]:          0 :         if( m_aContext.HideViewerWindowControls )
    5985         [ #  # ]:          0 :             aLine.append( "/HideWindowUI true\n" );
    5986         [ #  # ]:          0 :         if( m_aContext.FitWindow )
    5987         [ #  # ]:          0 :             aLine.append( "/FitWindow true\n" );
    5988         [ #  # ]:          0 :         if( m_aContext.CenterWindow )
    5989         [ #  # ]:          0 :             aLine.append( "/CenterWindow true\n" );
    5990 [ #  # ][ #  # ]:          0 :         if( m_aContext.Version > PDFWriter::PDF_1_3 && m_aContext.DocumentInfo.Title.Len() && m_aContext.DisplayPDFDocumentTitle )
         [ #  # ][ #  # ]
    5991         [ #  # ]:          0 :             aLine.append( "/DisplayDocTitle true\n" );
    5992 [ #  # ][ #  # ]:          0 :         if( m_aContext.FirstPageLeft &&  m_aContext.PageLayout == PDFWriter::ContinuousFacing )
    5993         [ #  # ]:          0 :             aLine.append( "/Direction/R2L\n" );
    5994         [ #  # ]:          0 :         if( m_aContext.OpenInFullScreenMode )
    5995      [ #  #  # ]:          0 :             switch( m_aContext.PDFDocumentMode )
    5996                 :            :             {
    5997                 :            :             default :
    5998                 :            :             case PDFWriter::ModeDefault :
    5999         [ #  # ]:          0 :                 aLine.append( "/NonFullScreenPageMode/UseNone\n" );
    6000                 :          0 :                 break;
    6001                 :            :             case PDFWriter::UseOutlines :
    6002         [ #  # ]:          0 :                 aLine.append( "/NonFullScreenPageMode/UseOutlines\n" );
    6003                 :          0 :                 break;
    6004                 :            :             case PDFWriter::UseThumbs :
    6005         [ #  # ]:          0 :                 aLine.append( "/NonFullScreenPageMode/UseThumbs\n" );
    6006                 :          0 :                 break;
    6007                 :            :             }
    6008         [ #  # ]:          0 :         aLine.append( ">>\n" );
    6009                 :            :     }
    6010                 :            : 
    6011         [ #  # ]:          0 :     if( nOutlineDict )
    6012                 :            :     {
    6013         [ #  # ]:          0 :         aLine.append( "/Outlines " );
    6014         [ #  # ]:          0 :         aLine.append( nOutlineDict );
    6015         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    6016                 :            :     }
    6017         [ #  # ]:          0 :     if( nStructureDict )
    6018                 :            :     {
    6019         [ #  # ]:          0 :         aLine.append( "/StructTreeRoot " );
    6020         [ #  # ]:          0 :         aLine.append( nStructureDict );
    6021         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    6022                 :            :     }
    6023         [ #  # ]:          0 :     if( !m_aContext.DocumentLocale.Language.isEmpty() )
    6024                 :            :     {
    6025                 :          0 :         OUStringBuffer aLocBuf( 16 );
    6026         [ #  # ]:          0 :         aLocBuf.append( m_aContext.DocumentLocale.Language.toAsciiLowerCase() );
    6027         [ #  # ]:          0 :         if( !m_aContext.DocumentLocale.Country.isEmpty() )
    6028                 :            :         {
    6029         [ #  # ]:          0 :             aLocBuf.append( sal_Unicode('-') );
    6030         [ #  # ]:          0 :             aLocBuf.append( m_aContext.DocumentLocale.Country );
    6031                 :            :         }
    6032         [ #  # ]:          0 :         aLine.append( "/Lang" );
    6033 [ #  # ][ #  # ]:          0 :         appendLiteralStringEncrypt( aLocBuf.makeStringAndClear(), m_nCatalogObject, aLine );
    6034         [ #  # ]:          0 :         aLine.append( "\n" );
    6035                 :            :     }
    6036 [ #  # ][ #  # ]:          0 :     if( m_aContext.Tagged && m_aContext.Version > PDFWriter::PDF_1_3 )
    6037                 :            :     {
    6038         [ #  # ]:          0 :         aLine.append( "/MarkInfo<</Marked true>>\n" );
    6039                 :            :     }
    6040         [ #  # ]:          0 :     if( m_aWidgets.size() > 0 )
    6041                 :            :     {
    6042         [ #  # ]:          0 :         aLine.append( "/AcroForm<</Fields[\n" );
    6043                 :          0 :         int nWidgets = m_aWidgets.size();
    6044                 :          0 :         int nOut = 0;
    6045         [ #  # ]:          0 :         for( int j = 0; j < nWidgets; j++ )
    6046                 :            :         {
    6047                 :            :             // output only root fields
    6048         [ #  # ]:          0 :             if( m_aWidgets[j].m_nParent < 1 )
    6049                 :            :             {
    6050         [ #  # ]:          0 :                 aLine.append( m_aWidgets[j].m_nObject );
    6051 [ #  # ][ #  # ]:          0 :                 aLine.append( (nOut++ % 5)==4 ? " 0 R\n" : " 0 R " );
    6052                 :            :             }
    6053                 :            :         }
    6054         [ #  # ]:          0 :         aLine.append( "\n]" );
    6055                 :            : 
    6056                 :            : #if !defined(ANDROID) && !defined(IOS)
    6057         [ #  # ]:          0 :         if (m_nSignatureObject != -1)
    6058         [ #  # ]:          0 :             aLine.append( "/SigFlags 3");
    6059                 :            : #endif
    6060                 :            : 
    6061         [ #  # ]:          0 :         aLine.append( "/DR " );
    6062 [ #  # ][ #  # ]:          0 :         aLine.append( getResourceDictObj() );
    6063         [ #  # ]:          0 :         aLine.append( " 0 R" );
    6064                 :            :         // /NeedAppearances must not be used if PDF is signed
    6065 [ #  # ][ #  # ]:          0 :         if( m_bIsPDF_A1
    6066                 :            : #if !defined(ANDROID) && !defined(IOS)
    6067                 :            :             || ( m_nSignatureObject != -1 )
    6068                 :            : #endif
    6069                 :            :             )
    6070         [ #  # ]:          0 :             aLine.append( ">>\n" );
    6071                 :            :         else
    6072         [ #  # ]:          0 :             aLine.append( "/NeedAppearances true>>\n" );
    6073                 :            :     }
    6074                 :            : //--->i59651
    6075                 :            : //check if there is a Metadata object
    6076         [ #  # ]:          0 :     if( nOutputIntentObject )
    6077                 :            :     {
    6078         [ #  # ]:          0 :         aLine.append("/OutputIntents[");
    6079         [ #  # ]:          0 :         aLine.append( nOutputIntentObject );
    6080         [ #  # ]:          0 :         aLine.append( " 0 R]" );
    6081                 :            :     }
    6082         [ #  # ]:          0 :     if( nMetadataObject )
    6083                 :            :     {
    6084         [ #  # ]:          0 :         aLine.append("/Metadata ");
    6085         [ #  # ]:          0 :         aLine.append( nMetadataObject );
    6086         [ #  # ]:          0 :         aLine.append( " 0 R" );
    6087                 :            :     }
    6088                 :            : //<----
    6089                 :            :     aLine.append( ">>\n"
    6090         [ #  # ]:          0 :                   "endobj\n\n" );
    6091 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6092                 :            : 
    6093                 :          0 :     return true;
    6094                 :            : }
    6095                 :            : 
    6096                 :            : #if !defined(ANDROID) && !defined(IOS)
    6097                 :            : 
    6098                 :          0 : bool PDFWriterImpl::emitSignature()
    6099                 :            : {
    6100 [ #  # ][ #  # ]:          0 :     if( !updateObject( m_nSignatureObject ) )
    6101                 :          0 :         return false;
    6102                 :            : 
    6103                 :          0 :     OStringBuffer aLine( 0x5000 );
    6104         [ #  # ]:          0 :     aLine.append( m_nSignatureObject );
    6105         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    6106         [ #  # ]:          0 :     aLine.append("<</Reference[<</Data ");
    6107         [ #  # ]:          0 :     aLine.append( m_nCatalogObject );
    6108                 :            :     aLine.append(" 0 R/Type/SigRef/TransformParams<</Type/TransformParams"
    6109                 :            :                  "/V/1.2/P 1>>/DigestMethod/MD5/DigestLocation[0 0]"
    6110         [ #  # ]:          0 :                  "/DigestValue(aa)/TransformMethod/DocMDP>>]/Contents <" );
    6111                 :            : 
    6112                 :          0 :     sal_uInt64 nOffset = ~0U;
    6113 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nOffset ) ) );
    6114                 :            : 
    6115                 :          0 :     m_nSignatureContentOffset = nOffset + aLine.getLength();
    6116                 :            : 
    6117                 :            :     // reserve some space for the PKCS#7 object
    6118                 :          0 :     OStringBuffer aContentFiller( MAX_SIGNATURE_CONTENT_LENGTH );
    6119         [ #  # ]:          0 :     comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
    6120         [ #  # ]:          0 :     aLine.append( aContentFiller.makeStringAndClear() );
    6121         [ #  # ]:          0 :     aLine.append( ">\n/Type/Sig/SubFilter/adbe.pkcs7.detached");
    6122                 :            : 
    6123         [ #  # ]:          0 :     if( m_aContext.DocumentInfo.Author.Len() )
    6124                 :            :     {
    6125         [ #  # ]:          0 :         aLine.append( "/Name" );
    6126 [ #  # ][ #  # ]:          0 :         appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, m_nSignatureObject, aLine );
    6127                 :            :     }
    6128                 :            : 
    6129         [ #  # ]:          0 :     aLine.append( " /M ");
    6130         [ #  # ]:          0 :     appendLiteralStringEncrypt( m_aCreationDateString, m_nSignatureObject, aLine );
    6131                 :            : 
    6132         [ #  # ]:          0 :     aLine.append( " /ByteRange [ 0 ");
    6133         [ #  # ]:          0 :     aLine.append( m_nSignatureContentOffset - 1, 10 );
    6134         [ #  # ]:          0 :     aLine.append( " " );
    6135         [ #  # ]:          0 :     aLine.append( m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1, 10 );
    6136         [ #  # ]:          0 :     aLine.append( " " );
    6137                 :            : 
    6138                 :          0 :     m_nSignatureLastByteRangeNoOffset = nOffset + aLine.getLength();
    6139                 :            : 
    6140                 :            :     // mark the last ByteRange no and add some space. Now, we don't know
    6141                 :            :     // how many bytes we need for this ByteRange value
    6142                 :            :     // The real value will be overwritten in the finalizeSignature method
    6143                 :          0 :     OStringBuffer aByteRangeFiller( 100  );
    6144         [ #  # ]:          0 :     comphelper::string::padToLength(aByteRangeFiller, 100, ' ');
    6145         [ #  # ]:          0 :     aLine.append( aByteRangeFiller.makeStringAndClear() );
    6146         [ #  # ]:          0 :     aLine.append("  /Filter/Adobe.PPKMS");
    6147                 :            : 
    6148                 :            :     //emit reason, location and contactinfo
    6149         [ #  # ]:          0 :     if ( !m_aContext.SignReason.isEmpty() )
    6150                 :            :     {
    6151         [ #  # ]:          0 :         aLine.append("/Reason");
    6152         [ #  # ]:          0 :         appendUnicodeTextStringEncrypt( m_aContext.SignReason, m_nSignatureObject, aLine );
    6153                 :            :     }
    6154                 :            : 
    6155         [ #  # ]:          0 :     if ( !m_aContext.SignLocation.isEmpty() )
    6156                 :            :     {
    6157         [ #  # ]:          0 :         aLine.append("/Location");
    6158         [ #  # ]:          0 :         appendUnicodeTextStringEncrypt( m_aContext.SignLocation, m_nSignatureObject, aLine );
    6159                 :            :     }
    6160                 :            : 
    6161         [ #  # ]:          0 :     if ( !m_aContext.SignContact.isEmpty() )
    6162                 :            :     {
    6163         [ #  # ]:          0 :         aLine.append("/ContactInfo");
    6164         [ #  # ]:          0 :         appendUnicodeTextStringEncrypt( m_aContext.SignContact, m_nSignatureObject, aLine );
    6165                 :            :     }
    6166                 :            : 
    6167         [ #  # ]:          0 :     aLine.append(" >>\nendobj\n\n" );
    6168                 :            : 
    6169 [ #  # ][ #  # ]:          0 :     if (!writeBuffer( aLine.getStr(), aLine.getLength() ))
    6170                 :          0 :         return false;
    6171                 :            : 
    6172                 :          0 :     return true;
    6173                 :            : }
    6174                 :            : 
    6175                 :          0 : char *PDFSigningPKCS7PasswordCallback(PK11SlotInfo * /*slot*/, PRBool /*retry*/, void *arg)
    6176                 :            : {
    6177                 :          0 :     return (char *)arg;
    6178                 :            : }
    6179                 :            : 
    6180                 :          0 : bool PDFWriterImpl::finalizeSignature()
    6181                 :            : {
    6182                 :            : 
    6183         [ #  # ]:          0 :     if (!m_aContext.SignCertificate.is())
    6184                 :          0 :         return false;
    6185                 :            : 
    6186                 :            :     // 1- calculate last ByteRange value
    6187                 :          0 :     sal_uInt64 nOffset = ~0U;
    6188 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nOffset ) ) );
    6189                 :            : 
    6190                 :          0 :     sal_Int64 nLastByteRangeNo = nOffset - (m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1);
    6191                 :            : 
    6192                 :            :     // 2- overwrite the value to the m_nSignatureLastByteRangeNoOffset position
    6193                 :          0 :     sal_uInt64 nWritten = 0;
    6194 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, m_nSignatureLastByteRangeNoOffset ) ) );
    6195                 :          0 :     OStringBuffer aByteRangeNo( 256 );
    6196         [ #  # ]:          0 :     aByteRangeNo.append( nLastByteRangeNo, 10);
    6197         [ #  # ]:          0 :     aByteRangeNo.append( " ]" );
    6198                 :            : 
    6199 [ #  # ][ #  # ]:          0 :     if( osl_writeFile( m_aFile, aByteRangeNo.getStr(), aByteRangeNo.getLength(), &nWritten ) != osl_File_E_None )
    6200                 :            :     {
    6201 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, nOffset ) ) );
    6202                 :          0 :         return false;
    6203                 :            :     }
    6204                 :            : 
    6205                 :            :     // 3- create the PKCS#7 object using NSS
    6206 [ #  # ][ #  # ]:          0 :     com::sun::star::uno::Sequence< sal_Int8 > derEncoded = m_aContext.SignCertificate->getEncoded();
    6207                 :            : 
    6208         [ #  # ]:          0 :     if (!derEncoded.hasElements())
    6209                 :          0 :         return false;
    6210                 :            : 
    6211         [ #  # ]:          0 :     sal_Int8* n_derArray = derEncoded.getArray();
    6212                 :          0 :     sal_Int32 n_derLength = derEncoded.getLength();
    6213                 :            : 
    6214         [ #  # ]:          0 :     NSS_NoDB_Init(".");
    6215                 :            : 
    6216         [ #  # ]:          0 :     CERTCertificate *cert = CERT_DecodeCertFromPackage(reinterpret_cast<char *>(n_derArray), n_derLength);
    6217                 :            : 
    6218         [ #  # ]:          0 :     if (!cert)
    6219                 :            :     {
    6220                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: Error occured, certificate cannot be reconstructed.");
    6221                 :          0 :         return false;
    6222                 :            :     }
    6223                 :            : 
    6224                 :            :     SAL_WARN("vcl.gdi", "PDF Signing: Certificate Subject: " <<  cert->subjectName << "\n\tCertificate Issuer: " << cert->issuerName);
    6225                 :            : 
    6226                 :            :     // Prepare buffer and calculate PDF file digest
    6227 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, 0) ) );
    6228                 :            : 
    6229         [ #  # ]:          0 :     HASHContext *hc = HASH_Create(HASH_AlgSHA1);
    6230                 :            : 
    6231         [ #  # ]:          0 :     if (!hc)
    6232                 :            :     {
    6233                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: SHA1 HASH_Create failed!");
    6234                 :          0 :         return false;
    6235                 :            :     }
    6236                 :            : 
    6237         [ #  # ]:          0 :     HASH_Begin(hc);
    6238                 :            : 
    6239         [ #  # ]:          0 :     char *buffer = new char[m_nSignatureContentOffset + 1];
    6240                 :            :     sal_uInt64 bytesRead;
    6241                 :            : 
    6242                 :            :     //FIXME: Check if SHA1 is calculated from the correct byterange
    6243                 :            : 
    6244 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_readFile( m_aFile, buffer, m_nSignatureContentOffset - 1 , &bytesRead ) ) );
    6245                 :          0 :     if (bytesRead != (sal_uInt64)m_nSignatureContentOffset - 1)
    6246                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: First buffer read failed!");
    6247                 :            : 
    6248         [ #  # ]:          0 :     HASH_Update(hc, reinterpret_cast<const unsigned char*>(buffer), bytesRead);
    6249         [ #  # ]:          0 :     delete[] buffer;
    6250                 :            : 
    6251         [ #  # ]:          0 :     buffer = new char[nLastByteRangeNo + 1];
    6252 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, m_nSignatureContentOffset + MAX_SIGNATURE_CONTENT_LENGTH + 1) ) );
    6253 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_readFile( m_aFile, buffer, nLastByteRangeNo, &bytesRead ) ) );
    6254                 :          0 :     if (bytesRead != (sal_uInt64) nLastByteRangeNo)
    6255                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: Second buffer read failed!");
    6256                 :            : 
    6257         [ #  # ]:          0 :     HASH_Update(hc, reinterpret_cast<const unsigned char*>(buffer), bytesRead);
    6258         [ #  # ]:          0 :     delete[] buffer;
    6259                 :            : 
    6260                 :            :     SECItem digest;
    6261                 :            :     unsigned char hash[SHA1_LENGTH];
    6262                 :          0 :     digest.data = hash;
    6263         [ #  # ]:          0 :     HASH_End(hc, digest.data, &digest.len, SHA1_LENGTH);
    6264         [ #  # ]:          0 :     HASH_Destroy(hc);
    6265                 :            : 
    6266         [ #  # ]:          0 :     const char *pass = OUStringToOString( m_aContext.SignPassword, RTL_TEXTENCODING_UTF8 ).getStr();
    6267                 :            : 
    6268         [ #  # ]:          0 :     NSSCMSMessage *cms_msg = NSS_CMSMessage_Create(NULL);
    6269         [ #  # ]:          0 :     if (!cms_msg)
    6270                 :            :     {
    6271                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't create new CMS message.");
    6272                 :          0 :         return false;
    6273                 :            :     }
    6274                 :            : 
    6275         [ #  # ]:          0 :     NSSCMSSignedData *cms_sd = NSS_CMSSignedData_Create(cms_msg);
    6276         [ #  # ]:          0 :     if (!cms_sd)
    6277                 :            :     {
    6278                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't create CMS SignedData.");
    6279                 :          0 :         return false;
    6280                 :            :     }
    6281                 :            : 
    6282         [ #  # ]:          0 :     NSSCMSContentInfo *cms_cinfo = NSS_CMSMessage_GetContentInfo(cms_msg);
    6283 [ #  # ][ #  # ]:          0 :     if (NSS_CMSContentInfo_SetContent_SignedData(cms_msg, cms_cinfo, cms_sd) != SECSuccess)
    6284                 :            :     {
    6285                 :            :         SAL_WARN("vcl.gdi", "PDF signing: Can't set CMS content signed data.");
    6286                 :          0 :         return false;
    6287                 :            :     }
    6288                 :            : 
    6289         [ #  # ]:          0 :     cms_cinfo = NSS_CMSSignedData_GetContentInfo(cms_sd);
    6290                 :            :     //attach NULL data as detached data
    6291 [ #  # ][ #  # ]:          0 :     if (NSS_CMSContentInfo_SetContent_Data(cms_msg, cms_cinfo, NULL, PR_TRUE) != SECSuccess)
    6292                 :            :     {
    6293                 :            :         SAL_WARN("vcl.gdi", "PDF signing: Can't set CMS content data.");
    6294                 :          0 :         return false;
    6295                 :            :     }
    6296                 :            : 
    6297         [ #  # ]:          0 :     NSSCMSSignerInfo *cms_signer = NSS_CMSSignerInfo_Create(cms_msg, cert, SEC_OID_SHA1);
    6298         [ #  # ]:          0 :     if (!cms_signer)
    6299                 :            :     {
    6300                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't create CMS SignerInfo.");
    6301                 :          0 :         return false;
    6302                 :            :     }
    6303                 :            : 
    6304 [ #  # ][ #  # ]:          0 :     if (NSS_CMSSignerInfo_IncludeCerts(cms_signer, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess)
    6305                 :            :     {
    6306                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't include cert chain.");
    6307                 :          0 :         return false;
    6308                 :            :     }
    6309                 :            : 
    6310                 :            :     //NSS_CMSSignerInfo_AddSigningTime(cms_signer, PR_Now()); //TODO: Needs PDF 1.6?
    6311                 :            : 
    6312 [ #  # ][ #  # ]:          0 :     if (NSS_CMSSignedData_AddCertificate(cms_sd, cert) != SECSuccess)
    6313                 :            :     {
    6314                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't add signer certificate.");
    6315                 :          0 :         return false;
    6316                 :            :     }
    6317                 :            : 
    6318 [ #  # ][ #  # ]:          0 :     if (NSS_CMSSignedData_AddSignerInfo(cms_sd, cms_signer) != SECSuccess)
    6319                 :            :     {
    6320                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't add signer info.");
    6321                 :          0 :         return false;
    6322                 :            :     }
    6323                 :            : 
    6324 [ #  # ][ #  # ]:          0 :     if (NSS_CMSSignedData_SetDigestValue(cms_sd, SEC_OID_SHA1, &digest) != SECSuccess)
    6325                 :            :     {
    6326                 :            :         SAL_WARN("vcl.gdi", "PDF signing: can't set PDF digest value.");
    6327                 :          0 :         return false;
    6328                 :            :     }
    6329                 :            : 
    6330                 :            :     SAL_WARN("vcl.gdi","PKCS7 Object created successfully!");
    6331                 :            : 
    6332                 :            :     SECItem cms_output;
    6333                 :          0 :     cms_output.data = 0;
    6334                 :          0 :     cms_output.len = 0;
    6335         [ #  # ]:          0 :     PLArenaPool *arena = PORT_NewArena(MAX_SIGNATURE_CONTENT_LENGTH);
    6336                 :            :     NSSCMSEncoderContext *cms_ecx;
    6337                 :            : 
    6338                 :            :     //FIXME: Check if password is passed correctly to SEC_PKCS7CreateSignedData function
    6339         [ #  # ]:          0 :     cms_ecx = NSS_CMSEncoder_Start(cms_msg, NULL, NULL, &cms_output, arena, (PK11PasswordFunc)::PDFSigningPKCS7PasswordCallback, (void *)pass, NULL, NULL, NULL, NULL);
    6340                 :            : 
    6341         [ #  # ]:          0 :     if (!cms_ecx)
    6342                 :            :     {
    6343                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: can't start DER encoder.");
    6344                 :          0 :         return false;
    6345                 :            :     }
    6346                 :            :     SAL_WARN("vcl.gdi", "PDF Signing: Started DER encoding.");
    6347                 :            : 
    6348 [ #  # ][ #  # ]:          0 :     if (NSS_CMSEncoder_Finish(cms_ecx) != SECSuccess)
    6349                 :            :     {
    6350                 :            :         SAL_WARN("vcl.gdi", "PDF Signing: can't finish DER encoder.");
    6351                 :          0 :         return false;
    6352                 :            :     }
    6353                 :            :     SAL_WARN("vcl.gdi", "PDF Signing: Finished DER encoding.");
    6354                 :            : 
    6355                 :          0 :     OStringBuffer cms_hexbuffer;
    6356                 :            : 
    6357         [ #  # ]:          0 :     for (unsigned int i = 0; i < cms_output.len ; i++)
    6358         [ #  # ]:          0 :         appendHex(cms_output.data[i], cms_hexbuffer);
    6359                 :            : 
    6360                 :            :     SAL_WARN("vcl.gdi","PKCS7 object encoded successfully!");
    6361                 :            : 
    6362                 :            :     // Set file pointer to the m_nSignatureContentOffset, we're ready to overwrite PKCS7 object
    6363                 :          0 :     nWritten = 0;
    6364 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, m_nSignatureContentOffset) ) );
    6365         [ #  # ]:          0 :     osl_writeFile(m_aFile, cms_hexbuffer.getStr(), cms_hexbuffer.getLength(), &nWritten);
    6366                 :            : 
    6367         [ #  # ]:          0 :     NSS_CMSMessage_Destroy(cms_msg);
    6368                 :            : 
    6369 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_setFilePos( m_aFile, osl_Pos_Absolut, nOffset ) ) );
    6370         [ #  # ]:          0 :     return true;
    6371                 :            : }
    6372                 :            : 
    6373                 :            : #endif
    6374                 :            : 
    6375                 :          0 : sal_Int32 PDFWriterImpl::emitInfoDict( )
    6376                 :            : {
    6377                 :          0 :     sal_Int32 nObject = createObject();
    6378                 :            : 
    6379         [ #  # ]:          0 :     if( updateObject( nObject ) )
    6380                 :            :     {
    6381                 :          0 :         OStringBuffer aLine( 1024 );
    6382         [ #  # ]:          0 :         aLine.append( nObject );
    6383                 :            :         aLine.append( " 0 obj\n"
    6384         [ #  # ]:          0 :                       "<<" );
    6385         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Title.Len() )
    6386                 :            :         {
    6387         [ #  # ]:          0 :             aLine.append( "/Title" );
    6388 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Title, nObject, aLine );
    6389         [ #  # ]:          0 :             aLine.append( "\n" );
    6390                 :            :         }
    6391         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Author.Len() )
    6392                 :            :         {
    6393         [ #  # ]:          0 :             aLine.append( "/Author" );
    6394 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, nObject, aLine );
    6395         [ #  # ]:          0 :             aLine.append( "\n" );
    6396                 :            :         }
    6397         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Subject.Len() )
    6398                 :            :         {
    6399         [ #  # ]:          0 :             aLine.append( "/Subject" );
    6400 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Subject, nObject, aLine );
    6401         [ #  # ]:          0 :             aLine.append( "\n" );
    6402                 :            :         }
    6403         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Keywords.Len() )
    6404                 :            :         {
    6405         [ #  # ]:          0 :             aLine.append( "/Keywords" );
    6406 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Keywords, nObject, aLine );
    6407         [ #  # ]:          0 :             aLine.append( "\n" );
    6408                 :            :         }
    6409         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Creator.Len() )
    6410                 :            :         {
    6411         [ #  # ]:          0 :             aLine.append( "/Creator" );
    6412 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Creator, nObject, aLine );
    6413         [ #  # ]:          0 :             aLine.append( "\n" );
    6414                 :            :         }
    6415         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Producer.Len() )
    6416                 :            :         {
    6417         [ #  # ]:          0 :             aLine.append( "/Producer" );
    6418 [ #  # ][ #  # ]:          0 :             appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Producer, nObject, aLine );
    6419         [ #  # ]:          0 :             aLine.append( "\n" );
    6420                 :            :         }
    6421                 :            : 
    6422         [ #  # ]:          0 :          aLine.append( "/CreationDate" );
    6423         [ #  # ]:          0 :          appendLiteralStringEncrypt( m_aCreationDateString, nObject, aLine );
    6424         [ #  # ]:          0 :         aLine.append( ">>\nendobj\n\n" );
    6425 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    6426                 :          0 :             nObject = 0;
    6427                 :            :     }
    6428                 :            :     else
    6429                 :          0 :         nObject = 0;
    6430                 :            : 
    6431                 :          0 :     return nObject;
    6432                 :            : }
    6433                 :            : 
    6434                 :            : //--->i56629
    6435                 :            : // Part of this function may be shared with method appendDest.
    6436                 :            : //
    6437                 :          0 : sal_Int32 PDFWriterImpl::emitNamedDestinations()
    6438                 :            : {
    6439                 :          0 :     sal_Int32  nCount = m_aNamedDests.size();
    6440         [ #  # ]:          0 :     if( nCount <= 0 )
    6441                 :          0 :         return 0;//define internal error
    6442                 :            : 
    6443                 :            : //get the object number for all the destinations
    6444                 :          0 :     sal_Int32 nObject = createObject();
    6445                 :            : 
    6446         [ #  # ]:          0 :     if( updateObject( nObject ) )
    6447                 :            :     {
    6448                 :            : //emit the dictionary
    6449                 :          0 :         OStringBuffer aLine( 1024 );
    6450         [ #  # ]:          0 :         aLine.append( nObject );
    6451                 :            :         aLine.append( " 0 obj\n"
    6452         [ #  # ]:          0 :                       "<<" );
    6453                 :            : 
    6454                 :            :         sal_Int32  nDestID;
    6455         [ #  # ]:          0 :         for( nDestID = 0; nDestID < nCount; nDestID++ )
    6456                 :            :         {
    6457                 :          0 :             const PDFNamedDest& rDest   = m_aNamedDests[ nDestID ];
    6458                 :            : // In order to correctly function both under an Internet browser and
    6459                 :            : // directly with a reader (provided the reader has the feature) we
    6460                 :            : // need to set the name of the destination the same way it will be encoded
    6461                 :            : // in an Internet link
    6462                 :            :             INetURLObject aLocalURL(
    6463         [ #  # ]:          0 :                 OUString( "http://ahost.ax"  ) ); //dummy location, won't be used
    6464         [ #  # ]:          0 :             aLocalURL.SetMark( rDest.m_aDestName );
    6465                 :            : 
    6466         [ #  # ]:          0 :             const rtl::OUString aName   = aLocalURL.GetMark( INetURLObject::NO_DECODE ); //same coding as
    6467                 :            :             // in link creation ( see PDFWriterImpl::emitLinkAnnotations )
    6468                 :          0 :             const PDFPage& rDestPage    = m_aPages[ rDest.m_nPage ];
    6469                 :            : 
    6470         [ #  # ]:          0 :             aLine.append( '/' );
    6471         [ #  # ]:          0 :             appendDestinationName( aName, aLine ); // this conversion must be done when forming the link to target ( see in emitCatalog )
    6472         [ #  # ]:          0 :             aLine.append( '[' ); // the '[' can be emitted immediately, because the appendDestinationName function
    6473                 :            :                                  //maps the preceeding character properly
    6474         [ #  # ]:          0 :             aLine.append( rDestPage.m_nPageObject );
    6475         [ #  # ]:          0 :             aLine.append( " 0 R" );
    6476                 :            : 
    6477   [ #  #  #  #  :          0 :             switch( rDest.m_eType )
             #  #  #  # ]
    6478                 :            :             {
    6479                 :            :             case PDFWriter::XYZ:
    6480                 :            :             default:
    6481         [ #  # ]:          0 :                 aLine.append( "/XYZ " );
    6482         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Left(), aLine );
    6483         [ #  # ]:          0 :                 aLine.append( ' ' );
    6484         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Bottom(), aLine );
    6485         [ #  # ]:          0 :                 aLine.append( " 0" );
    6486                 :          0 :                 break;
    6487                 :            :             case PDFWriter::Fit:
    6488         [ #  # ]:          0 :                 aLine.append( "/Fit" );
    6489                 :          0 :                 break;
    6490                 :            :             case PDFWriter::FitRectangle:
    6491         [ #  # ]:          0 :                 aLine.append( "/FitR " );
    6492         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Left(), aLine );
    6493         [ #  # ]:          0 :                 aLine.append( ' ' );
    6494         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Top(), aLine );
    6495         [ #  # ]:          0 :                 aLine.append( ' ' );
    6496         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Right(), aLine );
    6497         [ #  # ]:          0 :                 aLine.append( ' ' );
    6498         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Bottom(), aLine );
    6499                 :          0 :                 break;
    6500                 :            :             case PDFWriter::FitHorizontal:
    6501         [ #  # ]:          0 :                 aLine.append( "/FitH " );
    6502         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Bottom(), aLine );
    6503                 :          0 :                 break;
    6504                 :            :             case PDFWriter::FitVertical:
    6505         [ #  # ]:          0 :                 aLine.append( "/FitV " );
    6506         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Left(), aLine );
    6507                 :          0 :                 break;
    6508                 :            :             case PDFWriter::FitPageBoundingBox:
    6509         [ #  # ]:          0 :                 aLine.append( "/FitB" );
    6510                 :          0 :                 break;
    6511                 :            :             case PDFWriter::FitPageBoundingBoxHorizontal:
    6512         [ #  # ]:          0 :                 aLine.append( "/FitBH " );
    6513         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Bottom(), aLine );
    6514                 :          0 :                 break;
    6515                 :            :             case PDFWriter::FitPageBoundingBoxVertical:
    6516         [ #  # ]:          0 :                 aLine.append( "/FitBV " );
    6517         [ #  # ]:          0 :                 appendFixedInt( rDest.m_aRect.Left(), aLine );
    6518                 :          0 :                 break;
    6519                 :            :             }
    6520         [ #  # ]:          0 :             aLine.append( "]\n" );
    6521         [ #  # ]:          0 :         }
    6522                 :            : //close
    6523                 :            : 
    6524         [ #  # ]:          0 :         aLine.append( ">>\nendobj\n\n" );
    6525 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    6526                 :          0 :             nObject = 0;
    6527                 :            :     }
    6528                 :            :     else
    6529                 :          0 :         nObject = 0;
    6530                 :            : 
    6531                 :          0 :     return nObject;
    6532                 :            : }
    6533                 :            : //<--- i56629
    6534                 :            : 
    6535                 :            : //--->i59651
    6536                 :            : // emits the output intent dictionary
    6537                 :            : 
    6538                 :          0 : sal_Int32 PDFWriterImpl::emitOutputIntent()
    6539                 :            : {
    6540         [ #  # ]:          0 :     if( !m_bIsPDF_A1 )
    6541                 :          0 :         return 0;
    6542                 :            : 
    6543                 :            : //emit the sRGB standard profile, in ICC format, in a stream, per IEC61966-2.1
    6544                 :            : 
    6545                 :          0 :     OStringBuffer aLine( 1024 );
    6546         [ #  # ]:          0 :     sal_Int32 nICCObject = createObject();
    6547         [ #  # ]:          0 :     sal_Int32 nStreamLengthObject = createObject();
    6548                 :            : 
    6549         [ #  # ]:          0 :     aLine.append( nICCObject );
    6550                 :            : // sRGB has 3 colors, hence /N 3 below (PDF 1.4 table 4.16)
    6551         [ #  # ]:          0 :     aLine.append( " 0 obj\n<</N 3/Length " );
    6552         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
    6553         [ #  # ]:          0 :     aLine.append( " 0 R" );
    6554                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    6555         [ #  # ]:          0 :     aLine.append( "/Filter/FlateDecode" );
    6556                 :            : #endif
    6557         [ #  # ]:          0 :     aLine.append( ">>\nstream\n" );
    6558 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nICCObject ) );
    6559 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6560                 :            : //get file position
    6561                 :          0 :     sal_uInt64 nBeginStreamPos = 0;
    6562         [ #  # ]:          0 :     osl_getFilePos( m_aFile, &nBeginStreamPos );
    6563         [ #  # ]:          0 :     beginCompression();
    6564         [ #  # ]:          0 :     checkAndEnableStreamEncryption( nICCObject );
    6565         [ #  # ]:          0 :     cmsHPROFILE hProfile = cmsCreate_sRGBProfile();
    6566                 :          0 :     cmsUInt32Number nBytesNeeded = 0;
    6567         [ #  # ]:          0 :     cmsSaveProfileToMem(hProfile, NULL, &nBytesNeeded);
    6568         [ #  # ]:          0 :     if (!nBytesNeeded)
    6569                 :          0 :       return 0;
    6570         [ #  # ]:          0 :     std::vector<unsigned char> xBuffer(nBytesNeeded);
    6571 [ #  # ][ #  # ]:          0 :     cmsSaveProfileToMem(hProfile, &xBuffer[0], &nBytesNeeded);
    6572         [ #  # ]:          0 :     cmsCloseProfile(hProfile);
    6573 [ #  # ][ #  # ]:          0 :     sal_Int32 nStreamSize = writeBuffer( &xBuffer[0], (sal_Int32) xBuffer.size() );
    6574                 :          0 :     disableStreamEncryption();
    6575         [ #  # ]:          0 :     endCompression();
    6576                 :          0 :     sal_uInt64 nEndStreamPos = 0;
    6577         [ #  # ]:          0 :     osl_getFilePos( m_aFile, &nEndStreamPos );
    6578                 :            : 
    6579         [ #  # ]:          0 :     if( nStreamSize == 0 )
    6580                 :          0 :         return 0;
    6581 [ #  # ][ #  # ]:          0 :     if( ! writeBuffer( "\nendstream\nendobj\n\n", 19 ) )
    6582                 :          0 :         return 0 ;
    6583         [ #  # ]:          0 :     aLine.setLength( 0 );
    6584                 :            : 
    6585                 :            : //emit the stream length   object
    6586 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nStreamLengthObject ) );
    6587         [ #  # ]:          0 :     aLine.setLength( 0 );
    6588         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
    6589         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    6590         [ #  # ]:          0 :     aLine.append( (sal_Int64)(nEndStreamPos-nBeginStreamPos) );
    6591         [ #  # ]:          0 :     aLine.append( "\nendobj\n\n" );
    6592 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6593         [ #  # ]:          0 :     aLine.setLength( 0 );
    6594                 :            : 
    6595                 :            : //emit the OutputIntent dictionary
    6596         [ #  # ]:          0 :     sal_Int32 nOIObject = createObject();
    6597 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nOIObject ) );
    6598         [ #  # ]:          0 :     aLine.append( nOIObject );
    6599                 :            :     aLine.append( " 0 obj\n"
    6600         [ #  # ]:          0 :                   "<</Type/OutputIntent/S/GTS_PDFA1/OutputConditionIdentifier");
    6601                 :            : 
    6602                 :          0 :     rtl::OUString aComment( "sRGB IEC61966-2.1"  );
    6603         [ #  # ]:          0 :     appendLiteralStringEncrypt( aComment ,nOIObject, aLine );
    6604         [ #  # ]:          0 :     aLine.append("/DestOutputProfile ");
    6605         [ #  # ]:          0 :     aLine.append( nICCObject );
    6606         [ #  # ]:          0 :     aLine.append( " 0 R>>\nendobj\n\n" );;
    6607 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6608                 :            : 
    6609                 :          0 :     return nOIObject;
    6610                 :            : }
    6611                 :            : 
    6612                 :            : // formats the string for the XML stream
    6613                 :          0 : static void escapeStringXML( const rtl::OUString& rStr, rtl::OUString &rValue)
    6614                 :            : {
    6615                 :          0 :     const sal_Unicode* pUni = rStr.getStr();
    6616                 :          0 :     int nLen = rStr.getLength();
    6617         [ #  # ]:          0 :     for( ; nLen; nLen--, pUni++ )
    6618                 :            :     {
    6619   [ #  #  #  #  :          0 :         switch( *pUni )
                   #  # ]
    6620                 :            :         {
    6621                 :            :         case sal_Unicode('&'):
    6622                 :          0 :             rValue += rtl::OUString( "&amp;"  );
    6623                 :          0 :         break;
    6624                 :            :         case sal_Unicode('<'):
    6625                 :          0 :             rValue += rtl::OUString( "&lt;"  );
    6626                 :          0 :         break;
    6627                 :            :         case sal_Unicode('>'):
    6628                 :          0 :             rValue += rtl::OUString( "&gt;"  );
    6629                 :          0 :         break;
    6630                 :            :         case sal_Unicode('\''):
    6631                 :          0 :             rValue += rtl::OUString( "&apos;"  );
    6632                 :          0 :         break;
    6633                 :            :         case sal_Unicode('"'):
    6634                 :          0 :             rValue += rtl::OUString( "&quot;"  );
    6635                 :          0 :         break;
    6636                 :            :         default:
    6637                 :          0 :             rValue += rtl::OUString( *pUni );
    6638                 :          0 :             break;
    6639                 :            :         }
    6640                 :            :     }
    6641                 :          0 : }
    6642                 :            : 
    6643                 :            : // emits the document metadata
    6644                 :            : //
    6645                 :          0 : sal_Int32 PDFWriterImpl::emitDocumentMetadata()
    6646                 :            : {
    6647         [ #  # ]:          0 :     if( !m_bIsPDF_A1 )
    6648                 :          0 :         return 0;
    6649                 :            : 
    6650                 :            :     //get the object number for all the destinations
    6651                 :          0 :     sal_Int32 nObject = createObject();
    6652                 :            : 
    6653         [ #  # ]:          0 :     if( updateObject( nObject ) )
    6654                 :            :     {
    6655                 :            : // the following string are written in UTF-8 unicode
    6656                 :          0 :         OStringBuffer aMetadataStream( 8192 );
    6657                 :            : 
    6658         [ #  # ]:          0 :         aMetadataStream.append( "<?xpacket begin=\"" );
    6659                 :            : // this lines writes Unicode “zero width non-breaking space character” (U+FEFF) (aka byte-order mark ) used
    6660                 :            : // as a byte-order marker.
    6661 [ #  # ][ #  # ]:          0 :         aMetadataStream.append( OUStringToOString( OUString( sal_Unicode( 0xFEFF ) ), RTL_TEXTENCODING_UTF8 ) );
    6662         [ #  # ]:          0 :         aMetadataStream.append( "\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n" );
    6663         [ #  # ]:          0 :         aMetadataStream.append( "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n" );
    6664         [ #  # ]:          0 :         aMetadataStream.append( " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n" );
    6665                 :            : //PDF/A part ( ISO 19005-1:2005 - 6.7.11 )
    6666         [ #  # ]:          0 :         aMetadataStream.append( "  <rdf:Description rdf:about=\"\"\n" );
    6667         [ #  # ]:          0 :         aMetadataStream.append( "      xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n" );
    6668         [ #  # ]:          0 :         aMetadataStream.append( "   <pdfaid:part>1</pdfaid:part>\n" );
    6669         [ #  # ]:          0 :         aMetadataStream.append( "   <pdfaid:conformance>A</pdfaid:conformance>\n" );
    6670         [ #  # ]:          0 :         aMetadataStream.append( "  </rdf:Description>\n" );
    6671                 :            : //... Dublin Core properties go here
    6672   [ #  #  #  #  :          0 :         if( m_aContext.DocumentInfo.Title.Len() ||
           #  # ][ #  # ]
    6673                 :          0 :             m_aContext.DocumentInfo.Author.Len() ||
    6674                 :          0 :             m_aContext.DocumentInfo.Subject.Len() )
    6675                 :            :         {
    6676         [ #  # ]:          0 :             aMetadataStream.append( "  <rdf:Description rdf:about=\"\"\n" );
    6677         [ #  # ]:          0 :             aMetadataStream.append( "      xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n" );
    6678         [ #  # ]:          0 :             if( m_aContext.DocumentInfo.Title.Len() )
    6679                 :            :             {
    6680                 :            : // this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
    6681         [ #  # ]:          0 :                 aMetadataStream.append( "   <dc:title>\n" );
    6682         [ #  # ]:          0 :                 aMetadataStream.append( "    <rdf:Alt>\n" );
    6683         [ #  # ]:          0 :                 aMetadataStream.append( "     <rdf:li xml:lang=\"x-default\">" );
    6684                 :          0 :                 rtl::OUString aTitle;
    6685 [ #  # ][ #  # ]:          0 :                 escapeStringXML( m_aContext.DocumentInfo.Title, aTitle );
    6686 [ #  # ][ #  # ]:          0 :                 aMetadataStream.append( OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 )  );
    6687         [ #  # ]:          0 :                 aMetadataStream.append( "</rdf:li>\n" );
    6688         [ #  # ]:          0 :                 aMetadataStream.append( "    </rdf:Alt>\n" );
    6689         [ #  # ]:          0 :                 aMetadataStream.append( "   </dc:title>\n" );
    6690                 :            :             }
    6691         [ #  # ]:          0 :             if( m_aContext.DocumentInfo.Author.Len() )
    6692                 :            :             {
    6693         [ #  # ]:          0 :                 aMetadataStream.append( "   <dc:creator>\n" );
    6694         [ #  # ]:          0 :                 aMetadataStream.append( "    <rdf:Seq>\n" );
    6695         [ #  # ]:          0 :                 aMetadataStream.append( "     <rdf:li>" );
    6696                 :          0 :                 rtl::OUString aAuthor;
    6697 [ #  # ][ #  # ]:          0 :                 escapeStringXML( m_aContext.DocumentInfo.Author, aAuthor );
    6698 [ #  # ][ #  # ]:          0 :                 aMetadataStream.append( OUStringToOString( aAuthor , RTL_TEXTENCODING_UTF8 )  );
    6699         [ #  # ]:          0 :                 aMetadataStream.append( "</rdf:li>\n" );
    6700         [ #  # ]:          0 :                 aMetadataStream.append( "    </rdf:Seq>\n" );
    6701         [ #  # ]:          0 :                 aMetadataStream.append( "   </dc:creator>\n" );
    6702                 :            :             }
    6703         [ #  # ]:          0 :             if( m_aContext.DocumentInfo.Subject.Len() )
    6704                 :            :             {
    6705                 :            : // this is according to PDF/A-1, technical corrigendum 1 (2007-04-01)
    6706         [ #  # ]:          0 :                 aMetadataStream.append( "   <dc:description>\n" );
    6707         [ #  # ]:          0 :                 aMetadataStream.append( "    <rdf:Alt>\n" );
    6708         [ #  # ]:          0 :                 aMetadataStream.append( "     <rdf:li xml:lang=\"x-default\">" );
    6709                 :          0 :                 rtl::OUString aSubject;
    6710 [ #  # ][ #  # ]:          0 :                 escapeStringXML( m_aContext.DocumentInfo.Subject, aSubject );
    6711 [ #  # ][ #  # ]:          0 :                 aMetadataStream.append( OUStringToOString( aSubject , RTL_TEXTENCODING_UTF8 )  );
    6712         [ #  # ]:          0 :                 aMetadataStream.append( "</rdf:li>\n" );
    6713         [ #  # ]:          0 :                 aMetadataStream.append( "    </rdf:Alt>\n" );
    6714         [ #  # ]:          0 :                 aMetadataStream.append( "   </dc:description>\n" );
    6715                 :            :             }
    6716         [ #  # ]:          0 :             aMetadataStream.append( "  </rdf:Description>\n" );
    6717                 :            :         }
    6718                 :            : 
    6719                 :            : //... PDF properties go here
    6720   [ #  #  #  # ]:          0 :         if( m_aContext.DocumentInfo.Producer.Len() ||
                 [ #  # ]
    6721                 :          0 :             m_aContext.DocumentInfo.Keywords.Len() )
    6722                 :            :         {
    6723         [ #  # ]:          0 :             aMetadataStream.append( "  <rdf:Description rdf:about=\"\"\n" );
    6724         [ #  # ]:          0 :             aMetadataStream.append( "     xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n" );
    6725         [ #  # ]:          0 :             if( m_aContext.DocumentInfo.Producer.Len() )
    6726                 :            :             {
    6727         [ #  # ]:          0 :                 aMetadataStream.append( "   <pdf:Producer>" );
    6728                 :          0 :                 rtl::OUString aProducer;
    6729 [ #  # ][ #  # ]:          0 :                 escapeStringXML( m_aContext.DocumentInfo.Producer, aProducer );
    6730 [ #  # ][ #  # ]:          0 :                 aMetadataStream.append( OUStringToOString( aProducer , RTL_TEXTENCODING_UTF8 )  );
    6731         [ #  # ]:          0 :                 aMetadataStream.append( "</pdf:Producer>\n" );
    6732                 :            :             }
    6733         [ #  # ]:          0 :             if( m_aContext.DocumentInfo.Keywords.Len() )
    6734                 :            :             {
    6735         [ #  # ]:          0 :                 aMetadataStream.append( "   <pdf:Keywords>" );
    6736                 :          0 :                 rtl::OUString aKeywords;
    6737 [ #  # ][ #  # ]:          0 :                 escapeStringXML( m_aContext.DocumentInfo.Keywords, aKeywords );
    6738 [ #  # ][ #  # ]:          0 :                 aMetadataStream.append( OUStringToOString( aKeywords , RTL_TEXTENCODING_UTF8 )  );
    6739         [ #  # ]:          0 :                 aMetadataStream.append( "</pdf:Keywords>\n" );
    6740                 :            :             }
    6741         [ #  # ]:          0 :             aMetadataStream.append( "  </rdf:Description>\n" );
    6742                 :            :         }
    6743                 :            : 
    6744         [ #  # ]:          0 :         aMetadataStream.append( "  <rdf:Description rdf:about=\"\"\n" );
    6745         [ #  # ]:          0 :         aMetadataStream.append( "    xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">\n" );
    6746         [ #  # ]:          0 :         if( m_aContext.DocumentInfo.Creator.Len() )
    6747                 :            :         {
    6748         [ #  # ]:          0 :             aMetadataStream.append( "   <xmp:CreatorTool>" );
    6749                 :          0 :             rtl::OUString aCreator;
    6750 [ #  # ][ #  # ]:          0 :             escapeStringXML( m_aContext.DocumentInfo.Creator, aCreator );
    6751 [ #  # ][ #  # ]:          0 :             aMetadataStream.append( OUStringToOString( aCreator , RTL_TEXTENCODING_UTF8 )  );
    6752         [ #  # ]:          0 :             aMetadataStream.append( "</xmp:CreatorTool>\n" );
    6753                 :            :         }
    6754                 :            : //creation date
    6755         [ #  # ]:          0 :         aMetadataStream.append( "   <xmp:CreateDate>" );
    6756         [ #  # ]:          0 :         aMetadataStream.append( m_aCreationMetaDateString );
    6757         [ #  # ]:          0 :         aMetadataStream.append( "</xmp:CreateDate>\n" );
    6758                 :            : 
    6759         [ #  # ]:          0 :         aMetadataStream.append( "  </rdf:Description>\n" );
    6760         [ #  # ]:          0 :         aMetadataStream.append( " </rdf:RDF>\n" );
    6761         [ #  # ]:          0 :         aMetadataStream.append( "</x:xmpmeta>\n" );
    6762                 :            : 
    6763                 :            : //add the padding
    6764         [ #  # ]:          0 :         for( sal_Int32 nSpaces = 1; nSpaces <= 2100; nSpaces++ )
    6765                 :            :         {
    6766         [ #  # ]:          0 :             aMetadataStream.append( " " );
    6767         [ #  # ]:          0 :             if( nSpaces % 100 == 0 )
    6768         [ #  # ]:          0 :                 aMetadataStream.append( "\n" );
    6769                 :            :         }
    6770                 :            : 
    6771         [ #  # ]:          0 :         aMetadataStream.append( "<?xpacket end=\"w\"?>\n" );
    6772                 :            : 
    6773                 :          0 :         OStringBuffer aMetadataObj( 1024 );
    6774                 :            : 
    6775         [ #  # ]:          0 :         aMetadataObj.append( nObject );
    6776         [ #  # ]:          0 :         aMetadataObj.append( " 0 obj\n" );
    6777                 :            : 
    6778         [ #  # ]:          0 :         aMetadataObj.append( "<</Type/Metadata/Subtype/XML/Length " );
    6779                 :            : 
    6780         [ #  # ]:          0 :         aMetadataObj.append( (sal_Int32) aMetadataStream.getLength() );
    6781         [ #  # ]:          0 :         aMetadataObj.append( ">>\nstream\n" );
    6782 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aMetadataObj.getStr(), aMetadataObj.getLength() ) );
    6783                 :            : //emit the stream
    6784 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aMetadataStream.getStr(), aMetadataStream.getLength() ) );
    6785                 :            : 
    6786         [ #  # ]:          0 :         aMetadataObj.setLength( 0 );
    6787         [ #  # ]:          0 :         aMetadataObj.append( "\nendstream\nendobj\n\n" );
    6788 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( aMetadataObj.getStr(), aMetadataObj.getLength() ) )
    6789 [ #  # ][ #  # ]:          0 :             nObject = 0;
    6790                 :            :     }
    6791                 :            :     else
    6792                 :          0 :         nObject = 0;
    6793                 :            : 
    6794                 :          0 :     return nObject;
    6795                 :            : }
    6796                 :            : //<---i59651
    6797                 :            : 
    6798                 :          0 : bool PDFWriterImpl::emitTrailer()
    6799                 :            : {
    6800                 :            :     // emit doc info
    6801                 :          0 :     OString aInfoValuesOut;
    6802         [ #  # ]:          0 :     sal_Int32 nDocInfoObject = emitInfoDict( );
    6803                 :            : 
    6804                 :          0 :     sal_Int32 nSecObject = 0;
    6805                 :            : 
    6806         [ #  # ]:          0 :     if( m_aContext.Encryption.Encrypt() )
    6807                 :            :     {
    6808                 :            : //emit the security information
    6809                 :            : //must be emitted as indirect dictionary object, since
    6810                 :            : //Acrobat Reader 5 works only with this kind of implementation
    6811         [ #  # ]:          0 :         nSecObject = createObject();
    6812                 :            : 
    6813 [ #  # ][ #  # ]:          0 :         if( updateObject( nSecObject ) )
    6814                 :            :         {
    6815                 :          0 :             OStringBuffer aLineS( 1024 );
    6816         [ #  # ]:          0 :             aLineS.append( nSecObject );
    6817                 :            :             aLineS.append( " 0 obj\n"
    6818         [ #  # ]:          0 :                            "<</Filter/Standard/V " );
    6819                 :            :             // check the version
    6820         [ #  # ]:          0 :             if( m_aContext.Encryption.Security128bit )
    6821         [ #  # ]:          0 :                 aLineS.append( "2/Length 128/R 3" );
    6822                 :            :             else
    6823         [ #  # ]:          0 :                 aLineS.append( "1/R 2" );
    6824                 :            : 
    6825                 :            :             // emit the owner password, must not be encrypted
    6826         [ #  # ]:          0 :             aLineS.append( "/O(" );
    6827 [ #  # ][ #  # ]:          0 :             appendLiteralString( (const sal_Char*)&m_aContext.Encryption.OValue[0], sal_Int32(m_aContext.Encryption.OValue.size()), aLineS );
    6828         [ #  # ]:          0 :             aLineS.append( ")/U(" );
    6829 [ #  # ][ #  # ]:          0 :             appendLiteralString( (const sal_Char*)&m_aContext.Encryption.UValue[0], sal_Int32(m_aContext.Encryption.UValue.size()), aLineS );
    6830         [ #  # ]:          0 :             aLineS.append( ")/P " );// the permission set
    6831         [ #  # ]:          0 :             aLineS.append( m_nAccessPermissions );
    6832         [ #  # ]:          0 :             aLineS.append( ">>\nendobj\n\n" );
    6833 [ #  # ][ #  # ]:          0 :             if( !writeBuffer( aLineS.getStr(), aLineS.getLength() ) )
    6834                 :          0 :                 nSecObject = 0;
    6835                 :            :         }
    6836                 :            :         else
    6837                 :          0 :             nSecObject = 0;
    6838                 :            :     }
    6839                 :            :     // emit xref table
    6840                 :            :     // remember start
    6841                 :          0 :     sal_uInt64 nXRefOffset = 0;
    6842 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nXRefOffset )) );
    6843 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( "xref\n", 5 ) );
    6844                 :            : 
    6845                 :          0 :     sal_Int32 nObjects = m_aObjects.size();
    6846                 :          0 :     OStringBuffer aLine;
    6847         [ #  # ]:          0 :     aLine.append( "0 " );
    6848         [ #  # ]:          0 :     aLine.append( (sal_Int32)(nObjects+1) );
    6849         [ #  # ]:          0 :     aLine.append( "\n" );
    6850         [ #  # ]:          0 :     aLine.append( "0000000000 65535 f \n" );
    6851 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6852                 :            : 
    6853         [ #  # ]:          0 :     for( sal_Int32 i = 0; i < nObjects; i++ )
    6854                 :            :     {
    6855         [ #  # ]:          0 :         aLine.setLength( 0 );
    6856         [ #  # ]:          0 :         OString aOffset = OString::valueOf( (sal_Int64)m_aObjects[i] );
    6857         [ #  # ]:          0 :         for( sal_Int32 j = 0; j < (10-aOffset.getLength()); j++ )
    6858         [ #  # ]:          0 :             aLine.append( '0' );
    6859         [ #  # ]:          0 :         aLine.append( aOffset );
    6860         [ #  # ]:          0 :         aLine.append( " 00000 n \n" );
    6861                 :            :         DBG_ASSERT( aLine.getLength() == 20, "invalid xref entry" );
    6862 [ #  # ][ #  # ]:          0 :         CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6863         [ #  # ]:          0 :     }
    6864                 :            : 
    6865                 :            :     // prepare document checksum
    6866                 :          0 :     OStringBuffer aDocChecksum( 2*RTL_DIGEST_LENGTH_MD5+1 );
    6867         [ #  # ]:          0 :     if( m_aDocDigest )
    6868                 :            :     {
    6869                 :            :         sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
    6870                 :          0 :         rtl_digest_getMD5( m_aDocDigest, nMD5Sum, sizeof(nMD5Sum) );
    6871         [ #  # ]:          0 :         for( unsigned int i = 0; i < RTL_DIGEST_LENGTH_MD5; i++ )
    6872         [ #  # ]:          0 :             appendHex( nMD5Sum[i], aDocChecksum );
    6873                 :            :     }
    6874                 :            :     // document id set in setDocInfo method
    6875                 :            :     // emit trailer
    6876         [ #  # ]:          0 :     aLine.setLength( 0 );
    6877                 :            :     aLine.append( "trailer\n"
    6878         [ #  # ]:          0 :                   "<</Size " );
    6879         [ #  # ]:          0 :     aLine.append( (sal_Int32)(nObjects+1) );
    6880         [ #  # ]:          0 :     aLine.append( "/Root " );
    6881         [ #  # ]:          0 :     aLine.append( m_nCatalogObject );
    6882         [ #  # ]:          0 :     aLine.append( " 0 R\n" );
    6883         [ #  # ]:          0 :     if( nSecObject )
    6884                 :            :     {
    6885         [ #  # ]:          0 :         aLine.append( "/Encrypt ");
    6886         [ #  # ]:          0 :         aLine.append( nSecObject );
    6887         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    6888                 :            :     }
    6889         [ #  # ]:          0 :     if( nDocInfoObject )
    6890                 :            :     {
    6891         [ #  # ]:          0 :         aLine.append( "/Info " );
    6892         [ #  # ]:          0 :         aLine.append( nDocInfoObject );
    6893         [ #  # ]:          0 :         aLine.append( " 0 R\n" );
    6894                 :            :     }
    6895         [ #  # ]:          0 :     if( ! m_aContext.Encryption.DocumentIdentifier.empty() )
    6896                 :            :     {
    6897         [ #  # ]:          0 :         aLine.append( "/ID [ <" );
    6898         [ #  # ]:          0 :         for( std::vector< sal_uInt8 >::const_iterator it = m_aContext.Encryption.DocumentIdentifier.begin();
           [ #  #  #  # ]
                 [ #  # ]
    6899                 :          0 :              it != m_aContext.Encryption.DocumentIdentifier.end(); ++it )
    6900                 :            :         {
    6901 [ #  # ][ #  # ]:          0 :             appendHex( sal_Int8(*it), aLine );
    6902                 :            :         }
    6903                 :            :         aLine.append( ">\n"
    6904         [ #  # ]:          0 :                       "<" );
    6905         [ #  # ]:          0 :         for( std::vector< sal_uInt8 >::const_iterator it = m_aContext.Encryption.DocumentIdentifier.begin();
           [ #  #  #  # ]
                 [ #  # ]
    6906                 :          0 :              it != m_aContext.Encryption.DocumentIdentifier.end(); ++it )
    6907                 :            :         {
    6908 [ #  # ][ #  # ]:          0 :             appendHex( sal_Int8(*it), aLine );
    6909                 :            :         }
    6910         [ #  # ]:          0 :         aLine.append( "> ]\n" );
    6911                 :            :     }
    6912         [ #  # ]:          0 :     if( aDocChecksum.getLength() )
    6913                 :            :     {
    6914         [ #  # ]:          0 :         aLine.append( "/DocChecksum /" );
    6915         [ #  # ]:          0 :         aLine.append( aDocChecksum.makeStringAndClear() );
    6916         [ #  # ]:          0 :         aLine.append( "\n" );
    6917                 :            :     }
    6918         [ #  # ]:          0 :     if( m_aAdditionalStreams.size() > 0 )
    6919                 :            :     {
    6920         [ #  # ]:          0 :         aLine.append( "/AdditionalStreams [" );
    6921         [ #  # ]:          0 :         for( unsigned int i = 0; i < m_aAdditionalStreams.size(); i++ )
    6922                 :            :         {
    6923         [ #  # ]:          0 :             aLine.append( "/" );
    6924         [ #  # ]:          0 :             appendName( m_aAdditionalStreams[i].m_aMimeType, aLine );
    6925         [ #  # ]:          0 :             aLine.append( " " );
    6926         [ #  # ]:          0 :             aLine.append( m_aAdditionalStreams[i].m_nStreamObject );
    6927         [ #  # ]:          0 :             aLine.append( " 0 R\n" );
    6928                 :            :         }
    6929         [ #  # ]:          0 :         aLine.append( "]\n" );
    6930                 :            :     }
    6931                 :            :     aLine.append( ">>\n"
    6932         [ #  # ]:          0 :                   "startxref\n" );
    6933         [ #  # ]:          0 :     aLine.append( (sal_Int64)nXRefOffset );
    6934                 :            :     aLine.append( "\n"
    6935         [ #  # ]:          0 :                   "%%EOF\n" );
    6936 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    6937                 :            : 
    6938                 :          0 :     return true;
    6939                 :            : }
    6940                 :            : 
    6941                 :            : struct AnnotationSortEntry
    6942                 :            : {
    6943                 :            :     sal_Int32 nTabOrder;
    6944                 :            :     sal_Int32 nObject;
    6945                 :            :     sal_Int32 nWidgetIndex;
    6946                 :            : 
    6947                 :          0 :     AnnotationSortEntry( sal_Int32 nTab, sal_Int32 nObj, sal_Int32 nI ) :
    6948                 :            :         nTabOrder( nTab ),
    6949                 :            :         nObject( nObj ),
    6950                 :          0 :         nWidgetIndex( nI )
    6951                 :          0 :     {}
    6952                 :            : };
    6953                 :            : 
    6954         [ #  # ]:          0 : struct AnnotSortContainer
    6955                 :            : {
    6956                 :            :     std::set< sal_Int32 >               aObjects;
    6957                 :            :     std::vector< AnnotationSortEntry >    aSortedAnnots;
    6958                 :            : };
    6959                 :            : 
    6960                 :            : struct AnnotSorterLess
    6961                 :            : {
    6962                 :            :     std::vector< PDFWriterImpl::PDFWidget >& m_rWidgets;
    6963                 :            : 
    6964                 :          0 :     AnnotSorterLess( std::vector< PDFWriterImpl::PDFWidget >& rWidgets ) : m_rWidgets( rWidgets ) {}
    6965                 :            : 
    6966                 :          0 :     bool operator()( const AnnotationSortEntry& rLeft, const AnnotationSortEntry& rRight )
    6967                 :            :     {
    6968         [ #  # ]:          0 :         if( rLeft.nTabOrder < rRight.nTabOrder )
    6969                 :          0 :             return true;
    6970         [ #  # ]:          0 :         if( rRight.nTabOrder < rLeft.nTabOrder )
    6971                 :          0 :             return false;
    6972 [ #  # ][ #  # ]:          0 :         if( rLeft.nWidgetIndex < 0 && rRight.nWidgetIndex < 0 )
    6973                 :          0 :             return false;
    6974         [ #  # ]:          0 :         if( rRight.nWidgetIndex < 0 )
    6975                 :          0 :             return true;
    6976         [ #  # ]:          0 :         if( rLeft.nWidgetIndex < 0 )
    6977                 :          0 :             return false;
    6978                 :            :         // remember: widget rects are in PDF coordinates, so they are ordered down up
    6979         [ #  # ]:          0 :         if( m_rWidgets[ rLeft.nWidgetIndex ].m_aRect.Top() >
    6980                 :          0 :             m_rWidgets[ rRight.nWidgetIndex ].m_aRect.Top() )
    6981                 :          0 :             return true;
    6982         [ #  # ]:          0 :         if( m_rWidgets[ rRight.nWidgetIndex ].m_aRect.Top() >
    6983                 :          0 :             m_rWidgets[ rLeft.nWidgetIndex ].m_aRect.Top() )
    6984                 :          0 :             return false;
    6985         [ #  # ]:          0 :         if( m_rWidgets[ rLeft.nWidgetIndex ].m_aRect.Left() <
    6986                 :          0 :             m_rWidgets[ rRight.nWidgetIndex ].m_aRect.Left() )
    6987                 :          0 :             return true;
    6988                 :          0 :         return false;
    6989                 :            :     }
    6990                 :            : };
    6991                 :            : 
    6992                 :          0 : void PDFWriterImpl::sortWidgets()
    6993                 :            : {
    6994                 :            :     // sort widget annotations on each page as per their
    6995                 :            :     // TabOrder attribute
    6996         [ #  # ]:          0 :     boost::unordered_map< sal_Int32, AnnotSortContainer > sorted;
    6997                 :          0 :     int nWidgets = m_aWidgets.size();
    6998         [ #  # ]:          0 :     for( int nW = 0; nW < nWidgets; nW++ )
    6999                 :            :     {
    7000                 :          0 :         const PDFWidget& rWidget = m_aWidgets[nW];
    7001         [ #  # ]:          0 :         if( rWidget.m_nPage >= 0 )
    7002                 :            :         {
    7003         [ #  # ]:          0 :             AnnotSortContainer& rCont = sorted[ rWidget.m_nPage ];
    7004                 :            :             // optimize vector allocation
    7005         [ #  # ]:          0 :             if( rCont.aSortedAnnots.empty() )
    7006         [ #  # ]:          0 :                 rCont.aSortedAnnots.reserve( m_aPages[ rWidget.m_nPage ].m_aAnnotations.size() );
    7007                 :            :             // insert widget to tab sorter
    7008                 :            :             // RadioButtons are not page annotations, only their individual check boxes are
    7009         [ #  # ]:          0 :             if( rWidget.m_eType != PDFWriter::RadioButton )
    7010                 :            :             {
    7011         [ #  # ]:          0 :                 rCont.aObjects.insert( rWidget.m_nObject );
    7012         [ #  # ]:          0 :                 rCont.aSortedAnnots.push_back( AnnotationSortEntry( rWidget.m_nTabOrder, rWidget.m_nObject, nW ) );
    7013                 :            :             }
    7014                 :            :         }
    7015                 :            :     }
    7016 [ #  # ][ #  # ]:          0 :     for( boost::unordered_map< sal_Int32, AnnotSortContainer >::iterator it = sorted.begin(); it != sorted.end(); ++it )
                 [ #  # ]
    7017                 :            :     {
    7018                 :            :         // append entries for non widget annotations
    7019         [ #  # ]:          0 :         PDFPage& rPage = m_aPages[ it->first ];
    7020                 :          0 :         unsigned int nAnnots = rPage.m_aAnnotations.size();
    7021         [ #  # ]:          0 :         for( unsigned int nA = 0; nA < nAnnots; nA++ )
    7022 [ #  # ][ #  # ]:          0 :             if( it->second.aObjects.find( rPage.m_aAnnotations[nA] ) == it->second.aObjects.end())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7023 [ #  # ][ #  # ]:          0 :                 it->second.aSortedAnnots.push_back( AnnotationSortEntry( 10000, rPage.m_aAnnotations[nA], -1 ) );
                 [ #  # ]
    7024                 :            : 
    7025                 :          0 :         AnnotSorterLess aLess( m_aWidgets );
    7026 [ #  # ][ #  # ]:          0 :         std::stable_sort( it->second.aSortedAnnots.begin(), it->second.aSortedAnnots.end(), aLess );
                 [ #  # ]
    7027                 :            :         // sanity check
    7028 [ #  # ][ #  # ]:          0 :         if( it->second.aSortedAnnots.size() == nAnnots)
    7029                 :            :         {
    7030         [ #  # ]:          0 :             for( unsigned int nA = 0; nA < nAnnots; nA++ )
    7031 [ #  # ][ #  # ]:          0 :                 rPage.m_aAnnotations[nA] = it->second.aSortedAnnots[nA].nObject;
    7032                 :            :         }
    7033                 :            :         else
    7034                 :            :         {
    7035                 :            :             DBG_ASSERT( 0, "wrong number of sorted annotations" );
    7036                 :            :             #if OSL_DEBUG_LEVEL > 0
    7037                 :            :             fprintf( stderr, "PDFWriterImpl::sortWidgets(): wrong number of sorted assertions on page nr %ld\n"
    7038                 :            :                      "    %ld sorted and %ld unsorted\n", (long int)it->first, (long int)it->second.aSortedAnnots.size(), (long int)nAnnots );
    7039                 :            :             #endif
    7040                 :            :         }
    7041         [ #  # ]:          0 :     }
    7042                 :            : 
    7043                 :            :     // FIXME: implement tab order in structure tree for PDF 1.5
    7044                 :          0 : }
    7045                 :            : 
    7046                 :            : namespace vcl {
    7047                 :            : class PDFStreamIf :
    7048                 :            :         public cppu::WeakImplHelper1< com::sun::star::io::XOutputStream >
    7049                 :            : {
    7050                 :            :     PDFWriterImpl*  m_pWriter;
    7051                 :            :     bool            m_bWrite;
    7052                 :            :     public:
    7053                 :          0 :     PDFStreamIf( PDFWriterImpl* pWriter ) : m_pWriter( pWriter ), m_bWrite( true ) {}
    7054                 :            :     virtual ~PDFStreamIf();
    7055                 :            : 
    7056                 :            :     virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw();
    7057                 :            :     virtual void SAL_CALL flush() throw();
    7058                 :            :     virtual void SAL_CALL closeOutput() throw();
    7059                 :            : };
    7060                 :            : }
    7061                 :            : 
    7062                 :          0 : PDFStreamIf::~PDFStreamIf()
    7063                 :            : {
    7064         [ #  # ]:          0 : }
    7065                 :            : 
    7066                 :          0 : void SAL_CALL  PDFStreamIf::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw()
    7067                 :            : {
    7068 [ #  # ][ #  # ]:          0 :     if( m_bWrite && aData.getLength() )
                 [ #  # ]
    7069                 :            :     {
    7070                 :          0 :         sal_Int32 nBytes = aData.getLength();
    7071                 :          0 :         m_pWriter->writeBuffer( aData.getConstArray(), nBytes );
    7072                 :            :     }
    7073                 :          0 : }
    7074                 :            : 
    7075                 :          0 : void SAL_CALL PDFStreamIf::flush() throw()
    7076                 :            : {
    7077                 :          0 : }
    7078                 :            : 
    7079                 :          0 : void SAL_CALL PDFStreamIf::closeOutput() throw()
    7080                 :            : {
    7081                 :          0 :     m_bWrite = false;
    7082                 :          0 : }
    7083                 :            : 
    7084                 :          0 : bool PDFWriterImpl::emitAdditionalStreams()
    7085                 :            : {
    7086                 :          0 :     unsigned int nStreams = m_aAdditionalStreams.size();
    7087         [ #  # ]:          0 :     for( unsigned int i = 0; i < nStreams; i++ )
    7088                 :            :     {
    7089                 :          0 :         PDFAddStream& rStream = m_aAdditionalStreams[i];
    7090         [ #  # ]:          0 :         rStream.m_nStreamObject = createObject();
    7091         [ #  # ]:          0 :         sal_Int32 nSizeObject = createObject();
    7092                 :            : 
    7093 [ #  # ][ #  # ]:          0 :         if( ! updateObject( rStream.m_nStreamObject ) )
    7094                 :          0 :             return false;
    7095                 :            : 
    7096                 :          0 :         OStringBuffer aLine;
    7097         [ #  # ]:          0 :         aLine.append( rStream.m_nStreamObject );
    7098         [ #  # ]:          0 :         aLine.append( " 0 obj\n<</Length " );
    7099         [ #  # ]:          0 :         aLine.append( nSizeObject );
    7100         [ #  # ]:          0 :         aLine.append( " 0 R" );
    7101         [ #  # ]:          0 :         if( rStream.m_bCompress )
    7102         [ #  # ]:          0 :             aLine.append( "/Filter/FlateDecode" );
    7103         [ #  # ]:          0 :         aLine.append( ">>\nstream\n" );
    7104 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    7105                 :          0 :             return false;
    7106                 :          0 :         sal_uInt64 nBeginStreamPos = 0, nEndStreamPos = 0;
    7107 [ #  # ][ #  # ]:          0 :         if( osl_File_E_None != osl_getFilePos( m_aFile, &nBeginStreamPos ) )
    7108                 :            :         {
    7109         [ #  # ]:          0 :             osl_closeFile( m_aFile );
    7110                 :          0 :             m_bOpen = false;
    7111                 :            :         }
    7112         [ #  # ]:          0 :         if( rStream.m_bCompress )
    7113         [ #  # ]:          0 :             beginCompression();
    7114                 :            : 
    7115         [ #  # ]:          0 :         checkAndEnableStreamEncryption( rStream.m_nStreamObject );
    7116 [ #  # ][ #  # ]:          0 :         com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > xStream( new PDFStreamIf( this ) );
                 [ #  # ]
    7117         [ #  # ]:          0 :         rStream.m_pStream->write( xStream );
    7118                 :          0 :         xStream.clear();
    7119 [ #  # ][ #  # ]:          0 :         delete rStream.m_pStream;
    7120                 :          0 :         rStream.m_pStream = NULL;
    7121                 :          0 :         disableStreamEncryption();
    7122                 :            : 
    7123         [ #  # ]:          0 :         if( rStream.m_bCompress )
    7124         [ #  # ]:          0 :             endCompression();
    7125                 :            : 
    7126 [ #  # ][ #  # ]:          0 :         if( osl_File_E_None != osl_getFilePos( m_aFile, &nEndStreamPos ) )
    7127                 :            :         {
    7128         [ #  # ]:          0 :             osl_closeFile( m_aFile );
    7129                 :          0 :             m_bOpen = false;
    7130                 :          0 :             return false;
    7131                 :            :         }
    7132 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( "\nendstream\nendobj\n\n", 19 ) )
    7133                 :          0 :             return false ;
    7134                 :            :         // emit stream length object
    7135 [ #  # ][ #  # ]:          0 :         if( ! updateObject( nSizeObject ) )
    7136                 :          0 :             return false;
    7137         [ #  # ]:          0 :         aLine.setLength( 0 );
    7138         [ #  # ]:          0 :         aLine.append( nSizeObject );
    7139         [ #  # ]:          0 :         aLine.append( " 0 obj\n" );
    7140         [ #  # ]:          0 :         aLine.append( (sal_Int64)(nEndStreamPos-nBeginStreamPos) );
    7141         [ #  # ]:          0 :         aLine.append( "\nendobj\n\n" );
    7142 [ #  # ][ #  # ]:          0 :         if( ! writeBuffer( aLine.getStr(), aLine.getLength() ) )
    7143                 :          0 :             return false;
    7144 [ #  # ][ #  # ]:          0 :     }
    7145                 :          0 :     return true;
    7146                 :            : }
    7147                 :            : 
    7148                 :          0 : bool PDFWriterImpl::emit()
    7149                 :            : {
    7150                 :          0 :     endPage();
    7151                 :            : 
    7152                 :            :     // resort structure tree and annotations if necessary
    7153                 :            :     // needed for widget tab order
    7154                 :          0 :     sortWidgets();
    7155                 :            : 
    7156                 :            : #if !defined(ANDROID) && !defined(IOS)
    7157         [ #  # ]:          0 :     if( m_aContext.SignPDF )
    7158                 :            :     {
    7159                 :            :         // sign the document
    7160         [ #  # ]:          0 :         PDFWriter::SignatureWidget aSignature;
    7161                 :          0 :         aSignature.Name = OUString("Signature1");
    7162 [ #  # ][ #  # ]:          0 :         createControl( aSignature, 0 );
    7163                 :            :     }
    7164                 :            : #endif
    7165                 :            : 
    7166                 :            :     // emit additional streams
    7167         [ #  # ]:          0 :     CHECK_RETURN( emitAdditionalStreams() );
    7168                 :            : 
    7169                 :            :     // emit catalog
    7170         [ #  # ]:          0 :     CHECK_RETURN( emitCatalog() );
    7171                 :            : 
    7172                 :            : #if !defined(ANDROID) && !defined(IOS)
    7173         [ #  # ]:          0 :     if (m_nSignatureObject != -1) // if document is signed, emit sigdict
    7174         [ #  # ]:          0 :         CHECK_RETURN( emitSignature() );
    7175                 :            : #endif
    7176                 :            : 
    7177                 :            :     // emit trailer
    7178         [ #  # ]:          0 :     CHECK_RETURN( emitTrailer() );
    7179                 :            : 
    7180                 :            : #if !defined(ANDROID) && !defined(IOS)
    7181         [ #  # ]:          0 :     if (m_nSignatureObject != -1) // finalize the signature
    7182         [ #  # ]:          0 :         CHECK_RETURN( finalizeSignature() );
    7183                 :            : #endif
    7184                 :            : 
    7185                 :          0 :     osl_closeFile( m_aFile );
    7186                 :          0 :     m_bOpen = false;
    7187                 :            : 
    7188                 :          0 :     return true;
    7189                 :            : }
    7190                 :            : 
    7191                 :          0 : std::set< PDFWriter::ErrorCode > PDFWriterImpl::getErrors()
    7192                 :            : {
    7193                 :          0 :     return m_aErrors;
    7194                 :            : }
    7195                 :            : 
    7196                 :          0 : sal_Int32 PDFWriterImpl::getSystemFont( const Font& i_rFont )
    7197                 :            : {
    7198 [ #  # ][ #  # ]:          0 :     getReferenceDevice()->Push();
    7199 [ #  # ][ #  # ]:          0 :     getReferenceDevice()->SetFont( i_rFont );
    7200 [ #  # ][ #  # ]:          0 :     getReferenceDevice()->ImplNewFont();
    7201                 :            : 
    7202                 :          0 :     const PhysicalFontFace* pDevFont = m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData;
    7203                 :          0 :     sal_Int32 nFontID = 0;
    7204         [ #  # ]:          0 :     FontEmbedData::iterator it = m_aSystemFonts.find( pDevFont );
    7205         [ #  # ]:          0 :     if( it != m_aSystemFonts.end() )
    7206                 :          0 :         nFontID = it->second.m_nNormalFontID;
    7207                 :            :     else
    7208                 :            :     {
    7209                 :          0 :         nFontID = m_nNextFID++;
    7210 [ #  # ][ #  # ]:          0 :         m_aSystemFonts[ pDevFont ] = EmbedFont();
                 [ #  # ]
    7211         [ #  # ]:          0 :         m_aSystemFonts[ pDevFont ].m_nNormalFontID = nFontID;
    7212                 :            :     }
    7213                 :            : 
    7214 [ #  # ][ #  # ]:          0 :     getReferenceDevice()->Pop();
    7215 [ #  # ][ #  # ]:          0 :     getReferenceDevice()->ImplNewFont();
    7216                 :            : 
    7217                 :          0 :     return nFontID;
    7218                 :            : }
    7219                 :            : 
    7220                 :          0 : void PDFWriterImpl::registerGlyphs( int nGlyphs,
    7221                 :            :                                     sal_GlyphId* pGlyphs,
    7222                 :            :                                     sal_Int32* pGlyphWidths,
    7223                 :            :                                     sal_Ucs* pUnicodes,
    7224                 :            :                                     sal_Int32* pUnicodesPerGlyph,
    7225                 :            :                                     sal_uInt8* pMappedGlyphs,
    7226                 :            :                                     sal_Int32* pMappedFontObjects,
    7227                 :            :                                     const PhysicalFontFace* pFallbackFonts[] )
    7228                 :            : {
    7229                 :          0 :     const PhysicalFontFace* pDevFont = m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData;
    7230                 :          0 :     sal_Ucs* pCurUnicode = pUnicodes;
    7231         [ #  # ]:          0 :     for( int i = 0; i < nGlyphs; pCurUnicode += pUnicodesPerGlyph[i] , i++ )
    7232                 :            :     {
    7233                 :          0 :         const int nFontGlyphId = pGlyphs[i] & (GF_IDXMASK | GF_ISCHAR | GF_GSUB);
    7234         [ #  # ]:          0 :         const PhysicalFontFace* pCurrentFont = pFallbackFonts[i] ? pFallbackFonts[i] : pDevFont;
    7235                 :            : 
    7236         [ #  # ]:          0 :         if( isBuiltinFont( pCurrentFont ) )
    7237                 :            :         {
    7238                 :          0 :             sal_Int32 nFontID = 0;
    7239         [ #  # ]:          0 :             FontEmbedData::iterator it = m_aEmbeddedFonts.find( pCurrentFont );
    7240         [ #  # ]:          0 :             if( it != m_aEmbeddedFonts.end() )
    7241                 :          0 :                 nFontID = it->second.m_nNormalFontID;
    7242                 :            :             else
    7243                 :            :             {
    7244                 :          0 :                 nFontID = m_nNextFID++;
    7245 [ #  # ][ #  # ]:          0 :                 m_aEmbeddedFonts[ pCurrentFont ] = EmbedFont();
                 [ #  # ]
    7246         [ #  # ]:          0 :                 m_aEmbeddedFonts[ pCurrentFont ].m_nNormalFontID = nFontID;
    7247                 :            :             }
    7248                 :            : 
    7249                 :          0 :             pGlyphWidths[ i ] = 0;
    7250                 :          0 :             pMappedGlyphs[ i ] = sal::static_int_cast<sal_Int8>( nFontGlyphId );
    7251                 :          0 :             pMappedFontObjects[ i ] = nFontID;
    7252                 :          0 :             const ImplPdfBuiltinFontData* pFD = GetPdfFontData( pCurrentFont );
    7253         [ #  # ]:          0 :             if( pFD )
    7254                 :            :             {
    7255                 :          0 :                 const BuiltinFont* pBuiltinFont = pFD->GetBuiltinFont();
    7256                 :          0 :                 pGlyphWidths[i] = pBuiltinFont->m_aWidths[ nFontGlyphId & 0x00ff ];
    7257                 :            :             }
    7258                 :            :         }
    7259         [ #  # ]:          0 :         else if( pCurrentFont->mbSubsettable )
    7260                 :            :         {
    7261         [ #  # ]:          0 :             FontSubset& rSubset = m_aSubsets[ pCurrentFont ];
    7262                 :            :             // search for font specific glyphID
    7263         [ #  # ]:          0 :             FontMapping::iterator it = rSubset.m_aMapping.find( nFontGlyphId );
    7264         [ #  # ]:          0 :             if( it != rSubset.m_aMapping.end() )
    7265                 :            :             {
    7266                 :          0 :                 pMappedFontObjects[i] = it->second.m_nFontID;
    7267                 :          0 :                 pMappedGlyphs[i] = it->second.m_nSubsetGlyphID;
    7268                 :            :             }
    7269                 :            :             else
    7270                 :            :             {
    7271                 :            :                 // create new subset if necessary
    7272   [ #  #  #  # ]:          0 :                 if( rSubset.m_aSubsets.empty()
                 [ #  # ]
    7273         [ #  # ]:          0 :                 || (rSubset.m_aSubsets.back().m_aMapping.size() > 254) )
    7274                 :            :                 {
    7275 [ #  # ][ #  # ]:          0 :                     rSubset.m_aSubsets.push_back( FontEmit( m_nNextFID++ ) );
    7276                 :            :                 }
    7277                 :            : 
    7278                 :            :                 // copy font id
    7279         [ #  # ]:          0 :                 pMappedFontObjects[i] = rSubset.m_aSubsets.back().m_nFontID;
    7280                 :            :                 // create new glyph in subset
    7281         [ #  # ]:          0 :                 sal_uInt8 nNewId = sal::static_int_cast<sal_uInt8>(rSubset.m_aSubsets.back().m_aMapping.size()+1);
    7282                 :          0 :                 pMappedGlyphs[i] = nNewId;
    7283                 :            : 
    7284                 :            :                 // add new glyph to emitted font subset
    7285 [ #  # ][ #  # ]:          0 :                 GlyphEmit& rNewGlyphEmit = rSubset.m_aSubsets.back().m_aMapping[ nFontGlyphId ];
    7286                 :          0 :                 rNewGlyphEmit.setGlyphId( nNewId );
    7287         [ #  # ]:          0 :                 for( sal_Int32 n = 0; n < pUnicodesPerGlyph[i]; n++ )
    7288         [ #  # ]:          0 :                     rNewGlyphEmit.addCode( pCurUnicode[n] );
    7289                 :            : 
    7290                 :            :                 // add new glyph to font mapping
    7291         [ #  # ]:          0 :                 Glyph& rNewGlyph = rSubset.m_aMapping[ nFontGlyphId ];
    7292                 :          0 :                 rNewGlyph.m_nFontID = pMappedFontObjects[i];
    7293                 :          0 :                 rNewGlyph.m_nSubsetGlyphID = nNewId;
    7294                 :            :             }
    7295 [ #  # ][ #  # ]:          0 :             getReferenceDevice()->ImplGetGraphics();
    7296                 :          0 :             const bool bVertical = ((pGlyphs[i] & GF_ROTMASK) != 0);
    7297                 :          0 :             pGlyphWidths[i] = m_aFontCache.getGlyphWidth( pCurrentFont,
    7298                 :            :                                                           nFontGlyphId,
    7299                 :            :                                                           bVertical,
    7300         [ #  # ]:          0 :                                                           m_pReferenceDevice->mpGraphics );
    7301                 :            :         }
    7302         [ #  # ]:          0 :         else if( pCurrentFont->IsEmbeddable() )
    7303                 :            :         {
    7304                 :          0 :             sal_Int32 nFontID = 0;
    7305         [ #  # ]:          0 :             FontEmbedData::iterator it = m_aEmbeddedFonts.find( pCurrentFont );
    7306         [ #  # ]:          0 :             if( it != m_aEmbeddedFonts.end() )
    7307                 :          0 :                 nFontID = it->second.m_nNormalFontID;
    7308                 :            :             else
    7309                 :            :             {
    7310                 :          0 :                 nFontID = m_nNextFID++;
    7311 [ #  # ][ #  # ]:          0 :                 m_aEmbeddedFonts[ pCurrentFont ] = EmbedFont();
                 [ #  # ]
    7312         [ #  # ]:          0 :                 m_aEmbeddedFonts[ pCurrentFont ].m_nNormalFontID = nFontID;
    7313                 :            :             }
    7314         [ #  # ]:          0 :             EmbedFont& rEmbedFont = m_aEmbeddedFonts[pCurrentFont];
    7315                 :            : 
    7316                 :          0 :             const Ucs2SIntMap* pEncoding = NULL;
    7317                 :          0 :             const Ucs2OStrMap* pNonEncoded = NULL;
    7318 [ #  # ][ #  # ]:          0 :             getReferenceDevice()->ImplGetGraphics();
    7319         [ #  # ]:          0 :             pEncoding = m_pReferenceDevice->mpGraphics->GetFontEncodingVector( pCurrentFont, &pNonEncoded );
    7320                 :            : 
    7321         [ #  # ]:          0 :             Ucs2SIntMap::const_iterator enc_it;
    7322                 :          0 :             Ucs2OStrMap::const_iterator nonenc_it;
    7323                 :            : 
    7324                 :          0 :             sal_Int32 nCurFontID = nFontID;
    7325                 :          0 :             sal_Ucs cChar = *pCurUnicode;
    7326         [ #  # ]:          0 :             if( pEncoding )
    7327                 :            :             {
    7328         [ #  # ]:          0 :                 enc_it = pEncoding->find( cChar );
    7329 [ #  # ][ #  # ]:          0 :                 if( enc_it != pEncoding->end() && enc_it->second > 0 )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    7330                 :            :                 {
    7331                 :            :                     DBG_ASSERT( (enc_it->second & 0xffffff00) == 0, "Invalid character code" );
    7332         [ #  # ]:          0 :                     cChar = (sal_Ucs)enc_it->second;
    7333                 :            :                 }
    7334 [ #  # ][ #  # ]:          0 :                 else if( (enc_it == pEncoding->end() || enc_it->second == -1) &&
         [ #  # ][ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    7335                 :            :                          pNonEncoded &&
    7336 [ #  # ][ #  # ]:          0 :                          (nonenc_it = pNonEncoded->find( cChar )) != pNonEncoded->end() )
                 [ #  # ]
    7337                 :            :                 {
    7338                 :          0 :                     nCurFontID = 0;
    7339                 :            :                     // find non encoded glyph
    7340         [ #  # ]:          0 :                     for( std::list< EmbedEncoding >::iterator nec_it = rEmbedFont.m_aExtendedEncodings.begin(); nec_it != rEmbedFont.m_aExtendedEncodings.end(); ++nec_it )
    7341                 :            :                     {
    7342 [ #  # ][ #  # ]:          0 :                         if( nec_it->m_aCMap.find( cChar ) != nec_it->m_aCMap.end() )
                 [ #  # ]
    7343                 :            :                         {
    7344                 :          0 :                             nCurFontID = nec_it->m_nFontID;
    7345         [ #  # ]:          0 :                             cChar = (sal_Ucs)nec_it->m_aCMap[ cChar ];
    7346                 :          0 :                             break;
    7347                 :            :                         }
    7348                 :            :                     }
    7349         [ #  # ]:          0 :                     if( nCurFontID == 0 ) // new nonencoded glyph
    7350                 :            :                     {
    7351 [ #  # ][ #  # ]:          0 :                         if( rEmbedFont.m_aExtendedEncodings.empty() || rEmbedFont.m_aExtendedEncodings.back().m_aEncVector.size() == 255 )
         [ #  # ][ #  # ]
    7352                 :            :                         {
    7353 [ #  # ][ #  # ]:          0 :                             rEmbedFont.m_aExtendedEncodings.push_back( EmbedEncoding() );
    7354         [ #  # ]:          0 :                             rEmbedFont.m_aExtendedEncodings.back().m_nFontID = m_nNextFID++;
    7355                 :            :                         }
    7356         [ #  # ]:          0 :                         EmbedEncoding& rEncoding = rEmbedFont.m_aExtendedEncodings.back();
    7357         [ #  # ]:          0 :                         rEncoding.m_aEncVector.push_back( EmbedCode() );
    7358         [ #  # ]:          0 :                         rEncoding.m_aEncVector.back().m_aUnicode = cChar;
    7359         [ #  # ]:          0 :                         rEncoding.m_aEncVector.back().m_aName = nonenc_it->second;
    7360         [ #  # ]:          0 :                         rEncoding.m_aCMap[ cChar ] = (sal_Int8)(rEncoding.m_aEncVector.size()-1);
    7361                 :          0 :                         nCurFontID = rEncoding.m_nFontID;
    7362         [ #  # ]:          0 :                         cChar = (sal_Ucs)rEncoding.m_aCMap[ cChar ];
    7363                 :            :                     }
    7364                 :            :                 }
    7365                 :            :                 else
    7366                 :          0 :                     pEncoding = NULL;
    7367                 :            :             }
    7368         [ #  # ]:          0 :             if( ! pEncoding )
    7369                 :            :             {
    7370         [ #  # ]:          0 :                 if( cChar & 0xff00 )
    7371                 :            :                 {
    7372                 :            :                     // some characters can be used by conversion
    7373 [ #  # ][ #  # ]:          0 :                     if( cChar >= 0xf000 && cChar <= 0xf0ff ) // symbol encoding in private use area
    7374                 :          0 :                         cChar -= 0xf000;
    7375                 :            :                     else
    7376                 :            :                     {
    7377         [ #  # ]:          0 :                         rtl::OString aChar(&cChar, 1, RTL_TEXTENCODING_MS_1252);
    7378                 :          0 :                         cChar = ((sal_Ucs)aChar[0]) & 0x00ff;
    7379                 :            :                     }
    7380                 :            :                 }
    7381                 :            :             }
    7382                 :            : 
    7383                 :          0 :             pMappedGlyphs[ i ] = (sal_Int8)cChar;
    7384                 :          0 :             pMappedFontObjects[ i ] = nCurFontID;
    7385                 :          0 :             pGlyphWidths[ i ] = m_aFontCache.getGlyphWidth( pCurrentFont,
    7386                 :            :                                                             (pEncoding ? *pCurUnicode : cChar) | GF_ISCHAR,
    7387                 :            :                                                             false,
    7388 [ #  # ][ #  # ]:          0 :                                                             m_pReferenceDevice->mpGraphics );
    7389                 :            :         }
    7390                 :            :     }
    7391                 :          0 : }
    7392                 :            : 
    7393                 :          0 : void PDFWriterImpl::drawRelief( SalLayout& rLayout, const String& rText, bool bTextLines )
    7394                 :            : {
    7395         [ #  # ]:          0 :     push( PUSH_ALL );
    7396                 :            : 
    7397         [ #  # ]:          0 :     FontRelief eRelief = m_aCurrentPDFState.m_aFont.GetRelief();
    7398                 :            : 
    7399         [ #  # ]:          0 :     Color aTextColor = m_aCurrentPDFState.m_aFont.GetColor();
    7400                 :          0 :     Color aTextLineColor = m_aCurrentPDFState.m_aTextLineColor;
    7401                 :          0 :     Color aOverlineColor = m_aCurrentPDFState.m_aOverlineColor;
    7402                 :          0 :     Color aReliefColor( COL_LIGHTGRAY );
    7403         [ #  # ]:          0 :     if( aTextColor == COL_BLACK )
    7404                 :          0 :         aTextColor = Color( COL_WHITE );
    7405         [ #  # ]:          0 :     if( aTextLineColor == COL_BLACK )
    7406                 :          0 :         aTextLineColor = Color( COL_WHITE );
    7407         [ #  # ]:          0 :     if( aOverlineColor == COL_BLACK )
    7408                 :          0 :         aOverlineColor = Color( COL_WHITE );
    7409         [ #  # ]:          0 :     if( aTextColor == COL_WHITE )
    7410                 :          0 :         aReliefColor = Color( COL_BLACK );
    7411                 :            : 
    7412         [ #  # ]:          0 :     Font aSetFont = m_aCurrentPDFState.m_aFont;
    7413         [ #  # ]:          0 :     aSetFont.SetRelief( RELIEF_NONE );
    7414         [ #  # ]:          0 :     aSetFont.SetShadow( sal_False );
    7415                 :            : 
    7416         [ #  # ]:          0 :     aSetFont.SetColor( aReliefColor );
    7417         [ #  # ]:          0 :     setTextLineColor( aReliefColor );
    7418         [ #  # ]:          0 :     setOverlineColor( aReliefColor );
    7419         [ #  # ]:          0 :     setFont( aSetFont );
    7420         [ #  # ]:          0 :     long nOff = 1 + getReferenceDevice()->mnDPIX/300;
    7421         [ #  # ]:          0 :     if( eRelief == RELIEF_ENGRAVED )
    7422                 :          0 :         nOff = -nOff;
    7423                 :            : 
    7424                 :          0 :     rLayout.DrawOffset() += Point( nOff, nOff );
    7425         [ #  # ]:          0 :     updateGraphicsState();
    7426         [ #  # ]:          0 :     drawLayout( rLayout, rText, bTextLines );
    7427                 :            : 
    7428                 :          0 :     rLayout.DrawOffset() -= Point( nOff, nOff );
    7429         [ #  # ]:          0 :     setTextLineColor( aTextLineColor );
    7430         [ #  # ]:          0 :     setOverlineColor( aOverlineColor );
    7431         [ #  # ]:          0 :     aSetFont.SetColor( aTextColor );
    7432         [ #  # ]:          0 :     setFont( aSetFont );
    7433         [ #  # ]:          0 :     updateGraphicsState();
    7434         [ #  # ]:          0 :     drawLayout( rLayout, rText, bTextLines );
    7435                 :            : 
    7436                 :            :     // clean up the mess
    7437 [ #  # ][ #  # ]:          0 :     pop();
    7438                 :          0 : }
    7439                 :            : 
    7440                 :          0 : void PDFWriterImpl::drawShadow( SalLayout& rLayout, const String& rText, bool bTextLines )
    7441                 :            : {
    7442         [ #  # ]:          0 :     Font aSaveFont = m_aCurrentPDFState.m_aFont;
    7443                 :          0 :     Color aSaveTextLineColor = m_aCurrentPDFState.m_aTextLineColor;
    7444                 :          0 :     Color aSaveOverlineColor = m_aCurrentPDFState.m_aOverlineColor;
    7445                 :            : 
    7446                 :          0 :     Font& rFont = m_aCurrentPDFState.m_aFont;
    7447 [ #  # ][ #  # ]:          0 :     if( rFont.GetColor() == Color( COL_BLACK ) || rFont.GetColor().GetLuminance() < 8 )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    7448         [ #  # ]:          0 :         rFont.SetColor( Color( COL_LIGHTGRAY ) );
    7449                 :            :     else
    7450         [ #  # ]:          0 :         rFont.SetColor( Color( COL_BLACK ) );
    7451         [ #  # ]:          0 :     rFont.SetShadow( sal_False );
    7452         [ #  # ]:          0 :     rFont.SetOutline( sal_False );
    7453         [ #  # ]:          0 :     setFont( rFont );
    7454 [ #  # ][ #  # ]:          0 :     setTextLineColor( rFont.GetColor() );
    7455 [ #  # ][ #  # ]:          0 :     setOverlineColor( rFont.GetColor() );
    7456         [ #  # ]:          0 :     updateGraphicsState();
    7457                 :            : 
    7458                 :          0 :     long nOff = 1 + ((m_pReferenceDevice->mpFontEntry->mnLineHeight-24)/24);
    7459 [ #  # ][ #  # ]:          0 :     if( rFont.IsOutline() )
    7460                 :          0 :         nOff++;
    7461                 :          0 :     rLayout.DrawBase() += Point( nOff, nOff );
    7462         [ #  # ]:          0 :     drawLayout( rLayout, rText, bTextLines );
    7463                 :          0 :     rLayout.DrawBase() -= Point( nOff, nOff );
    7464                 :            : 
    7465         [ #  # ]:          0 :     setFont( aSaveFont );
    7466         [ #  # ]:          0 :     setTextLineColor( aSaveTextLineColor );
    7467         [ #  # ]:          0 :     setOverlineColor( aSaveOverlineColor );
    7468 [ #  # ][ #  # ]:          0 :     updateGraphicsState();
    7469                 :          0 : }
    7470                 :            : 
    7471                 :          0 : void PDFWriterImpl::drawVerticalGlyphs(
    7472                 :            :         const std::vector<PDFWriterImpl::PDFGlyph>& rGlyphs,
    7473                 :            :         OStringBuffer& rLine,
    7474                 :            :         const Point& rAlignOffset,
    7475                 :            :         const Matrix3& rRotScale,
    7476                 :            :         double fAngle,
    7477                 :            :         double fXScale,
    7478                 :            :         double fSkew,
    7479                 :            :         sal_Int32 nFontHeight )
    7480                 :            : {
    7481                 :          0 :     long nXOffset = 0;
    7482                 :          0 :     Point aCurPos( rGlyphs[0].m_aPos );
    7483         [ #  # ]:          0 :     aCurPos = m_pReferenceDevice->PixelToLogic( aCurPos );
    7484                 :          0 :     aCurPos += rAlignOffset;
    7485         [ #  # ]:          0 :     for( size_t i = 0; i < rGlyphs.size(); i++ )
    7486                 :            :     {
    7487                 :            :         // have to emit each glyph on its own
    7488                 :          0 :         double fDeltaAngle = 0.0;
    7489                 :          0 :         double fYScale = 1.0;
    7490                 :          0 :         double fTempXScale = fXScale;
    7491                 :          0 :         double fSkewB = fSkew;
    7492                 :          0 :         double fSkewA = 0.0;
    7493                 :            : 
    7494                 :          0 :         Point aDeltaPos;
    7495         [ #  # ]:          0 :         if( ( rGlyphs[i].m_nGlyphId & GF_ROTMASK ) == GF_ROTL )
    7496                 :            :         {
    7497                 :          0 :             fDeltaAngle = M_PI/2.0;
    7498 [ #  # ][ #  # ]:          0 :             aDeltaPos.X() = m_pReferenceDevice->GetFontMetric().GetAscent();
                 [ #  # ]
    7499 [ #  # ][ #  # ]:          0 :             aDeltaPos.Y() = (int)((double)m_pReferenceDevice->GetFontMetric().GetDescent() * fXScale);
                 [ #  # ]
    7500                 :          0 :             fYScale = fXScale;
    7501                 :          0 :             fTempXScale = 1.0;
    7502                 :          0 :             fSkewA = -fSkewB;
    7503                 :          0 :             fSkewB = 0.0;
    7504                 :            :         }
    7505         [ #  # ]:          0 :         else if( ( rGlyphs[i].m_nGlyphId & GF_ROTMASK ) == GF_ROTR )
    7506                 :            :         {
    7507                 :          0 :             fDeltaAngle = -M_PI/2.0;
    7508 [ #  # ][ #  # ]:          0 :             aDeltaPos.X() = (int)((double)m_pReferenceDevice->GetFontMetric().GetDescent()*fXScale);
                 [ #  # ]
    7509 [ #  # ][ #  # ]:          0 :             aDeltaPos.Y() = -m_pReferenceDevice->GetFontMetric().GetAscent();
                 [ #  # ]
    7510                 :          0 :             fYScale = fXScale;
    7511                 :          0 :             fTempXScale = 1.0;
    7512                 :          0 :             fSkewA = fSkewB;
    7513                 :          0 :             fSkewB = 0.0;
    7514                 :            :         }
    7515 [ #  # ][ #  # ]:          0 :         aDeltaPos += (m_pReferenceDevice->PixelToLogic( Point( (int)((double)nXOffset/fXScale), 0 ) ) - m_pReferenceDevice->PixelToLogic( Point() ) );
    7516         [ #  # ]:          0 :         if( i < rGlyphs.size()-1 )
    7517                 :          0 :             nXOffset += rGlyphs[i+1].m_aPos.Y() - rGlyphs[i].m_aPos.Y();
    7518         [ #  # ]:          0 :         if( ! rGlyphs[i].m_nGlyphId )
    7519                 :          0 :             continue;
    7520                 :            : 
    7521                 :          0 :         aDeltaPos = rRotScale.transform( aDeltaPos );
    7522                 :            : 
    7523                 :          0 :         Matrix3 aMat;
    7524 [ #  # ][ #  # ]:          0 :         if( fSkewB != 0.0 || fSkewA != 0.0 )
    7525                 :          0 :             aMat.skew( fSkewA, fSkewB );
    7526                 :          0 :         aMat.scale( fTempXScale, fYScale );
    7527                 :          0 :         aMat.rotate( fAngle+fDeltaAngle );
    7528                 :          0 :         aMat.translate( aCurPos.X()+aDeltaPos.X(), aCurPos.Y()+aDeltaPos.Y() );
    7529 [ #  # ][ #  # ]:          0 :         aMat.append( m_aPages.back(), rLine );
    7530         [ #  # ]:          0 :         rLine.append( " Tm" );
    7531 [ #  # ][ #  # ]:          0 :         if( i == 0 || rGlyphs[i-1].m_nMappedFontId != rGlyphs[i].m_nMappedFontId )
                 [ #  # ]
    7532                 :            :         {
    7533         [ #  # ]:          0 :             rLine.append( " /F" );
    7534         [ #  # ]:          0 :             rLine.append( rGlyphs[i].m_nMappedFontId );
    7535         [ #  # ]:          0 :             rLine.append( ' ' );
    7536 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendMappedLength( nFontHeight, rLine, true );
    7537         [ #  # ]:          0 :             rLine.append( " Tf" );
    7538                 :            :         }
    7539         [ #  # ]:          0 :         rLine.append( "<" );
    7540         [ #  # ]:          0 :         appendHex( rGlyphs[i].m_nMappedGlyphId, rLine );
    7541         [ #  # ]:          0 :         rLine.append( ">Tj\n" );
    7542                 :          0 :     }
    7543                 :          0 : }
    7544                 :            : 
    7545                 :          0 : void PDFWriterImpl::drawHorizontalGlyphs(
    7546                 :            :         const std::vector<PDFWriterImpl::PDFGlyph>& rGlyphs,
    7547                 :            :         OStringBuffer& rLine,
    7548                 :            :         const Point& rAlignOffset,
    7549                 :            :         double fAngle,
    7550                 :            :         double fXScale,
    7551                 :            :         double fSkew,
    7552                 :            :         sal_Int32 nFontHeight,
    7553                 :            :         sal_Int32 nPixelFontHeight
    7554                 :            :         )
    7555                 :            : {
    7556                 :            :     // horizontal (= normal) case
    7557                 :            : 
    7558                 :            :     // fill in  run end indices
    7559                 :            :     // end is marked by index of the first glyph of the next run
    7560                 :            :     // a run is marked by same mapped font id and same Y position
    7561         [ #  # ]:          0 :     std::vector< sal_uInt32 > aRunEnds;
    7562         [ #  # ]:          0 :     aRunEnds.reserve( rGlyphs.size() );
    7563         [ #  # ]:          0 :     for( size_t i = 1; i < rGlyphs.size(); i++ )
    7564                 :            :     {
    7565   [ #  #  #  # ]:          0 :         if( rGlyphs[i].m_nMappedFontId != rGlyphs[i-1].m_nMappedFontId ||
                 [ #  # ]
    7566                 :          0 :             rGlyphs[i].m_aPos.Y() != rGlyphs[i-1].m_aPos.Y() )
    7567                 :            :         {
    7568         [ #  # ]:          0 :             aRunEnds.push_back(i);
    7569                 :            :         }
    7570                 :            :     }
    7571                 :            :     // last run ends at last glyph
    7572         [ #  # ]:          0 :     aRunEnds.push_back( rGlyphs.size() );
    7573                 :            : 
    7574                 :            :     // loop over runs of the same font
    7575                 :          0 :     sal_uInt32 nBeginRun = 0;
    7576         [ #  # ]:          0 :     for( size_t nRun = 0; nRun < aRunEnds.size(); nRun++ )
    7577                 :            :     {
    7578                 :            :         // setup text matrix
    7579                 :          0 :         Point aCurPos = rGlyphs[nBeginRun].m_aPos;
    7580                 :            :         // back transformation to current coordinate system
    7581         [ #  # ]:          0 :         aCurPos = m_pReferenceDevice->PixelToLogic( aCurPos );
    7582                 :          0 :         aCurPos += rAlignOffset;
    7583                 :            :         // the first run can be set with "Td" operator
    7584                 :            :         // subsequent use of that operator would move
    7585                 :            :         // the texline matrix relative to what was set before
    7586                 :            :         // making use of that would drive us into rounding issues
    7587                 :          0 :         Matrix3 aMat;
    7588 [ #  # ][ #  # ]:          0 :         if( nRun == 0 && fAngle == 0.0 && fXScale == 1.0 && fSkew == 0.0 )
         [ #  # ][ #  # ]
    7589                 :            :         {
    7590 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendPoint( aCurPos, rLine, false );
    7591         [ #  # ]:          0 :             rLine.append( " Td " );
    7592                 :            :         }
    7593                 :            :         else
    7594                 :            :         {
    7595         [ #  # ]:          0 :             if( fSkew != 0.0 )
    7596                 :          0 :                 aMat.skew( 0.0, fSkew );
    7597                 :          0 :             aMat.scale( fXScale, 1.0 );
    7598                 :          0 :             aMat.rotate( fAngle );
    7599                 :          0 :             aMat.translate( aCurPos.X(), aCurPos.Y() );
    7600 [ #  # ][ #  # ]:          0 :             aMat.append( m_aPages.back(), rLine );
    7601         [ #  # ]:          0 :             rLine.append( " Tm\n" );
    7602                 :            :         }
    7603                 :            :         // set up correct font
    7604         [ #  # ]:          0 :         rLine.append( "/F" );
    7605         [ #  # ]:          0 :         rLine.append( rGlyphs[nBeginRun].m_nMappedFontId );
    7606         [ #  # ]:          0 :         rLine.append( ' ' );
    7607 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendMappedLength( nFontHeight, rLine, true );
    7608         [ #  # ]:          0 :         rLine.append( " Tf" );
    7609                 :            : 
    7610                 :            :         // output glyphs using Tj or TJ
    7611                 :          0 :         OStringBuffer aKernedLine( 256 ), aUnkernedLine( 256 );
    7612         [ #  # ]:          0 :         aKernedLine.append( "[<" );
    7613         [ #  # ]:          0 :         aUnkernedLine.append( '<' );
    7614         [ #  # ]:          0 :         appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aKernedLine );
    7615         [ #  # ]:          0 :         appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aUnkernedLine );
    7616                 :            : 
    7617                 :          0 :         aMat.invert();
    7618                 :          0 :         bool bNeedKern = false;
    7619 [ #  # ][ #  # ]:          0 :         for( sal_uInt32 nPos = nBeginRun+1; nPos < aRunEnds[nRun]; nPos++ )
    7620                 :            :         {
    7621         [ #  # ]:          0 :             appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine );
    7622                 :            :             // check if default glyph positioning is sufficient
    7623                 :          0 :             const Point aThisPos = aMat.transform( rGlyphs[nPos].m_aPos );
    7624                 :          0 :             const Point aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos );
    7625                 :          0 :             double fAdvance = aThisPos.X() - aPrevPos.X();
    7626                 :          0 :             fAdvance *= 1000.0 / nPixelFontHeight;
    7627                 :          0 :             const sal_Int32 nAdjustment = (sal_Int32)(rGlyphs[nPos-1].m_nNativeWidth - fAdvance + 0.5);
    7628         [ #  # ]:          0 :             if( nAdjustment != 0 )
    7629                 :            :             {
    7630                 :            :                 // apply individual glyph positioning
    7631                 :          0 :                 bNeedKern = true;
    7632         [ #  # ]:          0 :                 aKernedLine.append( ">" );
    7633         [ #  # ]:          0 :                 aKernedLine.append( nAdjustment );
    7634         [ #  # ]:          0 :                 aKernedLine.append( "<" );
    7635                 :            :             }
    7636         [ #  # ]:          0 :             appendHex( rGlyphs[nPos].m_nMappedGlyphId, aKernedLine );
    7637                 :            :         }
    7638         [ #  # ]:          0 :         aKernedLine.append( ">]TJ\n" );
    7639         [ #  # ]:          0 :         aUnkernedLine.append( ">Tj\n" );
    7640                 :            :         rLine.append(
    7641 [ #  # ][ #  # ]:          0 :             (bNeedKern ? aKernedLine : aUnkernedLine).makeStringAndClear() );
    7642                 :            : 
    7643                 :            :         // set beginning of next run
    7644         [ #  # ]:          0 :         nBeginRun = aRunEnds[nRun];
    7645                 :          0 :     }
    7646                 :          0 : }
    7647                 :            : 
    7648                 :          0 : void PDFWriterImpl::drawLayout( SalLayout& rLayout, const String& rText, bool bTextLines )
    7649                 :            : {
    7650                 :            :     // relief takes precedence over shadow (see outdev3.cxx)
    7651 [ #  # ][ #  # ]:          0 :     if(  m_aCurrentPDFState.m_aFont.GetRelief() != RELIEF_NONE )
    7652                 :            :     {
    7653         [ #  # ]:          0 :         drawRelief( rLayout, rText, bTextLines );
    7654                 :          0 :         return;
    7655                 :            :     }
    7656 [ #  # ][ #  # ]:          0 :     else if( m_aCurrentPDFState.m_aFont.IsShadow() )
    7657         [ #  # ]:          0 :         drawShadow( rLayout, rText, bTextLines );
    7658                 :            : 
    7659                 :          0 :     OStringBuffer aLine( 512 );
    7660                 :            : 
    7661                 :          0 :     const int nMaxGlyphs = 256;
    7662                 :            : 
    7663                 :            :     sal_GlyphId pGlyphs[nMaxGlyphs];
    7664                 :            :     sal_Int32 pGlyphWidths[nMaxGlyphs];
    7665                 :            :     sal_uInt8 pMappedGlyphs[nMaxGlyphs];
    7666                 :            :     sal_Int32 pMappedFontObjects[nMaxGlyphs];
    7667         [ #  # ]:          0 :     std::vector<sal_Ucs> aUnicodes;
    7668         [ #  # ]:          0 :     aUnicodes.reserve( nMaxGlyphs );
    7669                 :            :     sal_Int32 pUnicodesPerGlyph[nMaxGlyphs];
    7670                 :            :     int pCharPosAry[nMaxGlyphs];
    7671                 :            :     sal_Int32 nAdvanceWidths[nMaxGlyphs];
    7672                 :            :     const PhysicalFontFace* pFallbackFonts[nMaxGlyphs];
    7673         [ #  # ]:          0 :     bool bVertical = m_aCurrentPDFState.m_aFont.IsVertical();
    7674                 :            :     int nGlyphs;
    7675                 :          0 :     int nIndex = 0;
    7676                 :          0 :     int nMinCharPos = 0, nMaxCharPos = rText.Len()-1;
    7677                 :          0 :     double fXScale = 1.0;
    7678                 :          0 :     double fSkew = 0.0;
    7679                 :          0 :     sal_Int32 nPixelFontHeight = m_pReferenceDevice->mpFontEntry->maFontSelData.mnHeight;
    7680         [ #  # ]:          0 :     TextAlign eAlign = m_aCurrentPDFState.m_aFont.GetAlign();
    7681                 :            : 
    7682                 :            :     // transform font height back to current units
    7683                 :            :     // note: the layout calculates in outdevs device pixel !!
    7684         [ #  # ]:          0 :     sal_Int32 nFontHeight = m_pReferenceDevice->ImplDevicePixelToLogicHeight( nPixelFontHeight );
    7685 [ #  # ][ #  # ]:          0 :     if( m_aCurrentPDFState.m_aFont.GetWidth() )
    7686                 :            :     {
    7687         [ #  # ]:          0 :         Font aFont( m_aCurrentPDFState.m_aFont );
    7688         [ #  # ]:          0 :         aFont.SetWidth( 0 );
    7689         [ #  # ]:          0 :         FontMetric aMetric = m_pReferenceDevice->GetFontMetric( aFont );
    7690 [ #  # ][ #  # ]:          0 :         if( aMetric.GetWidth() != m_aCurrentPDFState.m_aFont.GetWidth() )
                 [ #  # ]
    7691                 :            :         {
    7692                 :            :             fXScale =
    7693         [ #  # ]:          0 :                 (double)m_aCurrentPDFState.m_aFont.GetWidth() /
    7694         [ #  # ]:          0 :                 (double)aMetric.GetWidth();
    7695                 :            :         }
    7696                 :            :         // force state before GetFontMetric
    7697 [ #  # ][ #  # ]:          0 :         m_pReferenceDevice->ImplNewFont();
                 [ #  # ]
    7698                 :            :     }
    7699                 :            : 
    7700                 :            :     // perform artificial italics if necessary
    7701 [ #  # ][ #  # ]:          0 :     if( ( m_aCurrentPDFState.m_aFont.GetItalic() == ITALIC_NORMAL ||
           [ #  #  #  # ]
                 [ #  # ]
    7702         [ #  # ]:          0 :           m_aCurrentPDFState.m_aFont.GetItalic() == ITALIC_OBLIQUE ) &&
    7703                 :          0 :         !( m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData->GetSlant() == ITALIC_NORMAL ||
    7704         [ #  # ]:          0 :            m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData->GetSlant() == ITALIC_OBLIQUE )
    7705                 :            :         )
    7706                 :            :     {
    7707                 :          0 :         fSkew = M_PI/12.0;
    7708                 :            :     }
    7709                 :            : 
    7710                 :            :     // if the mapmode is distorted we need to adjust for that also
    7711 [ #  # ][ #  # ]:          0 :     if( m_aCurrentPDFState.m_aMapMode.GetScaleX() != m_aCurrentPDFState.m_aMapMode.GetScaleY() )
    7712                 :            :     {
    7713 [ #  # ][ #  # ]:          0 :         fXScale *= double(m_aCurrentPDFState.m_aMapMode.GetScaleX()) / double(m_aCurrentPDFState.m_aMapMode.GetScaleY());
    7714                 :            :     }
    7715                 :            : 
    7716         [ #  # ]:          0 :     int nAngle = m_aCurrentPDFState.m_aFont.GetOrientation();
    7717                 :            :     // normalize angles
    7718         [ #  # ]:          0 :     while( nAngle < 0 )
    7719                 :          0 :         nAngle += 3600;
    7720                 :          0 :     nAngle = nAngle % 3600;
    7721                 :          0 :     double fAngle = (double)nAngle * M_PI / 1800.0;
    7722                 :            : 
    7723                 :          0 :     Matrix3 aRotScale;
    7724                 :          0 :     aRotScale.scale( fXScale, 1.0 );
    7725         [ #  # ]:          0 :     if( fAngle != 0.0 )
    7726                 :          0 :         aRotScale.rotate( -fAngle );
    7727                 :            : 
    7728                 :          0 :     bool bPop = false;
    7729                 :          0 :     bool bABold = false;
    7730                 :            :     // artificial bold necessary ?
    7731   [ #  #  #  # ]:          0 :     if( m_pReferenceDevice->mpFontEntry->maFontSelData.mpFontData->GetWeight() <= WEIGHT_MEDIUM &&
                 [ #  # ]
    7732                 :          0 :         m_pReferenceDevice->mpFontEntry->maFontSelData.GetWeight() > WEIGHT_MEDIUM )
    7733                 :            :     {
    7734         [ #  # ]:          0 :         if( ! bPop )
    7735         [ #  # ]:          0 :             aLine.append( "q " );
    7736                 :          0 :         bPop = true;
    7737                 :          0 :         bABold = true;
    7738                 :            :     }
    7739                 :            :     // setup text colors (if necessary)
    7740                 :          0 :     Color aStrokeColor( COL_TRANSPARENT );
    7741                 :          0 :     Color aNonStrokeColor( COL_TRANSPARENT );
    7742                 :            : 
    7743 [ #  # ][ #  # ]:          0 :     if( m_aCurrentPDFState.m_aFont.IsOutline() )
    7744                 :            :     {
    7745         [ #  # ]:          0 :         aStrokeColor = m_aCurrentPDFState.m_aFont.GetColor();
    7746                 :          0 :         aNonStrokeColor = Color( COL_WHITE );
    7747                 :            :     }
    7748                 :            :     else
    7749         [ #  # ]:          0 :         aNonStrokeColor = m_aCurrentPDFState.m_aFont.GetColor();
    7750         [ #  # ]:          0 :     if( bABold )
    7751         [ #  # ]:          0 :         aStrokeColor = m_aCurrentPDFState.m_aFont.GetColor();
    7752                 :            : 
    7753 [ #  # ][ #  # ]:          0 :     if( aStrokeColor != Color( COL_TRANSPARENT ) && aStrokeColor != m_aCurrentPDFState.m_aLineColor )
         [ #  # ][ #  # ]
    7754                 :            :     {
    7755         [ #  # ]:          0 :         if( ! bPop )
    7756         [ #  # ]:          0 :             aLine.append( "q " );
    7757                 :          0 :         bPop = true;
    7758         [ #  # ]:          0 :         appendStrokingColor( aStrokeColor, aLine );
    7759         [ #  # ]:          0 :         aLine.append( "\n" );
    7760                 :            :     }
    7761 [ #  # ][ #  # ]:          0 :     if( aNonStrokeColor != Color( COL_TRANSPARENT ) && aNonStrokeColor != m_aCurrentPDFState.m_aFillColor )
         [ #  # ][ #  # ]
    7762                 :            :     {
    7763         [ #  # ]:          0 :         if( ! bPop )
    7764         [ #  # ]:          0 :             aLine.append( "q " );
    7765                 :          0 :         bPop = true;
    7766         [ #  # ]:          0 :         appendNonStrokingColor( aNonStrokeColor, aLine );
    7767         [ #  # ]:          0 :         aLine.append( "\n" );
    7768                 :            :     }
    7769                 :            : 
    7770                 :            :     // begin text object
    7771         [ #  # ]:          0 :     aLine.append( "BT\n" );
    7772                 :            :     // outline attribute ?
    7773 [ #  # ][ #  # ]:          0 :     if( m_aCurrentPDFState.m_aFont.IsOutline() || bABold )
         [ #  # ][ #  # ]
    7774                 :            :     {
    7775                 :            :         // set correct text mode, set stroke width
    7776         [ #  # ]:          0 :         aLine.append( "2 Tr " ); // fill, then stroke
    7777                 :            : 
    7778 [ #  # ][ #  # ]:          0 :         if( m_aCurrentPDFState.m_aFont.IsOutline() )
    7779                 :            :         {
    7780                 :            :             // unclear what to do in case of outline and artificial bold
    7781                 :            :             // for the time being outline wins
    7782         [ #  # ]:          0 :             aLine.append( "0.25 w \n" );
    7783                 :            :         }
    7784                 :            :         else
    7785                 :            :         {
    7786         [ #  # ]:          0 :             double fW = (double)m_aCurrentPDFState.m_aFont.GetHeight() / 30.0;
    7787 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendMappedLength( fW, aLine );
    7788         [ #  # ]:          0 :             aLine.append ( " w\n" );
    7789                 :            :         }
    7790                 :            :     }
    7791                 :            : 
    7792         [ #  # ]:          0 :     FontMetric aRefDevFontMetric = m_pReferenceDevice->GetFontMetric();
    7793                 :            : 
    7794                 :            :     // collect the glyphs into a single array
    7795         [ #  # ]:          0 :     const int nTmpMaxGlyphs = rLayout.GetOrientation() ? 1 : nMaxGlyphs; // #i97991# temporary workaround for #i87686#
    7796         [ #  # ]:          0 :     std::vector< PDFGlyph > aGlyphs;
    7797         [ #  # ]:          0 :     aGlyphs.reserve( nTmpMaxGlyphs );
    7798                 :            :     // first get all the glyphs and register them; coordinates still in Pixel
    7799                 :          0 :     Point aGNGlyphPos;
    7800 [ #  # ][ #  # ]:          0 :     while( (nGlyphs = rLayout.GetNextGlyphs( nTmpMaxGlyphs, pGlyphs, aGNGlyphPos, nIndex, nAdvanceWidths, pCharPosAry )) != 0 )
    7801                 :            :     {
    7802                 :          0 :         aUnicodes.clear();
    7803         [ #  # ]:          0 :         for( int i = 0; i < nGlyphs; i++ )
    7804                 :            :         {
    7805         [ #  # ]:          0 :             pFallbackFonts[i] = rLayout.GetFallbackFontData( pGlyphs[i] );
    7806                 :            : 
    7807                 :            :             // default case: 1 glyph is one unicode
    7808                 :          0 :             pUnicodesPerGlyph[i] = 1;
    7809         [ #  # ]:          0 :             if( (pGlyphs[i] & GF_ISCHAR) )
    7810                 :            :             {
    7811         [ #  # ]:          0 :                 aUnicodes.push_back( static_cast<sal_Ucs>(pGlyphs[i] & GF_IDXMASK) );
    7812                 :            :             }
    7813 [ #  # ][ #  # ]:          0 :             else if( pCharPosAry[i] >= nMinCharPos && pCharPosAry[i] <= nMaxCharPos )
    7814                 :            :             {
    7815                 :          0 :                 int nChars = 1;
    7816         [ #  # ]:          0 :                 aUnicodes.push_back( rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]) ) );
    7817                 :          0 :                 pUnicodesPerGlyph[i] = 1;
    7818                 :            :                 // try to handle ligatures and such
    7819         [ #  # ]:          0 :                 if( i < nGlyphs-1 )
    7820                 :            :                 {
    7821                 :          0 :                     nChars = pCharPosAry[i+1] - pCharPosAry[i];
    7822                 :            :                     // #i115618# fix for simple RTL+CTL cases
    7823                 :            :                     // TODO: sanitize for RTL ligatures, more complex CTL, etc.
    7824         [ #  # ]:          0 :                     if( nChars < 0 )
    7825                 :          0 :                         nChars = -nChars;
    7826         [ #  # ]:          0 :             else if( nChars == 0 )
    7827                 :          0 :                         nChars = 1;
    7828                 :          0 :                     pUnicodesPerGlyph[i] = nChars;
    7829         [ #  # ]:          0 :                     for( int n = 1; n < nChars; n++ )
    7830         [ #  # ]:          0 :                         aUnicodes.push_back( rText.GetChar( sal::static_int_cast<xub_StrLen>(pCharPosAry[i]+n) ) );
    7831                 :            :                 }
    7832                 :            :                 // #i36691# hack that is needed because currently the pGlyphs[]
    7833                 :            :                 // argument is ignored for embeddable fonts and so the layout
    7834                 :            :                 // engine's glyph work is ignored (i.e. char mirroring)
    7835                 :            :                 // TODO: a real solution would be to map the layout engine's
    7836                 :            :                 // glyphid (i.e. FreeType's synthetic glyphid for a Type1 font)
    7837                 :            :                 // back to unicode and then to embeddable font's encoding
    7838 [ #  # ][ #  # ]:          0 :                 if( getReferenceDevice()->GetLayoutMode() & TEXT_LAYOUT_BIDI_RTL )
    7839                 :            :                 {
    7840                 :          0 :                     size_t nI = aUnicodes.size()-1;
    7841         [ #  # ]:          0 :                     for( int n = 0; n < nChars; n++, nI-- )
    7842 [ #  # ][ #  # ]:          0 :                         aUnicodes[nI] = static_cast<sal_Ucs>(GetMirroredChar(aUnicodes[nI]));
                 [ #  # ]
    7843                 :          0 :                 }
    7844                 :            :             }
    7845                 :            :             else
    7846         [ #  # ]:          0 :                 aUnicodes.push_back( 0 );
    7847                 :            :             // note: in case of ctl one character may result
    7848                 :            :             // in multiple glyphs. The current SalLayout
    7849                 :            :             // implementations set -1 then to indicate that no direct
    7850                 :            :             // mapping is possible
    7851                 :            :         }
    7852                 :            : 
    7853 [ #  # ][ #  # ]:          0 :         registerGlyphs( nGlyphs, pGlyphs, pGlyphWidths, &aUnicodes[0], pUnicodesPerGlyph, pMappedGlyphs, pMappedFontObjects, pFallbackFonts );
    7854                 :            : 
    7855         [ #  # ]:          0 :         for( int i = 0; i < nGlyphs; i++ )
    7856                 :            :         {
    7857                 :            :             aGlyphs.push_back( PDFGlyph( aGNGlyphPos,
    7858                 :            :                                          pGlyphWidths[i],
    7859                 :          0 :                                          pGlyphs[i],
    7860                 :            :                                          pMappedFontObjects[i],
    7861         [ #  # ]:          0 :                                          pMappedGlyphs[i] ) );
    7862         [ #  # ]:          0 :             if( bVertical )
    7863                 :          0 :                 aGNGlyphPos.Y() += nAdvanceWidths[i]/rLayout.GetUnitsPerPixel();
    7864                 :            :             else
    7865                 :          0 :                 aGNGlyphPos.X() += nAdvanceWidths[i]/rLayout.GetUnitsPerPixel();
    7866                 :            :         }
    7867                 :            :     }
    7868                 :            : 
    7869                 :          0 :     Point aAlignOffset;
    7870         [ #  # ]:          0 :     if ( eAlign == ALIGN_BOTTOM )
    7871         [ #  # ]:          0 :         aAlignOffset.Y() -= aRefDevFontMetric.GetDescent();
    7872         [ #  # ]:          0 :     else if ( eAlign == ALIGN_TOP )
    7873         [ #  # ]:          0 :         aAlignOffset.Y() += aRefDevFontMetric.GetAscent();
    7874 [ #  # ][ #  # ]:          0 :     if( aAlignOffset.X() || aAlignOffset.Y() )
                 [ #  # ]
    7875                 :          0 :         aAlignOffset = aRotScale.transform( aAlignOffset );
    7876                 :            : 
    7877                 :            :     /* #159153# do not emit an empty glyph vector; this can happen if e.g. the original
    7878                 :            :        string contained only on of the UTF16 BOMs
    7879                 :            :     */
    7880         [ #  # ]:          0 :     if( ! aGlyphs.empty() )
    7881                 :            :     {
    7882         [ #  # ]:          0 :         if( bVertical )
    7883         [ #  # ]:          0 :             drawVerticalGlyphs( aGlyphs, aLine, aAlignOffset, aRotScale, fAngle, fXScale, fSkew, nFontHeight );
    7884                 :            :         else
    7885         [ #  # ]:          0 :             drawHorizontalGlyphs( aGlyphs, aLine, aAlignOffset, fAngle, fXScale, fSkew, nFontHeight, nPixelFontHeight );
    7886                 :            :     }
    7887                 :            : 
    7888                 :            :     // end textobject
    7889         [ #  # ]:          0 :     aLine.append( "ET\n" );
    7890         [ #  # ]:          0 :     if( bPop )
    7891         [ #  # ]:          0 :         aLine.append( "Q\n" );
    7892                 :            : 
    7893         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    7894                 :            : 
    7895                 :            :     // draw eventual textlines
    7896         [ #  # ]:          0 :     FontStrikeout eStrikeout = m_aCurrentPDFState.m_aFont.GetStrikeout();
    7897         [ #  # ]:          0 :     FontUnderline eUnderline = m_aCurrentPDFState.m_aFont.GetUnderline();
    7898         [ #  # ]:          0 :     FontUnderline eOverline  = m_aCurrentPDFState.m_aFont.GetOverline();
    7899 [ #  # ][ #  # ]:          0 :     if( bTextLines &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    7900                 :            :         (
    7901                 :            :          ( eUnderline != UNDERLINE_NONE && eUnderline != UNDERLINE_DONTKNOW ) ||
    7902                 :            :          ( eOverline  != UNDERLINE_NONE && eOverline  != UNDERLINE_DONTKNOW ) ||
    7903                 :            :          ( eStrikeout != STRIKEOUT_NONE && eStrikeout != STRIKEOUT_DONTKNOW )
    7904                 :            :          )
    7905                 :            :         )
    7906                 :            :     {
    7907         [ #  # ]:          0 :         sal_Bool bUnderlineAbove = OutputDevice::ImplIsUnderlineAbove( m_aCurrentPDFState.m_aFont );
    7908 [ #  # ][ #  # ]:          0 :         if( m_aCurrentPDFState.m_aFont.IsWordLineMode() )
    7909                 :            :         {
    7910                 :          0 :             Point aPos, aStartPt;
    7911                 :          0 :             sal_Int32 nWidth = 0, nAdvance=0;
    7912                 :          0 :             for( int nStart = 0;;)
    7913                 :            :             {
    7914                 :            :                 sal_GlyphId nGlyphIndex;
    7915 [ #  # ][ #  # ]:          0 :                 if( !rLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart, &nAdvance ) )
    7916                 :            :                     break;
    7917                 :            : 
    7918 [ #  # ][ #  # ]:          0 :                 if( !rLayout.IsSpacingGlyph( nGlyphIndex ) )
    7919                 :            :                 {
    7920         [ #  # ]:          0 :                     if( !nWidth )
    7921                 :          0 :                         aStartPt = aPos;
    7922                 :            : 
    7923                 :          0 :                     nWidth += nAdvance;
    7924                 :            :                 }
    7925         [ #  # ]:          0 :                 else if( nWidth > 0 )
    7926                 :            :                 {
    7927                 :          0 :                     drawTextLine( m_pReferenceDevice->PixelToLogic( aStartPt ),
    7928                 :            :                                   m_pReferenceDevice->ImplDevicePixelToLogicWidth( nWidth ),
    7929 [ #  # ][ #  # ]:          0 :                                   eStrikeout, eUnderline, eOverline, bUnderlineAbove );
                 [ #  # ]
    7930                 :          0 :                     nWidth = 0;
    7931                 :            :                 }
    7932                 :            :             }
    7933                 :            : 
    7934         [ #  # ]:          0 :             if( nWidth > 0 )
    7935                 :            :             {
    7936                 :          0 :                 drawTextLine( m_pReferenceDevice->PixelToLogic( aStartPt ),
    7937                 :            :                               m_pReferenceDevice->ImplDevicePixelToLogicWidth( nWidth ),
    7938 [ #  # ][ #  # ]:          0 :                               eStrikeout, eUnderline, eOverline, bUnderlineAbove );
                 [ #  # ]
    7939                 :            :             }
    7940                 :            :         }
    7941                 :            :         else
    7942                 :            :         {
    7943         [ #  # ]:          0 :             Point aStartPt = rLayout.GetDrawPosition();
    7944         [ #  # ]:          0 :             int nWidth = rLayout.GetTextWidth() / rLayout.GetUnitsPerPixel();
    7945                 :          0 :             drawTextLine( m_pReferenceDevice->PixelToLogic( aStartPt ),
    7946                 :            :                           m_pReferenceDevice->ImplDevicePixelToLogicWidth( nWidth ),
    7947 [ #  # ][ #  # ]:          0 :                           eStrikeout, eUnderline, eOverline, bUnderlineAbove );
                 [ #  # ]
    7948                 :            :         }
    7949                 :            :     }
    7950                 :            : 
    7951                 :            :     // write eventual emphasis marks
    7952 [ #  # ][ #  # ]:          0 :     if( m_aCurrentPDFState.m_aFont.GetEmphasisMark() & EMPHASISMARK_STYLE )
    7953                 :            :     {
    7954         [ #  # ]:          0 :         PolyPolygon             aEmphPoly;
    7955         [ #  # ]:          0 :         Rectangle               aEmphRect1;
    7956         [ #  # ]:          0 :         Rectangle               aEmphRect2;
    7957                 :            :         long                    nEmphYOff;
    7958                 :            :         long                    nEmphWidth;
    7959                 :            :         long                    nEmphHeight;
    7960                 :            :         sal_Bool                    bEmphPolyLine;
    7961                 :            :         FontEmphasisMark        nEmphMark;
    7962                 :            : 
    7963         [ #  # ]:          0 :         push( PUSH_ALL );
    7964                 :            : 
    7965         [ #  # ]:          0 :         aLine.setLength( 0 );
    7966         [ #  # ]:          0 :         aLine.append( "q\n" );
    7967                 :            : 
    7968         [ #  # ]:          0 :         nEmphMark = m_pReferenceDevice->ImplGetEmphasisMarkStyle( m_aCurrentPDFState.m_aFont );
    7969         [ #  # ]:          0 :         if ( nEmphMark & EMPHASISMARK_POS_BELOW )
    7970                 :          0 :             nEmphHeight = m_pReferenceDevice->mnEmphasisDescent;
    7971                 :            :         else
    7972                 :          0 :             nEmphHeight = m_pReferenceDevice->mnEmphasisAscent;
    7973                 :            :         m_pReferenceDevice->ImplGetEmphasisMark( aEmphPoly,
    7974                 :            :                                                  bEmphPolyLine,
    7975                 :            :                                                  aEmphRect1,
    7976                 :            :                                                  aEmphRect2,
    7977                 :            :                                                  nEmphYOff,
    7978                 :            :                                                  nEmphWidth,
    7979                 :            :                                                  nEmphMark,
    7980                 :            :                                                  m_pReferenceDevice->ImplDevicePixelToLogicWidth(nEmphHeight),
    7981 [ #  # ][ #  # ]:          0 :                                                  m_pReferenceDevice->mpFontEntry->mnOrientation );
    7982         [ #  # ]:          0 :         if ( bEmphPolyLine )
    7983                 :            :         {
    7984 [ #  # ][ #  # ]:          0 :             setLineColor( m_aCurrentPDFState.m_aFont.GetColor() );
    7985         [ #  # ]:          0 :             setFillColor( Color( COL_TRANSPARENT ) );
    7986                 :            :         }
    7987                 :            :         else
    7988                 :            :         {
    7989 [ #  # ][ #  # ]:          0 :             setFillColor( m_aCurrentPDFState.m_aFont.GetColor() );
    7990         [ #  # ]:          0 :             setLineColor( Color( COL_TRANSPARENT ) );
    7991                 :            :         }
    7992         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
    7993                 :            : 
    7994                 :          0 :         Point aOffset = Point(0,0);
    7995                 :            : 
    7996         [ #  # ]:          0 :         if ( nEmphMark & EMPHASISMARK_POS_BELOW )
    7997                 :          0 :             aOffset.Y() += m_pReferenceDevice->mpFontEntry->maMetric.mnDescent + nEmphYOff;
    7998                 :            :         else
    7999                 :          0 :             aOffset.Y() -= m_pReferenceDevice->mpFontEntry->maMetric.mnAscent + nEmphYOff;
    8000                 :            : 
    8001                 :          0 :         long nEmphWidth2     = nEmphWidth / 2;
    8002                 :          0 :         long nEmphHeight2    = nEmphHeight / 2;
    8003                 :          0 :         aOffset += Point( nEmphWidth2, nEmphHeight2 );
    8004                 :            : 
    8005         [ #  # ]:          0 :         if ( eAlign == ALIGN_BOTTOM )
    8006                 :          0 :             aOffset.Y() -= m_pReferenceDevice->mpFontEntry->maMetric.mnDescent;
    8007         [ #  # ]:          0 :         else if ( eAlign == ALIGN_TOP )
    8008                 :          0 :             aOffset.Y() += m_pReferenceDevice->mpFontEntry->maMetric.mnAscent;
    8009                 :            : 
    8010                 :          0 :         for( int nStart = 0;;)
    8011                 :            :         {
    8012                 :          0 :             Point aPos;
    8013                 :            :             sal_GlyphId nGlyphIndex;
    8014                 :            :             sal_Int32 nAdvance;
    8015 [ #  # ][ #  # ]:          0 :             if( !rLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart, &nAdvance ) )
    8016                 :            :                 break;
    8017                 :            : 
    8018 [ #  # ][ #  # ]:          0 :             if( !rLayout.IsSpacingGlyph( nGlyphIndex ) )
    8019                 :            :             {
    8020                 :          0 :                 Point aAdjOffset = aOffset;
    8021                 :          0 :                 aAdjOffset.X() += (nAdvance - nEmphWidth) / 2;
    8022                 :          0 :                 aAdjOffset = aRotScale.transform( aAdjOffset );
    8023                 :            : 
    8024                 :          0 :                 aAdjOffset -= Point( nEmphWidth2, nEmphHeight2 );
    8025                 :            : 
    8026                 :          0 :                 aPos += aAdjOffset;
    8027         [ #  # ]:          0 :                 aPos = m_pReferenceDevice->PixelToLogic( aPos );
    8028                 :          0 :                 drawEmphasisMark( aPos.X(), aPos.Y(),
    8029                 :            :                                   aEmphPoly, bEmphPolyLine,
    8030         [ #  # ]:          0 :                                   aEmphRect1, aEmphRect2 );
    8031                 :            :             }
    8032                 :            :         }
    8033                 :            : 
    8034         [ #  # ]:          0 :         writeBuffer( "Q\n", 2 );
    8035 [ #  # ][ #  # ]:          0 :         pop();
    8036         [ #  # ]:          0 :     }
    8037                 :            : 
    8038                 :            : }
    8039                 :            : 
    8040                 :          0 : void PDFWriterImpl::drawEmphasisMark( long nX, long nY,
    8041                 :            :                                       const PolyPolygon& rPolyPoly, sal_Bool bPolyLine,
    8042                 :            :                                       const Rectangle& rRect1, const Rectangle& rRect2 )
    8043                 :            : {
    8044                 :            :     // TODO: pass nWidth as width of this mark
    8045                 :            :     // long nWidth = 0;
    8046                 :            : 
    8047         [ #  # ]:          0 :     if ( rPolyPoly.Count() )
    8048                 :            :     {
    8049         [ #  # ]:          0 :         if ( bPolyLine )
    8050                 :            :         {
    8051 [ #  # ][ #  # ]:          0 :             Polygon aPoly = rPolyPoly.GetObject( 0 );
    8052         [ #  # ]:          0 :             aPoly.Move( nX, nY );
    8053 [ #  # ][ #  # ]:          0 :             drawPolyLine( aPoly );
    8054                 :            :         }
    8055                 :            :         else
    8056                 :            :         {
    8057         [ #  # ]:          0 :             PolyPolygon aPolyPoly = rPolyPoly;
    8058         [ #  # ]:          0 :             aPolyPoly.Move( nX, nY );
    8059 [ #  # ][ #  # ]:          0 :             drawPolyPolygon( aPolyPoly );
    8060                 :            :         }
    8061                 :            :     }
    8062                 :            : 
    8063         [ #  # ]:          0 :     if ( !rRect1.IsEmpty() )
    8064                 :            :     {
    8065                 :          0 :         Rectangle aRect( Point( nX+rRect1.Left(),
    8066 [ #  # ][ #  # ]:          0 :                                 nY+rRect1.Top() ), rRect1.GetSize() );
    8067         [ #  # ]:          0 :         drawRectangle( aRect );
    8068                 :            :     }
    8069                 :            : 
    8070         [ #  # ]:          0 :     if ( !rRect2.IsEmpty() )
    8071                 :            :     {
    8072                 :          0 :         Rectangle aRect( Point( nX+rRect2.Left(),
    8073 [ #  # ][ #  # ]:          0 :                                 nY+rRect2.Top() ), rRect2.GetSize() );
    8074                 :            : 
    8075         [ #  # ]:          0 :         drawRectangle( aRect );
    8076                 :            :     }
    8077                 :          0 : }
    8078                 :            : 
    8079                 :          0 : void PDFWriterImpl::drawText( const Point& rPos, const String& rText, xub_StrLen nIndex, xub_StrLen nLen, bool bTextLines )
    8080                 :            : {
    8081                 :          0 :     MARK( "drawText" );
    8082                 :            : 
    8083                 :          0 :     updateGraphicsState();
    8084                 :            : 
    8085                 :            :     // get a layout from the OuputDevice's SalGraphics
    8086                 :            :     // this also enforces font substitution and sets the font on SalGraphics
    8087                 :          0 :     SalLayout* pLayout = m_pReferenceDevice->ImplLayout( rText, nIndex, nLen, rPos );
    8088         [ #  # ]:          0 :     if( pLayout )
    8089                 :            :     {
    8090                 :          0 :         drawLayout( *pLayout, rText, bTextLines );
    8091                 :          0 :         pLayout->Release();
    8092                 :            :     }
    8093                 :          0 : }
    8094                 :            : 
    8095                 :          0 : void PDFWriterImpl::drawTextArray( const Point& rPos, const String& rText, const sal_Int32* pDXArray, xub_StrLen nIndex, xub_StrLen nLen, bool bTextLines )
    8096                 :            : {
    8097                 :          0 :     MARK( "drawText with array" );
    8098                 :            : 
    8099                 :          0 :     updateGraphicsState();
    8100                 :            : 
    8101                 :            :     // get a layout from the OuputDevice's SalGraphics
    8102                 :            :     // this also enforces font substitution and sets the font on SalGraphics
    8103                 :          0 :     SalLayout* pLayout = m_pReferenceDevice->ImplLayout( rText, nIndex, nLen, rPos, 0, pDXArray );
    8104         [ #  # ]:          0 :     if( pLayout )
    8105                 :            :     {
    8106                 :          0 :         drawLayout( *pLayout, rText, bTextLines );
    8107                 :          0 :         pLayout->Release();
    8108                 :            :     }
    8109                 :          0 : }
    8110                 :            : 
    8111                 :          0 : void PDFWriterImpl::drawStretchText( const Point& rPos, sal_uLong nWidth, const String& rText, xub_StrLen nIndex, xub_StrLen nLen, bool bTextLines )
    8112                 :            : {
    8113                 :          0 :     MARK( "drawStretchText" );
    8114                 :            : 
    8115                 :          0 :     updateGraphicsState();
    8116                 :            : 
    8117                 :            :     // get a layout from the OuputDevice's SalGraphics
    8118                 :            :     // this also enforces font substitution and sets the font on SalGraphics
    8119                 :          0 :     SalLayout* pLayout = m_pReferenceDevice->ImplLayout( rText, nIndex, nLen, rPos, nWidth );
    8120         [ #  # ]:          0 :     if( pLayout )
    8121                 :            :     {
    8122                 :          0 :         drawLayout( *pLayout, rText, bTextLines );
    8123                 :          0 :         pLayout->Release();
    8124                 :            :     }
    8125                 :          0 : }
    8126                 :            : 
    8127                 :          0 : void PDFWriterImpl::drawText( const Rectangle& rRect, const String& rOrigStr, sal_uInt16 nStyle, bool bTextLines )
    8128                 :            : {
    8129         [ #  # ]:          0 :     long        nWidth          = rRect.GetWidth();
    8130         [ #  # ]:          0 :     long        nHeight         = rRect.GetHeight();
    8131                 :            : 
    8132 [ #  # ][ #  # ]:          0 :     if ( nWidth <= 0 || nHeight <= 0 )
    8133                 :          0 :         return;
    8134                 :            : 
    8135         [ #  # ]:          0 :     MARK( "drawText with rectangle" );
    8136                 :            : 
    8137         [ #  # ]:          0 :     updateGraphicsState();
    8138                 :            : 
    8139                 :            :     // clip with rectangle
    8140                 :          0 :     OStringBuffer aLine;
    8141         [ #  # ]:          0 :     aLine.append( "q " );
    8142 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendRect( rRect, aLine );
    8143         [ #  # ]:          0 :     aLine.append( " W* n\n" );
    8144         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8145                 :            : 
    8146                 :            :     // if disabled text is needed, put in here
    8147                 :            : 
    8148                 :          0 :     Point       aPos            = rRect.TopLeft();
    8149                 :            : 
    8150         [ #  # ]:          0 :     long        nTextHeight     = m_pReferenceDevice->GetTextHeight();
    8151                 :          0 :     xub_StrLen  nMnemonicPos    = STRING_NOTFOUND;
    8152                 :            : 
    8153         [ #  # ]:          0 :     String aStr = rOrigStr;
    8154         [ #  # ]:          0 :     if ( nStyle & TEXT_DRAW_MNEMONIC )
    8155 [ #  # ][ #  # ]:          0 :         aStr = m_pReferenceDevice->GetNonMnemonicString( aStr, nMnemonicPos );
                 [ #  # ]
    8156                 :            : 
    8157                 :            :     // multiline text
    8158         [ #  # ]:          0 :     if ( nStyle & TEXT_DRAW_MULTILINE )
    8159                 :            :     {
    8160                 :          0 :         rtl::OUString           aLastLine;
    8161         [ #  # ]:          0 :         ImplMultiTextLineInfo   aMultiLineInfo;
    8162                 :            :         ImplTextLineInfo*       pLineInfo;
    8163                 :            :         xub_StrLen              i;
    8164                 :            :         xub_StrLen              nLines;
    8165                 :            :         xub_StrLen              nFormatLines;
    8166                 :            : 
    8167         [ #  # ]:          0 :         if ( nTextHeight )
    8168                 :            :         {
    8169                 :          0 :             ::vcl::DefaultTextLayout aLayout( *m_pReferenceDevice );
    8170         [ #  # ]:          0 :             OutputDevice::ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, aLayout );
    8171                 :          0 :             nLines = (xub_StrLen)(nHeight/nTextHeight);
    8172                 :          0 :             nFormatLines = aMultiLineInfo.Count();
    8173         [ #  # ]:          0 :             if ( !nLines )
    8174                 :          0 :                 nLines = 1;
    8175         [ #  # ]:          0 :             if ( nFormatLines > nLines )
    8176                 :            :             {
    8177         [ #  # ]:          0 :                 if ( nStyle & TEXT_DRAW_ENDELLIPSIS )
    8178                 :            :                 {
    8179                 :            :                     // handle last line
    8180                 :          0 :                     nFormatLines = nLines-1;
    8181                 :            : 
    8182                 :          0 :                     pLineInfo = aMultiLineInfo.GetLine( nFormatLines );
    8183 [ #  # ][ #  # ]:          0 :                     aLastLine = convertLineEnd(aStr.Copy(pLineInfo->GetIndex()), LINEEND_LF);
         [ #  # ][ #  # ]
    8184                 :            :                     // replace line feed by space
    8185                 :          0 :                     aLastLine = aLastLine.replace(_LF, ' ');
    8186 [ #  # ][ #  # ]:          0 :                     aLastLine = m_pReferenceDevice->GetEllipsisString( aLastLine, nWidth, nStyle );
         [ #  # ][ #  # ]
                 [ #  # ]
    8187                 :          0 :                     nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
    8188                 :          0 :                     nStyle |= TEXT_DRAW_TOP;
    8189                 :            :                 }
    8190                 :            :             }
    8191                 :            : 
    8192                 :            :             // vertical alignment
    8193         [ #  # ]:          0 :             if ( nStyle & TEXT_DRAW_BOTTOM )
    8194                 :          0 :                 aPos.Y() += nHeight-(nFormatLines*nTextHeight);
    8195         [ #  # ]:          0 :             else if ( nStyle & TEXT_DRAW_VCENTER )
    8196                 :          0 :                 aPos.Y() += (nHeight-(nFormatLines*nTextHeight))/2;
    8197                 :            : 
    8198                 :            :             // draw all lines excluding the last
    8199         [ #  # ]:          0 :             for ( i = 0; i < nFormatLines; i++ )
    8200                 :            :             {
    8201                 :          0 :                 pLineInfo = aMultiLineInfo.GetLine( i );
    8202         [ #  # ]:          0 :                 if ( nStyle & TEXT_DRAW_RIGHT )
    8203                 :          0 :                     aPos.X() += nWidth-pLineInfo->GetWidth();
    8204         [ #  # ]:          0 :                 else if ( nStyle & TEXT_DRAW_CENTER )
    8205                 :          0 :                     aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
    8206                 :          0 :                 xub_StrLen nIndex   = pLineInfo->GetIndex();
    8207                 :          0 :                 xub_StrLen nLineLen = pLineInfo->GetLen();
    8208         [ #  # ]:          0 :                 drawText( aPos, aStr, nIndex, nLineLen, bTextLines );
    8209                 :            :                 // mnemonics should not appear in documents,
    8210                 :            :                 // if the need arises, put them in here
    8211                 :          0 :                 aPos.Y() += nTextHeight;
    8212                 :          0 :                 aPos.X() = rRect.Left();
    8213                 :            :             }
    8214                 :            : 
    8215                 :            : 
    8216                 :            :             // output last line left adjusted since it was shortened
    8217         [ #  # ]:          0 :             if (!aLastLine.isEmpty())
    8218 [ #  # ][ #  # ]:          0 :                 drawText( aPos, aLastLine, 0, STRING_LEN, bTextLines );
         [ #  # ][ #  # ]
    8219         [ #  # ]:          0 :         }
    8220                 :            :     }
    8221                 :            :     else
    8222                 :            :     {
    8223         [ #  # ]:          0 :         long nTextWidth = m_pReferenceDevice->GetTextWidth( aStr );
    8224                 :            : 
    8225                 :            :         // Evt. Text kuerzen
    8226         [ #  # ]:          0 :         if ( nTextWidth > nWidth )
    8227                 :            :         {
    8228         [ #  # ]:          0 :             if ( nStyle & (TEXT_DRAW_ENDELLIPSIS | TEXT_DRAW_PATHELLIPSIS | TEXT_DRAW_NEWSELLIPSIS) )
    8229                 :            :             {
    8230 [ #  # ][ #  # ]:          0 :                 aStr = m_pReferenceDevice->GetEllipsisString( aStr, nWidth, nStyle );
                 [ #  # ]
    8231                 :          0 :                 nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
    8232                 :          0 :                 nStyle |= TEXT_DRAW_LEFT;
    8233         [ #  # ]:          0 :                 nTextWidth = m_pReferenceDevice->GetTextWidth( aStr );
    8234                 :            :             }
    8235                 :            :         }
    8236                 :            : 
    8237                 :            :         // vertical alignment
    8238         [ #  # ]:          0 :         if ( nStyle & TEXT_DRAW_RIGHT )
    8239                 :          0 :             aPos.X() += nWidth-nTextWidth;
    8240         [ #  # ]:          0 :         else if ( nStyle & TEXT_DRAW_CENTER )
    8241                 :          0 :             aPos.X() += (nWidth-nTextWidth)/2;
    8242                 :            : 
    8243         [ #  # ]:          0 :         if ( nStyle & TEXT_DRAW_BOTTOM )
    8244                 :          0 :             aPos.Y() += nHeight-nTextHeight;
    8245         [ #  # ]:          0 :         else if ( nStyle & TEXT_DRAW_VCENTER )
    8246                 :          0 :             aPos.Y() += (nHeight-nTextHeight)/2;
    8247                 :            : 
    8248                 :            :         // mnemonics should be inserted here if the need arises
    8249                 :            : 
    8250                 :            :         // draw the actual text
    8251         [ #  # ]:          0 :         drawText( aPos, aStr, 0, STRING_LEN, bTextLines );
    8252                 :            :     }
    8253                 :            : 
    8254                 :            :     // reset clip region to original value
    8255         [ #  # ]:          0 :     aLine.setLength( 0 );
    8256         [ #  # ]:          0 :     aLine.append( "Q\n" );
    8257 [ #  # ][ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8258                 :            : }
    8259                 :            : 
    8260                 :          0 : void PDFWriterImpl::drawLine( const Point& rStart, const Point& rStop )
    8261                 :            : {
    8262         [ #  # ]:          0 :     MARK( "drawLine" );
    8263                 :            : 
    8264         [ #  # ]:          0 :     updateGraphicsState();
    8265                 :            : 
    8266 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) )
    8267                 :          0 :         return;
    8268                 :            : 
    8269                 :          0 :     OStringBuffer aLine;
    8270 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( rStart, aLine );
    8271         [ #  # ]:          0 :     aLine.append( " m " );
    8272 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( rStop, aLine );
    8273         [ #  # ]:          0 :     aLine.append( " l S\n" );
    8274                 :            : 
    8275         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8276                 :            : }
    8277                 :            : 
    8278                 :          0 : void PDFWriterImpl::drawLine( const Point& rStart, const Point& rStop, const LineInfo& rInfo )
    8279                 :            : {
    8280         [ #  # ]:          0 :     MARK( "drawLine with LineInfo" );
    8281         [ #  # ]:          0 :     updateGraphicsState();
    8282                 :            : 
    8283 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) )
    8284                 :            :         return;
    8285                 :            : 
    8286 [ #  # ][ #  # ]:          0 :     if( rInfo.GetStyle() == LINE_SOLID && rInfo.GetWidth() < 2 )
                 [ #  # ]
    8287                 :            :     {
    8288         [ #  # ]:          0 :         drawLine( rStart, rStop );
    8289                 :            :         return;
    8290                 :            :     }
    8291                 :            : 
    8292                 :          0 :     OStringBuffer aLine;
    8293                 :            : 
    8294         [ #  # ]:          0 :     aLine.append( "q " );
    8295 [ #  # ][ #  # ]:          0 :     if( m_aPages.back().appendLineInfo( rInfo, aLine ) )
                 [ #  # ]
    8296                 :            :     {
    8297 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendPoint( rStart, aLine );
    8298         [ #  # ]:          0 :         aLine.append( " m " );
    8299 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendPoint( rStop, aLine );
    8300         [ #  # ]:          0 :         aLine.append( " l S Q\n" );
    8301                 :            : 
    8302         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
    8303                 :            :     }
    8304                 :            :     else
    8305                 :            :     {
    8306         [ #  # ]:          0 :         PDFWriter::ExtLineInfo aInfo;
    8307         [ #  # ]:          0 :         convertLineInfoToExtLineInfo( rInfo, aInfo );
    8308                 :          0 :         Point aPolyPoints[2] = { rStart, rStop };
    8309         [ #  # ]:          0 :         Polygon aPoly( 2, aPolyPoints );
    8310 [ #  # ][ #  # ]:          0 :         drawPolyLine( aPoly, aInfo );
    8311                 :          0 :     }
    8312                 :            : }
    8313                 :            : 
    8314                 :            : #define HCONV( x ) m_pReferenceDevice->ImplDevicePixelToLogicHeight( x )
    8315                 :            : 
    8316                 :          0 : void PDFWriterImpl::drawWaveTextLine( OStringBuffer& aLine, long nWidth, FontUnderline eTextLine, Color aColor, bool bIsAbove )
    8317                 :            : {
    8318                 :            :     // note: units in pFontEntry are ref device pixel
    8319                 :          0 :     ImplFontEntry*  pFontEntry = m_pReferenceDevice->mpFontEntry;
    8320                 :          0 :     long            nLineHeight = 0;
    8321                 :          0 :     long            nLinePos = 0;
    8322                 :            : 
    8323                 :          0 :     appendStrokingColor( aColor, aLine );
    8324                 :          0 :     aLine.append( "\n" );
    8325                 :            : 
    8326         [ #  # ]:          0 :     if ( bIsAbove )
    8327                 :            :     {
    8328         [ #  # ]:          0 :         if ( !pFontEntry->maMetric.mnAboveWUnderlineSize )
    8329                 :          0 :             m_pReferenceDevice->ImplInitAboveTextLineSize();
    8330                 :          0 :         nLineHeight = HCONV( pFontEntry->maMetric.mnAboveWUnderlineSize );
    8331                 :          0 :         nLinePos = HCONV( pFontEntry->maMetric.mnAboveWUnderlineOffset );
    8332                 :            :     }
    8333                 :            :     else
    8334                 :            :     {
    8335         [ #  # ]:          0 :         if ( !pFontEntry->maMetric.mnWUnderlineSize )
    8336                 :          0 :             m_pReferenceDevice->ImplInitTextLineSize();
    8337                 :          0 :         nLineHeight = HCONV( pFontEntry->maMetric.mnWUnderlineSize );
    8338                 :          0 :         nLinePos = HCONV( pFontEntry->maMetric.mnWUnderlineOffset );
    8339                 :            :     }
    8340 [ #  # ][ #  # ]:          0 :     if ( (eTextLine == UNDERLINE_SMALLWAVE) && (nLineHeight > 3) )
    8341                 :          0 :         nLineHeight = 3;
    8342                 :            : 
    8343                 :          0 :     long nLineWidth = getReferenceDevice()->mnDPIX/450;
    8344         [ #  # ]:          0 :     if ( ! nLineWidth )
    8345                 :          0 :         nLineWidth = 1;
    8346                 :            : 
    8347         [ #  # ]:          0 :     if ( eTextLine == UNDERLINE_BOLDWAVE )
    8348                 :          0 :         nLineWidth = 3*nLineWidth;
    8349                 :            : 
    8350                 :          0 :     m_aPages.back().appendMappedLength( (sal_Int32)nLineWidth, aLine );
    8351                 :          0 :     aLine.append( " w " );
    8352                 :            : 
    8353         [ #  # ]:          0 :     if ( eTextLine == UNDERLINE_DOUBLEWAVE )
    8354                 :            :     {
    8355                 :          0 :         long nOrgLineHeight = nLineHeight;
    8356                 :          0 :         nLineHeight /= 3;
    8357         [ #  # ]:          0 :         if ( nLineHeight < 2 )
    8358                 :            :         {
    8359         [ #  # ]:          0 :             if ( nOrgLineHeight > 1 )
    8360                 :          0 :                 nLineHeight = 2;
    8361                 :            :             else
    8362                 :          0 :                 nLineHeight = 1;
    8363                 :            :         }
    8364                 :          0 :         long nLineDY = nOrgLineHeight-(nLineHeight*2);
    8365         [ #  # ]:          0 :         if ( nLineDY < nLineWidth )
    8366                 :          0 :             nLineDY = nLineWidth;
    8367                 :          0 :         long nLineDY2 = nLineDY/2;
    8368         [ #  # ]:          0 :         if ( !nLineDY2 )
    8369                 :          0 :             nLineDY2 = 1;
    8370                 :            : 
    8371                 :          0 :         nLinePos -= nLineWidth-nLineDY2;
    8372                 :            : 
    8373                 :          0 :         m_aPages.back().appendWaveLine( nWidth, -nLinePos, 2*nLineHeight, aLine );
    8374                 :            : 
    8375                 :          0 :         nLinePos += nLineWidth+nLineDY;
    8376                 :          0 :         m_aPages.back().appendWaveLine( nWidth, -nLinePos, 2*nLineHeight, aLine );
    8377                 :            :     }
    8378                 :            :     else
    8379                 :            :     {
    8380         [ #  # ]:          0 :         if ( eTextLine != UNDERLINE_BOLDWAVE )
    8381                 :          0 :             nLinePos -= nLineWidth/2;
    8382                 :          0 :         m_aPages.back().appendWaveLine( nWidth, -nLinePos, nLineHeight, aLine );
    8383                 :            :     }
    8384                 :          0 : }
    8385                 :            : 
    8386                 :          0 : void PDFWriterImpl::drawStraightTextLine( OStringBuffer& aLine, long nWidth, FontUnderline eTextLine, Color aColor, bool bIsAbove )
    8387                 :            : {
    8388                 :            :     // note: units in pFontEntry are ref device pixel
    8389                 :          0 :     ImplFontEntry*  pFontEntry = m_pReferenceDevice->mpFontEntry;
    8390                 :          0 :     long            nLineHeight = 0;
    8391                 :          0 :     long            nLinePos  = 0;
    8392                 :          0 :     long            nLinePos2 = 0;
    8393                 :            : 
    8394         [ #  # ]:          0 :     if ( eTextLine > UNDERLINE_BOLDWAVE )
    8395                 :          0 :         eTextLine = UNDERLINE_SINGLE;
    8396                 :            : 
    8397   [ #  #  #  # ]:          0 :     switch ( eTextLine )
    8398                 :            :     {
    8399                 :            :         case UNDERLINE_SINGLE:
    8400                 :            :         case UNDERLINE_DOTTED:
    8401                 :            :         case UNDERLINE_DASH:
    8402                 :            :         case UNDERLINE_LONGDASH:
    8403                 :            :         case UNDERLINE_DASHDOT:
    8404                 :            :         case UNDERLINE_DASHDOTDOT:
    8405         [ #  # ]:          0 :             if ( bIsAbove )
    8406                 :            :             {
    8407         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnAboveUnderlineSize )
    8408                 :          0 :                     m_pReferenceDevice->ImplInitAboveTextLineSize();
    8409                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnAboveUnderlineSize );
    8410                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnAboveUnderlineOffset );
    8411                 :            :             }
    8412                 :            :             else
    8413                 :            :             {
    8414         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnUnderlineSize )
    8415                 :          0 :                     m_pReferenceDevice->ImplInitTextLineSize();
    8416                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnUnderlineSize );
    8417                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnUnderlineOffset );
    8418                 :            :             }
    8419                 :          0 :             break;
    8420                 :            :         case UNDERLINE_BOLD:
    8421                 :            :         case UNDERLINE_BOLDDOTTED:
    8422                 :            :         case UNDERLINE_BOLDDASH:
    8423                 :            :         case UNDERLINE_BOLDLONGDASH:
    8424                 :            :         case UNDERLINE_BOLDDASHDOT:
    8425                 :            :         case UNDERLINE_BOLDDASHDOTDOT:
    8426         [ #  # ]:          0 :             if ( bIsAbove )
    8427                 :            :             {
    8428         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnAboveBUnderlineSize )
    8429                 :          0 :                     m_pReferenceDevice->ImplInitAboveTextLineSize();
    8430                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnAboveBUnderlineSize );
    8431                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnAboveBUnderlineOffset );
    8432                 :            :             }
    8433                 :            :             else
    8434                 :            :             {
    8435         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnBUnderlineSize )
    8436                 :          0 :                     m_pReferenceDevice->ImplInitTextLineSize();
    8437                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnBUnderlineSize );
    8438                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnBUnderlineOffset );
    8439                 :          0 :                 nLinePos += nLineHeight/2;
    8440                 :            :             }
    8441                 :          0 :             break;
    8442                 :            :         case UNDERLINE_DOUBLE:
    8443         [ #  # ]:          0 :             if ( bIsAbove )
    8444                 :            :             {
    8445         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnAboveDUnderlineSize )
    8446                 :          0 :                     m_pReferenceDevice->ImplInitAboveTextLineSize();
    8447                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnAboveDUnderlineSize );
    8448                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnAboveDUnderlineOffset1 );
    8449                 :          0 :                 nLinePos2   = HCONV( pFontEntry->maMetric.mnAboveDUnderlineOffset2 );
    8450                 :            :             }
    8451                 :            :             else
    8452                 :            :             {
    8453         [ #  # ]:          0 :                 if ( !pFontEntry->maMetric.mnDUnderlineSize )
    8454                 :          0 :                     m_pReferenceDevice->ImplInitTextLineSize();
    8455                 :          0 :                 nLineHeight = HCONV( pFontEntry->maMetric.mnDUnderlineSize );
    8456                 :          0 :                 nLinePos    = HCONV( pFontEntry->maMetric.mnDUnderlineOffset1 );
    8457                 :          0 :                 nLinePos2   = HCONV( pFontEntry->maMetric.mnDUnderlineOffset2 );
    8458                 :            :             }
    8459                 :            :         default:
    8460                 :          0 :             break;
    8461                 :            :     }
    8462                 :            : 
    8463         [ #  # ]:          0 :     if ( nLineHeight )
    8464                 :            :     {
    8465                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, true );
    8466                 :          0 :         aLine.append( " w " );
    8467                 :          0 :         appendStrokingColor( aColor, aLine );
    8468                 :          0 :         aLine.append( "\n" );
    8469                 :            : 
    8470   [ #  #  #  #  :          0 :         switch ( eTextLine )
                      # ]
    8471                 :            :         {
    8472                 :            :             case UNDERLINE_DOTTED:
    8473                 :            :             case UNDERLINE_BOLDDOTTED:
    8474                 :          0 :                 aLine.append( "[ " );
    8475                 :          0 :                 m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, false );
    8476                 :          0 :                 aLine.append( " ] 0 d\n" );
    8477                 :          0 :                 break;
    8478                 :            :             case UNDERLINE_DASH:
    8479                 :            :             case UNDERLINE_LONGDASH:
    8480                 :            :             case UNDERLINE_BOLDDASH:
    8481                 :            :             case UNDERLINE_BOLDLONGDASH:
    8482                 :            :                 {
    8483                 :          0 :                     sal_Int32 nDashLength = 4*nLineHeight;
    8484                 :          0 :                     sal_Int32 nVoidLength = 2*nLineHeight;
    8485 [ #  # ][ #  # ]:          0 :                     if ( ( eTextLine == UNDERLINE_LONGDASH ) || ( eTextLine == UNDERLINE_BOLDLONGDASH ) )
    8486                 :          0 :                         nDashLength = 8*nLineHeight;
    8487                 :            : 
    8488                 :          0 :                     aLine.append( "[ " );
    8489                 :          0 :                     m_aPages.back().appendMappedLength( nDashLength, aLine, false );
    8490                 :          0 :                     aLine.append( ' ' );
    8491                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8492                 :          0 :                     aLine.append( " ] 0 d\n" );
    8493                 :            :                 }
    8494                 :          0 :                 break;
    8495                 :            :             case UNDERLINE_DASHDOT:
    8496                 :            :             case UNDERLINE_BOLDDASHDOT:
    8497                 :            :                 {
    8498                 :          0 :                     sal_Int32 nDashLength = 4*nLineHeight;
    8499                 :          0 :                     sal_Int32 nVoidLength = 2*nLineHeight;
    8500                 :          0 :                     aLine.append( "[ " );
    8501                 :          0 :                     m_aPages.back().appendMappedLength( nDashLength, aLine, false );
    8502                 :          0 :                     aLine.append( ' ' );
    8503                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8504                 :          0 :                     aLine.append( ' ' );
    8505                 :          0 :                     m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, false );
    8506                 :          0 :                     aLine.append( ' ' );
    8507                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8508                 :          0 :                     aLine.append( " ] 0 d\n" );
    8509                 :            :                 }
    8510                 :          0 :                 break;
    8511                 :            :             case UNDERLINE_DASHDOTDOT:
    8512                 :            :             case UNDERLINE_BOLDDASHDOTDOT:
    8513                 :            :                 {
    8514                 :          0 :                     sal_Int32 nDashLength = 4*nLineHeight;
    8515                 :          0 :                     sal_Int32 nVoidLength = 2*nLineHeight;
    8516                 :          0 :                     aLine.append( "[ " );
    8517                 :          0 :                     m_aPages.back().appendMappedLength( nDashLength, aLine, false );
    8518                 :          0 :                     aLine.append( ' ' );
    8519                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8520                 :          0 :                     aLine.append( ' ' );
    8521                 :          0 :                     m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, false );
    8522                 :          0 :                     aLine.append( ' ' );
    8523                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8524                 :          0 :                     aLine.append( ' ' );
    8525                 :          0 :                     m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, false );
    8526                 :          0 :                     aLine.append( ' ' );
    8527                 :          0 :                     m_aPages.back().appendMappedLength( nVoidLength, aLine, false );
    8528                 :          0 :                     aLine.append( " ] 0 d\n" );
    8529                 :            :                 }
    8530                 :          0 :                 break;
    8531                 :            :             default:
    8532                 :          0 :                 break;
    8533                 :            :         }
    8534                 :            : 
    8535                 :          0 :         aLine.append( "0 " );
    8536                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos), aLine, true );
    8537                 :          0 :         aLine.append( " m " );
    8538                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)nWidth, aLine, false );
    8539                 :          0 :         aLine.append( ' ' );
    8540                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos), aLine, true );
    8541                 :          0 :         aLine.append( " l S\n" );
    8542         [ #  # ]:          0 :         if ( eTextLine == UNDERLINE_DOUBLE )
    8543                 :            :         {
    8544                 :          0 :             aLine.append( "0 " );
    8545                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos2-nLineHeight), aLine, true );
    8546                 :          0 :             aLine.append( " m " );
    8547                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)nWidth, aLine, false );
    8548                 :          0 :             aLine.append( ' ' );
    8549                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos2-nLineHeight), aLine, true );
    8550                 :          0 :             aLine.append( " l S\n" );
    8551                 :            :         }
    8552                 :            :     }
    8553                 :          0 : }
    8554                 :            : 
    8555                 :          0 : void PDFWriterImpl::drawStrikeoutLine( OStringBuffer& aLine, long nWidth, FontStrikeout eStrikeout, Color aColor )
    8556                 :            : {
    8557                 :            :     // note: units in pFontEntry are ref device pixel
    8558                 :          0 :     ImplFontEntry*  pFontEntry = m_pReferenceDevice->mpFontEntry;
    8559                 :          0 :     long            nLineHeight = 0;
    8560                 :          0 :     long            nLinePos  = 0;
    8561                 :          0 :     long            nLinePos2 = 0;
    8562                 :            : 
    8563         [ #  # ]:          0 :     if ( eStrikeout > STRIKEOUT_X )
    8564                 :          0 :         eStrikeout = STRIKEOUT_SINGLE;
    8565                 :            : 
    8566   [ #  #  #  # ]:          0 :     switch ( eStrikeout )
    8567                 :            :     {
    8568                 :            :         case STRIKEOUT_SINGLE:
    8569         [ #  # ]:          0 :             if ( !pFontEntry->maMetric.mnStrikeoutSize )
    8570                 :          0 :                 m_pReferenceDevice->ImplInitTextLineSize();
    8571                 :          0 :             nLineHeight = HCONV( pFontEntry->maMetric.mnStrikeoutSize );
    8572                 :          0 :             nLinePos    = HCONV( pFontEntry->maMetric.mnStrikeoutOffset );
    8573                 :          0 :             break;
    8574                 :            :         case STRIKEOUT_BOLD:
    8575         [ #  # ]:          0 :             if ( !pFontEntry->maMetric.mnBStrikeoutSize )
    8576                 :          0 :                 m_pReferenceDevice->ImplInitTextLineSize();
    8577                 :          0 :             nLineHeight = HCONV( pFontEntry->maMetric.mnBStrikeoutSize );
    8578                 :          0 :             nLinePos    = HCONV( pFontEntry->maMetric.mnBStrikeoutOffset );
    8579                 :          0 :             break;
    8580                 :            :         case STRIKEOUT_DOUBLE:
    8581         [ #  # ]:          0 :             if ( !pFontEntry->maMetric.mnDStrikeoutSize )
    8582                 :          0 :                 m_pReferenceDevice->ImplInitTextLineSize();
    8583                 :          0 :             nLineHeight = HCONV( pFontEntry->maMetric.mnDStrikeoutSize );
    8584                 :          0 :             nLinePos    = HCONV( pFontEntry->maMetric.mnDStrikeoutOffset1 );
    8585                 :          0 :             nLinePos2   = HCONV( pFontEntry->maMetric.mnDStrikeoutOffset2 );
    8586                 :          0 :             break;
    8587                 :            :         default:
    8588                 :          0 :             break;
    8589                 :            :     }
    8590                 :            : 
    8591         [ #  # ]:          0 :     if ( nLineHeight )
    8592                 :            :     {
    8593                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)nLineHeight, aLine, true );
    8594                 :          0 :         aLine.append( " w " );
    8595                 :          0 :         appendStrokingColor( aColor, aLine );
    8596                 :          0 :         aLine.append( "\n" );
    8597                 :            : 
    8598                 :          0 :         aLine.append( "0 " );
    8599                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos), aLine, true );
    8600                 :          0 :         aLine.append( " m " );
    8601                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)nWidth, aLine, true );
    8602                 :          0 :         aLine.append( ' ' );
    8603                 :          0 :         m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos), aLine, true );
    8604                 :          0 :         aLine.append( " l S\n" );
    8605                 :            : 
    8606         [ #  # ]:          0 :         if ( eStrikeout == STRIKEOUT_DOUBLE )
    8607                 :            :         {
    8608                 :          0 :             aLine.append( "0 " );
    8609                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos2-nLineHeight), aLine, true );
    8610                 :          0 :             aLine.append( " m " );
    8611                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)nWidth, aLine, true );
    8612                 :          0 :             aLine.append( ' ' );
    8613                 :          0 :             m_aPages.back().appendMappedLength( (sal_Int32)(-nLinePos2-nLineHeight), aLine, true );
    8614                 :          0 :             aLine.append( " l S\n" );
    8615                 :            :         }
    8616                 :            :     }
    8617                 :          0 : }
    8618                 :            : 
    8619                 :          0 : void PDFWriterImpl::drawStrikeoutChar( const Point& rPos, long nWidth, FontStrikeout eStrikeout )
    8620                 :            : {
    8621                 :            :     //See qadevOOo/testdocs/StrikeThrough.odt for examples if you need
    8622                 :            :     //to tweak this
    8623                 :            : 
    8624 [ #  # ][ #  # ]:          0 :     rtl::OUString aStrikeoutChar = eStrikeout == STRIKEOUT_SLASH ? rtl::OUString("/") : rtl::OUString("X");
                 [ #  # ]
    8625         [ #  # ]:          0 :     String aStrikeout = aStrikeoutChar;
    8626 [ #  # ][ #  # ]:          0 :     while( m_pReferenceDevice->GetTextWidth( aStrikeout ) < nWidth )
    8627         [ #  # ]:          0 :         aStrikeout.Append( aStrikeout );
    8628                 :            : 
    8629                 :            :     // do not get broader than nWidth modulo 1 character
    8630 [ #  # ][ #  # ]:          0 :     while( m_pReferenceDevice->GetTextWidth( aStrikeout ) >= nWidth )
    8631         [ #  # ]:          0 :         aStrikeout.Erase( 0, 1 );
    8632 [ #  # ][ #  # ]:          0 :     aStrikeout.Append( aStrikeoutChar );
                 [ #  # ]
    8633         [ #  # ]:          0 :     sal_Bool bShadow = m_aCurrentPDFState.m_aFont.IsShadow();
    8634         [ #  # ]:          0 :     if ( bShadow )
    8635                 :            :     {
    8636         [ #  # ]:          0 :         Font aFont = m_aCurrentPDFState.m_aFont;
    8637         [ #  # ]:          0 :         aFont.SetShadow( sal_False );
    8638         [ #  # ]:          0 :         setFont( aFont );
    8639 [ #  # ][ #  # ]:          0 :         updateGraphicsState();
    8640                 :            :     }
    8641                 :            : 
    8642                 :            :     // strikeout string is left aligned non-CTL text
    8643                 :          0 :     sal_uLong nOrigTLM = m_pReferenceDevice->GetLayoutMode();
    8644         [ #  # ]:          0 :     m_pReferenceDevice->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG|TEXT_LAYOUT_COMPLEX_DISABLED );
    8645                 :            : 
    8646         [ #  # ]:          0 :     push( PUSH_CLIPREGION );
    8647         [ #  # ]:          0 :     FontMetric aRefDevFontMetric = m_pReferenceDevice->GetFontMetric();
    8648         [ #  # ]:          0 :     Rectangle aRect;
    8649                 :          0 :     aRect.nLeft = rPos.X();
    8650                 :          0 :     aRect.nRight = aRect.nLeft+nWidth;
    8651         [ #  # ]:          0 :     aRect.nBottom = rPos.Y()+aRefDevFontMetric.GetDescent();
    8652         [ #  # ]:          0 :     aRect.nTop = rPos.Y()-aRefDevFontMetric.GetAscent();
    8653                 :            : 
    8654                 :          0 :     ImplFontEntry* pFontEntry = m_pReferenceDevice->mpFontEntry;
    8655         [ #  # ]:          0 :     if (pFontEntry->mnOrientation)
    8656                 :            :     {
    8657         [ #  # ]:          0 :         Polygon aPoly( aRect );
    8658         [ #  # ]:          0 :         aPoly.Rotate( rPos, pFontEntry->mnOrientation);
    8659 [ #  # ][ #  # ]:          0 :         aRect = aPoly.GetBoundRect();
    8660                 :            :     }
    8661                 :            : 
    8662         [ #  # ]:          0 :     intersectClipRegion( aRect );
    8663         [ #  # ]:          0 :     drawText( rPos, aStrikeout, 0, aStrikeout.Len(), false );
    8664         [ #  # ]:          0 :     pop();
    8665                 :            : 
    8666         [ #  # ]:          0 :     m_pReferenceDevice->SetLayoutMode( nOrigTLM );
    8667                 :            : 
    8668         [ #  # ]:          0 :     if ( bShadow )
    8669                 :            :     {
    8670         [ #  # ]:          0 :         Font aFont = m_aCurrentPDFState.m_aFont;
    8671         [ #  # ]:          0 :         aFont.SetShadow( sal_True );
    8672         [ #  # ]:          0 :         setFont( aFont );
    8673 [ #  # ][ #  # ]:          0 :         updateGraphicsState();
    8674 [ #  # ][ #  # ]:          0 :     }
    8675                 :          0 : }
    8676                 :            : 
    8677                 :          0 : void PDFWriterImpl::drawTextLine( const Point& rPos, long nWidth, FontStrikeout eStrikeout, FontUnderline eUnderline, FontUnderline eOverline, bool bUnderlineAbove )
    8678                 :            : {
    8679 [ #  # ][ #  # ]:          0 :     if ( !nWidth ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    8680                 :            :          ( ((eStrikeout == STRIKEOUT_NONE)||(eStrikeout == STRIKEOUT_DONTKNOW)) &&
    8681                 :            :            ((eUnderline == UNDERLINE_NONE)||(eUnderline == UNDERLINE_DONTKNOW)) &&
    8682                 :            :            ((eOverline  == UNDERLINE_NONE)||(eOverline  == UNDERLINE_DONTKNOW)) ) )
    8683                 :          0 :         return;
    8684                 :            : 
    8685         [ #  # ]:          0 :     MARK( "drawTextLine" );
    8686         [ #  # ]:          0 :     updateGraphicsState();
    8687                 :            : 
    8688                 :            :     // note: units in pFontEntry are ref device pixel
    8689                 :          0 :     ImplFontEntry*  pFontEntry = m_pReferenceDevice->mpFontEntry;
    8690                 :          0 :     Color           aUnderlineColor = m_aCurrentPDFState.m_aTextLineColor;
    8691                 :          0 :     Color           aOverlineColor  = m_aCurrentPDFState.m_aOverlineColor;
    8692         [ #  # ]:          0 :     Color           aStrikeoutColor = m_aCurrentPDFState.m_aFont.GetColor();
    8693                 :          0 :     bool            bStrikeoutDone = false;
    8694                 :          0 :     bool            bUnderlineDone = false;
    8695                 :          0 :     bool            bOverlineDone  = false;
    8696                 :            : 
    8697 [ #  # ][ #  # ]:          0 :     if ( (eStrikeout == STRIKEOUT_SLASH) || (eStrikeout == STRIKEOUT_X) )
    8698                 :            :     {
    8699         [ #  # ]:          0 :         drawStrikeoutChar( rPos, nWidth, eStrikeout );
    8700                 :          0 :         bStrikeoutDone = true;
    8701                 :            :     }
    8702                 :            : 
    8703                 :          0 :     Point aPos( rPos );
    8704         [ #  # ]:          0 :     TextAlign eAlign = m_aCurrentPDFState.m_aFont.GetAlign();
    8705         [ #  # ]:          0 :     if( eAlign == ALIGN_TOP )
    8706         [ #  # ]:          0 :         aPos.Y() += HCONV( pFontEntry->maMetric.mnAscent );
    8707         [ #  # ]:          0 :     else if( eAlign == ALIGN_BOTTOM )
    8708         [ #  # ]:          0 :         aPos.Y() -= HCONV( pFontEntry->maMetric.mnDescent );
    8709                 :            : 
    8710                 :          0 :     OStringBuffer aLine( 512 );
    8711                 :            :     // save GS
    8712         [ #  # ]:          0 :     aLine.append( "q " );
    8713                 :            : 
    8714                 :            :     // rotate and translate matrix
    8715         [ #  # ]:          0 :     double fAngle = (double)m_aCurrentPDFState.m_aFont.GetOrientation() * M_PI / 1800.0;
    8716                 :          0 :     Matrix3 aMat;
    8717                 :          0 :     aMat.rotate( fAngle );
    8718                 :          0 :     aMat.translate( aPos.X(), aPos.Y() );
    8719 [ #  # ][ #  # ]:          0 :     aMat.append( m_aPages.back(), aLine );
    8720         [ #  # ]:          0 :     aLine.append( " cm\n" );
    8721                 :            : 
    8722         [ #  # ]:          0 :     if ( aUnderlineColor.GetTransparency() != 0 )
    8723                 :          0 :         aUnderlineColor = aStrikeoutColor;
    8724                 :            : 
    8725 [ #  # ][ #  # ]:          0 :     if ( (eUnderline == UNDERLINE_SMALLWAVE) ||
         [ #  # ][ #  # ]
    8726                 :            :          (eUnderline == UNDERLINE_WAVE) ||
    8727                 :            :          (eUnderline == UNDERLINE_DOUBLEWAVE) ||
    8728                 :            :          (eUnderline == UNDERLINE_BOLDWAVE) )
    8729                 :            :     {
    8730         [ #  # ]:          0 :         drawWaveTextLine( aLine, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
    8731                 :          0 :         bUnderlineDone = true;
    8732                 :            :     }
    8733                 :            : 
    8734 [ #  # ][ #  # ]:          0 :     if ( (eOverline == UNDERLINE_SMALLWAVE) ||
         [ #  # ][ #  # ]
    8735                 :            :          (eOverline == UNDERLINE_WAVE) ||
    8736                 :            :          (eOverline == UNDERLINE_DOUBLEWAVE) ||
    8737                 :            :          (eOverline == UNDERLINE_BOLDWAVE) )
    8738                 :            :     {
    8739         [ #  # ]:          0 :         drawWaveTextLine( aLine, nWidth, eOverline, aOverlineColor, true );
    8740                 :          0 :         bOverlineDone = true;
    8741                 :            :     }
    8742                 :            : 
    8743         [ #  # ]:          0 :     if ( !bUnderlineDone )
    8744                 :            :     {
    8745         [ #  # ]:          0 :         drawStraightTextLine( aLine, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
    8746                 :            :     }
    8747                 :            : 
    8748         [ #  # ]:          0 :     if ( !bOverlineDone )
    8749                 :            :     {
    8750         [ #  # ]:          0 :         drawStraightTextLine( aLine, nWidth, eOverline, aOverlineColor, true );
    8751                 :            :     }
    8752                 :            : 
    8753         [ #  # ]:          0 :     if ( !bStrikeoutDone )
    8754                 :            :     {
    8755         [ #  # ]:          0 :         drawStrikeoutLine( aLine, nWidth, eStrikeout, aStrikeoutColor );
    8756                 :            :     }
    8757                 :            : 
    8758         [ #  # ]:          0 :     aLine.append( "Q\n" );
    8759         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8760                 :            : }
    8761                 :            : 
    8762                 :          0 : void PDFWriterImpl::drawPolygon( const Polygon& rPoly )
    8763                 :            : {
    8764         [ #  # ]:          0 :     MARK( "drawPolygon" );
    8765                 :            : 
    8766         [ #  # ]:          0 :     updateGraphicsState();
    8767                 :            : 
    8768         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    8769 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    8770                 :          0 :         return;
    8771                 :            : 
    8772         [ #  # ]:          0 :     int nPoints = rPoly.GetSize();
    8773                 :          0 :     OStringBuffer aLine( 20 * nPoints );
    8774 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPolygon( rPoly, aLine );
    8775         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    8776 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    8777         [ #  # ]:          0 :         aLine.append( "B*\n" );
    8778 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    8779         [ #  # ]:          0 :         aLine.append( "S\n" );
    8780                 :            :     else
    8781         [ #  # ]:          0 :         aLine.append( "f*\n" );
    8782                 :            : 
    8783         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8784                 :            : }
    8785                 :            : 
    8786                 :          0 : void PDFWriterImpl::drawPolyPolygon( const PolyPolygon& rPolyPoly )
    8787                 :            : {
    8788         [ #  # ]:          0 :     MARK( "drawPolyPolygon" );
    8789                 :            : 
    8790         [ #  # ]:          0 :     updateGraphicsState();
    8791                 :            : 
    8792         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    8793 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    8794                 :          0 :         return;
    8795                 :            : 
    8796         [ #  # ]:          0 :     int nPolygons = rPolyPoly.Count();
    8797                 :            : 
    8798                 :          0 :     OStringBuffer aLine( 40 * nPolygons );
    8799 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPolyPolygon( rPolyPoly, aLine );
    8800         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    8801 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    8802         [ #  # ]:          0 :         aLine.append( "B*\n" );
    8803 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    8804         [ #  # ]:          0 :         aLine.append( "S\n" );
    8805                 :            :     else
    8806         [ #  # ]:          0 :         aLine.append( "f*\n" );
    8807                 :            : 
    8808         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8809                 :            : }
    8810                 :            : 
    8811                 :          0 : void PDFWriterImpl::drawTransparent( const PolyPolygon& rPolyPoly, sal_uInt32 nTransparentPercent )
    8812                 :            : {
    8813                 :            :     DBG_ASSERT( nTransparentPercent <= 100, "invalid alpha value" );
    8814                 :          0 :     nTransparentPercent = nTransparentPercent % 100;
    8815                 :            : 
    8816         [ #  # ]:          0 :     MARK( "drawTransparent" );
    8817                 :            : 
    8818         [ #  # ]:          0 :     updateGraphicsState();
    8819                 :            : 
    8820         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    8821 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    8822                 :            :         return;
    8823                 :            : 
    8824 [ #  # ][ #  # ]:          0 :     if( m_bIsPDF_A1 || m_aContext.Version < PDFWriter::PDF_1_4 )
    8825                 :            :     {
    8826                 :            :         m_aErrors.insert( m_bIsPDF_A1 ?
    8827                 :            :                           PDFWriter::Warning_Transparency_Omitted_PDFA :
    8828         [ #  # ]:          0 :                           PDFWriter::Warning_Transparency_Omitted_PDF13 );
    8829                 :            : 
    8830         [ #  # ]:          0 :         drawPolyPolygon( rPolyPoly );
    8831                 :            :         return;
    8832                 :            :     }
    8833                 :            : 
    8834                 :            :     // create XObject
    8835 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.push_back( TransparencyEmit() );
                 [ #  # ]
    8836                 :            :     // FIXME: polygons with beziers may yield incorrect bound rect
    8837 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.back().m_aBoundRect     = rPolyPoly.GetBoundRect();
    8838                 :            :     // convert rectangle to default user space
    8839 [ #  # ][ #  # ]:          0 :     m_aPages.back().convertRect( m_aTransparentObjects.back().m_aBoundRect );
                 [ #  # ]
    8840 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.back().m_nObject          = createObject();
    8841 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.back().m_nExtGStateObject = createObject();
    8842         [ #  # ]:          0 :     m_aTransparentObjects.back().m_fAlpha           = (double)(100-nTransparentPercent) / 100.0;
    8843 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.back().m_pContentStream   = new SvMemoryStream( 256, 256 );
                 [ #  # ]
    8844                 :            :     // create XObject's content stream
    8845                 :          0 :     OStringBuffer aContent( 256 );
    8846 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPolyPolygon( rPolyPoly, aContent );
    8847   [ #  #  #  # ]:          0 :     if( m_aCurrentPDFState.m_aLineColor != Color( COL_TRANSPARENT ) &&
         [ #  # ][ #  # ]
    8848         [ #  # ]:          0 :         m_aCurrentPDFState.m_aFillColor != Color( COL_TRANSPARENT ) )
    8849         [ #  # ]:          0 :         aContent.append( " B*\n" );
    8850         [ #  # ]:          0 :     else if( m_aCurrentPDFState.m_aLineColor != Color( COL_TRANSPARENT ) )
    8851         [ #  # ]:          0 :         aContent.append( " S\n" );
    8852                 :            :     else
    8853         [ #  # ]:          0 :         aContent.append( " f*\n" );
    8854 [ #  # ][ #  # ]:          0 :     m_aTransparentObjects.back().m_pContentStream->Write( aContent.getStr(), aContent.getLength() );
    8855                 :            : 
    8856                 :          0 :     OStringBuffer aObjName( 16 );
    8857         [ #  # ]:          0 :     aObjName.append( "Tr" );
    8858 [ #  # ][ #  # ]:          0 :     aObjName.append( m_aTransparentObjects.back().m_nObject );
    8859                 :          0 :     OString aTrName( aObjName.makeStringAndClear() );
    8860         [ #  # ]:          0 :     aObjName.append( "EGS" );
    8861 [ #  # ][ #  # ]:          0 :     aObjName.append( m_aTransparentObjects.back().m_nExtGStateObject );
    8862                 :          0 :     OString aExtName( aObjName.makeStringAndClear() );
    8863                 :            : 
    8864                 :          0 :     OStringBuffer aLine( 80 );
    8865                 :            :     // insert XObject
    8866         [ #  # ]:          0 :     aLine.append( "q /" );
    8867         [ #  # ]:          0 :     aLine.append( aExtName );
    8868         [ #  # ]:          0 :     aLine.append( " gs /" );
    8869         [ #  # ]:          0 :     aLine.append( aTrName );
    8870         [ #  # ]:          0 :     aLine.append( " Do Q\n" );
    8871         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    8872                 :            : 
    8873 [ #  # ][ #  # ]:          0 :     pushResource( ResXObject, aTrName, m_aTransparentObjects.back().m_nObject );
    8874 [ #  # ][ #  # ]:          0 :     pushResource( ResExtGState, aExtName, m_aTransparentObjects.back().m_nExtGStateObject );
    8875                 :            : }
    8876                 :            : 
    8877                 :          0 : void PDFWriterImpl::pushResource( ResourceKind eKind, const OString& rResource, sal_Int32 nObject )
    8878                 :            : {
    8879         [ #  # ]:          0 :     if( nObject >= 0 )
    8880                 :            :     {
    8881   [ #  #  #  #  :          0 :         switch( eKind )
                      # ]
    8882                 :            :         {
    8883                 :            :             case ResXObject:
    8884                 :          0 :                 m_aGlobalResourceDict.m_aXObjects[ rResource ] = nObject;
    8885         [ #  # ]:          0 :                 if( ! m_aOutputStreams.empty() )
    8886                 :          0 :                     m_aOutputStreams.front().m_aResourceDict.m_aXObjects[ rResource ] = nObject;
    8887                 :          0 :                 break;
    8888                 :            :             case ResExtGState:
    8889                 :          0 :                 m_aGlobalResourceDict.m_aExtGStates[ rResource ] = nObject;
    8890         [ #  # ]:          0 :                 if( ! m_aOutputStreams.empty() )
    8891                 :          0 :                     m_aOutputStreams.front().m_aResourceDict.m_aExtGStates[ rResource ] = nObject;
    8892                 :          0 :                 break;
    8893                 :            :             case ResShading:
    8894                 :          0 :                 m_aGlobalResourceDict.m_aShadings[ rResource ] = nObject;
    8895         [ #  # ]:          0 :                 if( ! m_aOutputStreams.empty() )
    8896                 :          0 :                     m_aOutputStreams.front().m_aResourceDict.m_aShadings[ rResource ] = nObject;
    8897                 :          0 :                 break;
    8898                 :            :             case ResPattern:
    8899                 :          0 :                 m_aGlobalResourceDict.m_aPatterns[ rResource ] = nObject;
    8900         [ #  # ]:          0 :                 if( ! m_aOutputStreams.empty() )
    8901                 :          0 :                     m_aOutputStreams.front().m_aResourceDict.m_aPatterns[ rResource ] = nObject;
    8902                 :          0 :                 break;
    8903                 :            :         }
    8904                 :            :     }
    8905                 :          0 : }
    8906                 :            : 
    8907                 :          0 : void PDFWriterImpl::beginRedirect( SvStream* pStream, const Rectangle& rTargetRect )
    8908                 :            : {
    8909                 :          0 :     push( PUSH_ALL );
    8910                 :            : 
    8911                 :            :     // force reemitting clip region
    8912                 :          0 :     clearClipRegion();
    8913                 :          0 :     updateGraphicsState();
    8914                 :            : 
    8915         [ #  # ]:          0 :     m_aOutputStreams.push_front( StreamRedirect() );
    8916                 :          0 :     m_aOutputStreams.front().m_pStream = pStream;
    8917                 :          0 :     m_aOutputStreams.front().m_aMapMode = m_aMapMode;
    8918                 :            : 
    8919         [ #  # ]:          0 :     if( !rTargetRect.IsEmpty() )
    8920                 :            :     {
    8921         [ #  # ]:          0 :         m_aOutputStreams.front().m_aTargetRect =
    8922         [ #  # ]:          0 :             lcl_convert( m_aGraphicsStack.front().m_aMapMode,
    8923                 :            :                          m_aMapMode,
    8924                 :            :                          getReferenceDevice(),
    8925 [ #  # ][ #  # ]:          0 :                          rTargetRect );
    8926 [ #  # ][ #  # ]:          0 :         Point aDelta = m_aOutputStreams.front().m_aTargetRect.BottomLeft();
    8927                 :          0 :         long nPageHeight = pointToPixel(m_aPages[m_nCurrentPage].getHeight());
    8928         [ #  # ]:          0 :         aDelta.Y() = -(nPageHeight - m_aOutputStreams.front().m_aTargetRect.Bottom());
    8929         [ #  # ]:          0 :         m_aMapMode.SetOrigin( m_aMapMode.GetOrigin() + aDelta );
    8930                 :            :     }
    8931                 :            : 
    8932                 :            :     // setup graphics state for independent object stream
    8933                 :            : 
    8934                 :            :     // force reemitting colors
    8935                 :          0 :     m_aCurrentPDFState.m_aLineColor = Color( COL_TRANSPARENT );
    8936                 :          0 :     m_aCurrentPDFState.m_aFillColor = Color( COL_TRANSPARENT );
    8937                 :          0 : }
    8938                 :            : 
    8939                 :          0 : SvStream* PDFWriterImpl::endRedirect()
    8940                 :            : {
    8941                 :          0 :     SvStream* pStream = NULL;
    8942         [ #  # ]:          0 :     if( ! m_aOutputStreams.empty() )
    8943                 :            :     {
    8944                 :          0 :         pStream     = m_aOutputStreams.front().m_pStream;
    8945                 :          0 :         m_aMapMode  = m_aOutputStreams.front().m_aMapMode;
    8946                 :          0 :         m_aOutputStreams.pop_front();
    8947                 :            :     }
    8948                 :            : 
    8949                 :          0 :     pop();
    8950                 :            :     // force reemitting colors and clip region
    8951                 :          0 :     clearClipRegion();
    8952                 :          0 :     m_aCurrentPDFState.m_bClipRegion = m_aGraphicsStack.front().m_bClipRegion;
    8953                 :          0 :     m_aCurrentPDFState.m_aClipRegion = m_aGraphicsStack.front().m_aClipRegion;
    8954                 :          0 :     m_aCurrentPDFState.m_aLineColor = Color( COL_TRANSPARENT );
    8955                 :          0 :     m_aCurrentPDFState.m_aFillColor = Color( COL_TRANSPARENT );
    8956                 :            : 
    8957                 :          0 :     updateGraphicsState();
    8958                 :            : 
    8959                 :          0 :     return pStream;
    8960                 :            : }
    8961                 :            : 
    8962                 :          0 : void PDFWriterImpl::beginTransparencyGroup()
    8963                 :            : {
    8964                 :          0 :     updateGraphicsState();
    8965         [ #  # ]:          0 :     if( m_aContext.Version >= PDFWriter::PDF_1_4 )
    8966 [ #  # ][ #  # ]:          0 :         beginRedirect( new SvMemoryStream( 1024, 1024 ), Rectangle() );
                 [ #  # ]
    8967                 :          0 : }
    8968                 :            : 
    8969                 :          0 : void PDFWriterImpl::endTransparencyGroup( const Rectangle& rBoundingBox, sal_uInt32 nTransparentPercent )
    8970                 :            : {
    8971                 :            :     DBG_ASSERT( nTransparentPercent <= 100, "invalid alpha value" );
    8972                 :          0 :     nTransparentPercent = nTransparentPercent % 100;
    8973                 :            : 
    8974         [ #  # ]:          0 :     if( m_aContext.Version >= PDFWriter::PDF_1_4 )
    8975                 :            :     {
    8976                 :            :         // create XObject
    8977 [ #  # ][ #  # ]:          0 :         m_aTransparentObjects.push_back( TransparencyEmit() );
                 [ #  # ]
    8978         [ #  # ]:          0 :         m_aTransparentObjects.back().m_aBoundRect   = rBoundingBox;
    8979                 :            :         // convert rectangle to default user space
    8980 [ #  # ][ #  # ]:          0 :         m_aPages.back().convertRect( m_aTransparentObjects.back().m_aBoundRect );
                 [ #  # ]
    8981 [ #  # ][ #  # ]:          0 :         m_aTransparentObjects.back().m_nObject      = createObject();
    8982         [ #  # ]:          0 :         m_aTransparentObjects.back().m_fAlpha       = (double)(100-nTransparentPercent) / 100.0;
    8983                 :            :         // get XObject's content stream
    8984 [ #  # ][ #  # ]:          0 :         m_aTransparentObjects.back().m_pContentStream = static_cast<SvMemoryStream*>(endRedirect());
    8985 [ #  # ][ #  # ]:          0 :         m_aTransparentObjects.back().m_nExtGStateObject = createObject();
    8986                 :            : 
    8987                 :          0 :         OStringBuffer aObjName( 16 );
    8988         [ #  # ]:          0 :         aObjName.append( "Tr" );
    8989 [ #  # ][ #  # ]:          0 :         aObjName.append( m_aTransparentObjects.back().m_nObject );
    8990                 :          0 :         OString aTrName( aObjName.makeStringAndClear() );
    8991         [ #  # ]:          0 :         aObjName.append( "EGS" );
    8992 [ #  # ][ #  # ]:          0 :         aObjName.append( m_aTransparentObjects.back().m_nExtGStateObject );
    8993                 :          0 :         OString aExtName( aObjName.makeStringAndClear() );
    8994                 :            : 
    8995                 :          0 :         OStringBuffer aLine( 80 );
    8996                 :            :         // insert XObject
    8997         [ #  # ]:          0 :         aLine.append( "q /" );
    8998         [ #  # ]:          0 :         aLine.append( aExtName );
    8999         [ #  # ]:          0 :         aLine.append( " gs /" );
    9000         [ #  # ]:          0 :         aLine.append( aTrName );
    9001         [ #  # ]:          0 :         aLine.append( " Do Q\n" );
    9002         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
    9003                 :            : 
    9004 [ #  # ][ #  # ]:          0 :         pushResource( ResXObject, aTrName, m_aTransparentObjects.back().m_nObject );
    9005 [ #  # ][ #  # ]:          0 :         pushResource( ResExtGState, aExtName, m_aTransparentObjects.back().m_nExtGStateObject );
    9006                 :            :     }
    9007                 :          0 : }
    9008                 :            : 
    9009                 :          0 : void PDFWriterImpl::drawRectangle( const Rectangle& rRect )
    9010                 :            : {
    9011         [ #  # ]:          0 :     MARK( "drawRectangle" );
    9012                 :            : 
    9013         [ #  # ]:          0 :     updateGraphicsState();
    9014                 :            : 
    9015         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9016 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9017                 :          0 :         return;
    9018                 :            : 
    9019                 :          0 :     OStringBuffer aLine( 40 );
    9020 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendRect( rRect, aLine );
    9021                 :            : 
    9022         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9023 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9024         [ #  # ]:          0 :         aLine.append( " B*\n" );
    9025 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    9026         [ #  # ]:          0 :         aLine.append( " S\n" );
    9027                 :            :     else
    9028         [ #  # ]:          0 :         aLine.append( " f*\n" );
    9029                 :            : 
    9030         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9031                 :            : }
    9032                 :            : 
    9033                 :          0 : void PDFWriterImpl::drawRectangle( const Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound )
    9034                 :            : {
    9035         [ #  # ]:          0 :     MARK( "drawRectangle with rounded edges" );
    9036                 :            : 
    9037 [ #  # ][ #  # ]:          0 :     if( !nHorzRound && !nVertRound )
    9038         [ #  # ]:          0 :         drawRectangle( rRect );
    9039                 :            : 
    9040         [ #  # ]:          0 :     updateGraphicsState();
    9041                 :            : 
    9042         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9043 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9044                 :          0 :         return;
    9045                 :            : 
    9046 [ #  # ][ #  # ]:          0 :     if( nHorzRound > (sal_uInt32)rRect.GetWidth()/2 )
    9047         [ #  # ]:          0 :         nHorzRound = rRect.GetWidth()/2;
    9048 [ #  # ][ #  # ]:          0 :     if( nVertRound > (sal_uInt32)rRect.GetHeight()/2 )
    9049         [ #  # ]:          0 :         nVertRound = rRect.GetHeight()/2;
    9050                 :            : 
    9051         [ #  # ]:          0 :     Point aPoints[16];
    9052                 :          0 :     const double kappa = 0.5522847498;
    9053                 :          0 :     const sal_uInt32 kx = (sal_uInt32)((kappa*(double)nHorzRound)+0.5);
    9054                 :          0 :     const sal_uInt32 ky = (sal_uInt32)((kappa*(double)nVertRound)+0.5);
    9055                 :            : 
    9056                 :          0 :     aPoints[1]  = Point( rRect.TopLeft().X() + nHorzRound, rRect.TopLeft().Y() );
    9057                 :          0 :     aPoints[0]  = Point( aPoints[1].X() - kx, aPoints[1].Y() );
    9058         [ #  # ]:          0 :     aPoints[2]  = Point( rRect.TopRight().X()+1 - nHorzRound, aPoints[1].Y() );
    9059                 :          0 :     aPoints[3]  = Point( aPoints[2].X()+kx, aPoints[2].Y() );
    9060                 :            : 
    9061 [ #  # ][ #  # ]:          0 :     aPoints[5]  = Point( rRect.TopRight().X()+1, rRect.TopRight().Y()+nVertRound );
    9062                 :          0 :     aPoints[4]  = Point( aPoints[5].X(), aPoints[5].Y()-ky );
    9063         [ #  # ]:          0 :     aPoints[6]  = Point( aPoints[5].X(), rRect.BottomRight().Y()+1 - nVertRound );
    9064                 :          0 :     aPoints[7]  = Point( aPoints[6].X(), aPoints[6].Y()+ky );
    9065                 :            : 
    9066 [ #  # ][ #  # ]:          0 :     aPoints[9]  = Point( rRect.BottomRight().X()+1-nHorzRound, rRect.BottomRight().Y()+1 );
    9067                 :          0 :     aPoints[8]  = Point( aPoints[9].X()+kx, aPoints[9].Y() );
    9068         [ #  # ]:          0 :     aPoints[10] = Point( rRect.BottomLeft().X() + nHorzRound, aPoints[9].Y() );
    9069                 :          0 :     aPoints[11] = Point( aPoints[10].X()-kx, aPoints[10].Y() );
    9070                 :            : 
    9071 [ #  # ][ #  # ]:          0 :     aPoints[13] = Point( rRect.BottomLeft().X(), rRect.BottomLeft().Y()+1-nVertRound );
    9072                 :          0 :     aPoints[12] = Point( aPoints[13].X(), aPoints[13].Y()+ky );
    9073                 :          0 :     aPoints[14] = Point( rRect.TopLeft().X(), rRect.TopLeft().Y()+nVertRound );
    9074                 :          0 :     aPoints[15] = Point( aPoints[14].X(), aPoints[14].Y()-ky );
    9075                 :            : 
    9076                 :            : 
    9077                 :          0 :     OStringBuffer aLine( 80 );
    9078 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[1], aLine );
    9079         [ #  # ]:          0 :     aLine.append( " m " );
    9080 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[2], aLine );
    9081         [ #  # ]:          0 :     aLine.append( " l " );
    9082 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[3], aLine );
    9083         [ #  # ]:          0 :     aLine.append( ' ' );
    9084 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[4], aLine );
    9085         [ #  # ]:          0 :     aLine.append( ' ' );
    9086 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[5], aLine );
    9087         [ #  # ]:          0 :     aLine.append( " c\n" );
    9088 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[6], aLine );
    9089         [ #  # ]:          0 :     aLine.append( " l " );
    9090 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[7], aLine );
    9091         [ #  # ]:          0 :     aLine.append( ' ' );
    9092 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[8], aLine );
    9093         [ #  # ]:          0 :     aLine.append( ' ' );
    9094 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[9], aLine );
    9095         [ #  # ]:          0 :     aLine.append( " c\n" );
    9096 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[10], aLine );
    9097         [ #  # ]:          0 :     aLine.append( " l " );
    9098 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[11], aLine );
    9099         [ #  # ]:          0 :     aLine.append( ' ' );
    9100 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[12], aLine );
    9101         [ #  # ]:          0 :     aLine.append( ' ' );
    9102 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[13], aLine );
    9103         [ #  # ]:          0 :     aLine.append( " c\n" );
    9104 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[14], aLine );
    9105         [ #  # ]:          0 :     aLine.append( " l " );
    9106 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[15], aLine );
    9107         [ #  # ]:          0 :     aLine.append( ' ' );
    9108 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[0], aLine );
    9109         [ #  # ]:          0 :     aLine.append( ' ' );
    9110 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[1], aLine );
    9111         [ #  # ]:          0 :     aLine.append( " c " );
    9112                 :            : 
    9113         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9114 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9115         [ #  # ]:          0 :         aLine.append( "b*\n" );
    9116 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    9117         [ #  # ]:          0 :         aLine.append( "s\n" );
    9118                 :            :     else
    9119         [ #  # ]:          0 :         aLine.append( "f*\n" );
    9120                 :            : 
    9121         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9122                 :            : }
    9123                 :            : 
    9124                 :          0 : void PDFWriterImpl::drawEllipse( const Rectangle& rRect )
    9125                 :            : {
    9126         [ #  # ]:          0 :     MARK( "drawEllipse" );
    9127                 :            : 
    9128         [ #  # ]:          0 :     updateGraphicsState();
    9129                 :            : 
    9130         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9131 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9132                 :          0 :         return;
    9133                 :            : 
    9134         [ #  # ]:          0 :     Point aPoints[12];
    9135                 :          0 :     const double kappa = 0.5522847498;
    9136         [ #  # ]:          0 :     const sal_uInt32 kx = (sal_uInt32)((kappa*(double)rRect.GetWidth()/2.0)+0.5);
    9137         [ #  # ]:          0 :     const sal_uInt32 ky = (sal_uInt32)((kappa*(double)rRect.GetHeight()/2.0)+0.5);
    9138                 :            : 
    9139         [ #  # ]:          0 :     aPoints[1]  = Point( rRect.TopLeft().X() + rRect.GetWidth()/2, rRect.TopLeft().Y() );
    9140                 :          0 :     aPoints[0]  = Point( aPoints[1].X() - kx, aPoints[1].Y() );
    9141                 :          0 :     aPoints[2]  = Point( aPoints[1].X() + kx, aPoints[1].Y() );
    9142                 :            : 
    9143 [ #  # ][ #  # ]:          0 :     aPoints[4]  = Point( rRect.TopRight().X()+1, rRect.TopRight().Y() + rRect.GetHeight()/2 );
                 [ #  # ]
    9144                 :          0 :     aPoints[3]  = Point( aPoints[4].X(), aPoints[4].Y() - ky );
    9145                 :          0 :     aPoints[5]  = Point( aPoints[4].X(), aPoints[4].Y() + ky );
    9146                 :            : 
    9147 [ #  # ][ #  # ]:          0 :     aPoints[7]  = Point( rRect.BottomLeft().X() + rRect.GetWidth()/2, rRect.BottomLeft().Y()+1 );
                 [ #  # ]
    9148                 :          0 :     aPoints[6]  = Point( aPoints[7].X() + kx, aPoints[7].Y() );
    9149                 :          0 :     aPoints[8]  = Point( aPoints[7].X() - kx, aPoints[7].Y() );
    9150                 :            : 
    9151         [ #  # ]:          0 :     aPoints[10] = Point( rRect.TopLeft().X(), rRect.TopLeft().Y() + rRect.GetHeight()/2 );
    9152                 :          0 :     aPoints[9]  = Point( aPoints[10].X(), aPoints[10].Y() + ky );
    9153                 :          0 :     aPoints[11] = Point( aPoints[10].X(), aPoints[10].Y() - ky );
    9154                 :            : 
    9155                 :          0 :     OStringBuffer aLine( 80 );
    9156 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[1], aLine );
    9157         [ #  # ]:          0 :     aLine.append( " m " );
    9158 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[2], aLine );
    9159         [ #  # ]:          0 :     aLine.append( ' ' );
    9160 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[3], aLine );
    9161         [ #  # ]:          0 :     aLine.append( ' ' );
    9162 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[4], aLine );
    9163         [ #  # ]:          0 :     aLine.append( " c\n" );
    9164 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[5], aLine );
    9165         [ #  # ]:          0 :     aLine.append( ' ' );
    9166 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[6], aLine );
    9167         [ #  # ]:          0 :     aLine.append( ' ' );
    9168 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[7], aLine );
    9169         [ #  # ]:          0 :     aLine.append( " c\n" );
    9170 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[8], aLine );
    9171         [ #  # ]:          0 :     aLine.append( ' ' );
    9172 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[9], aLine );
    9173         [ #  # ]:          0 :     aLine.append( ' ' );
    9174 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[10], aLine );
    9175         [ #  # ]:          0 :     aLine.append( " c\n" );
    9176 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[11], aLine );
    9177         [ #  # ]:          0 :     aLine.append( ' ' );
    9178 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[0], aLine );
    9179         [ #  # ]:          0 :     aLine.append( ' ' );
    9180 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoints[1], aLine );
    9181         [ #  # ]:          0 :     aLine.append( " c " );
    9182                 :            : 
    9183         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9184 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9185         [ #  # ]:          0 :         aLine.append( "b*\n" );
    9186 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    9187         [ #  # ]:          0 :         aLine.append( "s\n" );
    9188                 :            :     else
    9189         [ #  # ]:          0 :         aLine.append( "f*\n" );
    9190                 :            : 
    9191         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9192                 :            : }
    9193                 :            : 
    9194                 :          0 : static double calcAngle( const Rectangle& rRect, const Point& rPoint )
    9195                 :            : {
    9196                 :          0 :     Point aOrigin((rRect.Left()+rRect.Right()+1)/2,
    9197                 :          0 :                   (rRect.Top()+rRect.Bottom()+1)/2);
    9198                 :          0 :     Point aPoint = rPoint - aOrigin;
    9199                 :            : 
    9200                 :          0 :     double fX = (double)aPoint.X();
    9201                 :          0 :     double fY = (double)-aPoint.Y();
    9202                 :            : 
    9203 [ #  # ][ #  # ]:          0 :     if( rRect.GetWidth() > rRect.GetHeight() )
                 [ #  # ]
    9204 [ #  # ][ #  # ]:          0 :         fY = fY*((double)rRect.GetWidth()/(double)rRect.GetHeight());
    9205 [ #  # ][ #  # ]:          0 :     else if( rRect.GetHeight() > rRect.GetWidth() )
                 [ #  # ]
    9206 [ #  # ][ #  # ]:          0 :         fX = fX*((double)rRect.GetHeight()/(double)rRect.GetWidth());
    9207                 :          0 :     return atan2( fY, fX );
    9208                 :            : }
    9209                 :            : 
    9210                 :          0 : void PDFWriterImpl::drawArc( const Rectangle& rRect, const Point& rStart, const Point& rStop, bool bWithPie, bool bWithChord )
    9211                 :            : {
    9212         [ #  # ]:          0 :     MARK( "drawArc" );
    9213                 :            : 
    9214         [ #  # ]:          0 :     updateGraphicsState();
    9215                 :            : 
    9216         [ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9217 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor == Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9218                 :          0 :         return;
    9219                 :            : 
    9220                 :            :     // calculate start and stop angles
    9221         [ #  # ]:          0 :     const double fStartAngle = calcAngle( rRect, rStart );
    9222         [ #  # ]:          0 :     double fStopAngle  = calcAngle( rRect, rStop );
    9223         [ #  # ]:          0 :     while( fStopAngle < fStartAngle )
    9224                 :          0 :         fStopAngle += 2.0*M_PI;
    9225                 :          0 :     const int nFragments = (int)((fStopAngle-fStartAngle)/(M_PI/2.0))+1;
    9226                 :          0 :     const double fFragmentDelta = (fStopAngle-fStartAngle)/(double)nFragments;
    9227                 :          0 :     const double kappa = fabs( 4.0 * (1.0-cos(fFragmentDelta/2.0))/sin(fFragmentDelta/2.0) / 3.0);
    9228         [ #  # ]:          0 :     const double halfWidth = (double)rRect.GetWidth()/2.0;
    9229         [ #  # ]:          0 :     const double halfHeight = (double)rRect.GetHeight()/2.0;
    9230                 :            : 
    9231                 :          0 :     const Point aCenter( (rRect.Left()+rRect.Right()+1)/2,
    9232                 :          0 :                          (rRect.Top()+rRect.Bottom()+1)/2 );
    9233                 :            : 
    9234                 :          0 :     OStringBuffer aLine( 30*nFragments );
    9235                 :          0 :     Point aPoint( (int)(halfWidth * cos(fStartAngle) ),
    9236                 :          0 :                   -(int)(halfHeight * sin(fStartAngle) ) );
    9237                 :          0 :     aPoint += aCenter;
    9238 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aPoint, aLine );
    9239         [ #  # ]:          0 :     aLine.append( " m " );
    9240         [ #  # ]:          0 :     if( !basegfx::fTools::equal(fStartAngle, fStopAngle) )
    9241                 :            :     {
    9242         [ #  # ]:          0 :         for( int i = 0; i < nFragments; i++ )
    9243                 :            :         {
    9244                 :          0 :             const double fStartFragment = fStartAngle + (double)i*fFragmentDelta;
    9245                 :          0 :             const double fStopFragment = fStartFragment + fFragmentDelta;
    9246                 :          0 :             aPoint = Point( (int)(halfWidth * (cos(fStartFragment) - kappa*sin(fStartFragment) ) ),
    9247                 :          0 :                             -(int)(halfHeight * (sin(fStartFragment) + kappa*cos(fStartFragment) ) ) );
    9248                 :          0 :             aPoint += aCenter;
    9249 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendPoint( aPoint, aLine );
    9250         [ #  # ]:          0 :             aLine.append( ' ' );
    9251                 :            : 
    9252                 :          0 :             aPoint = Point( (int)(halfWidth * (cos(fStopFragment) + kappa*sin(fStopFragment) ) ),
    9253                 :          0 :                             -(int)(halfHeight * (sin(fStopFragment) - kappa*cos(fStopFragment) ) ) );
    9254                 :          0 :             aPoint += aCenter;
    9255 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendPoint( aPoint, aLine );
    9256         [ #  # ]:          0 :             aLine.append( ' ' );
    9257                 :            : 
    9258                 :          0 :             aPoint = Point( (int)(halfWidth * cos(fStopFragment) ),
    9259                 :          0 :                             -(int)(halfHeight * sin(fStopFragment) ) );
    9260                 :          0 :             aPoint += aCenter;
    9261 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendPoint( aPoint, aLine );
    9262         [ #  # ]:          0 :             aLine.append( " c\n" );
    9263                 :            :         }
    9264                 :            :     }
    9265 [ #  # ][ #  # ]:          0 :     if( bWithChord || bWithPie )
    9266                 :            :     {
    9267         [ #  # ]:          0 :         if( bWithPie )
    9268                 :            :         {
    9269 [ #  # ][ #  # ]:          0 :             m_aPages.back().appendPoint( aCenter, aLine );
    9270         [ #  # ]:          0 :             aLine.append( " l " );
    9271                 :            :         }
    9272         [ #  # ]:          0 :         aLine.append( "h " );
    9273                 :            :     }
    9274 [ #  # ][ #  # ]:          0 :     if( ! bWithChord && ! bWithPie )
    9275         [ #  # ]:          0 :         aLine.append( "S\n" );
    9276         [ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) &&
           [ #  #  #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    9277 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aFillColor != Color( COL_TRANSPARENT ) )
                 [ #  # ]
    9278         [ #  # ]:          0 :         aLine.append( "B*\n" );
    9279 [ #  # ][ #  # ]:          0 :     else if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
    9280         [ #  # ]:          0 :         aLine.append( "S\n" );
    9281                 :            :     else
    9282         [ #  # ]:          0 :         aLine.append( "f*\n" );
    9283                 :            : 
    9284         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9285                 :            : }
    9286                 :            : 
    9287                 :          0 : void PDFWriterImpl::drawPolyLine( const Polygon& rPoly )
    9288                 :            : {
    9289         [ #  # ]:          0 :     MARK( "drawPolyLine" );
    9290                 :            : 
    9291         [ #  # ]:          0 :     sal_uInt16 nPoints = rPoly.GetSize();
    9292         [ #  # ]:          0 :     if( nPoints < 2 )
    9293                 :            :         return;
    9294                 :            : 
    9295         [ #  # ]:          0 :     updateGraphicsState();
    9296                 :            : 
    9297 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) )
    9298                 :            :         return;
    9299                 :            : 
    9300                 :          0 :     OStringBuffer aLine( 20 * nPoints );
    9301 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPolygon( rPoly, aLine, rPoly[0] == rPoly[nPoints-1] );
         [ #  # ][ #  # ]
    9302         [ #  # ]:          0 :     aLine.append( "S\n" );
    9303                 :            : 
    9304         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9305                 :            : }
    9306                 :            : 
    9307                 :          0 : void PDFWriterImpl::drawPolyLine( const Polygon& rPoly, const LineInfo& rInfo )
    9308                 :            : {
    9309         [ #  # ]:          0 :     MARK( "drawPolyLine with LineInfo" );
    9310                 :            : 
    9311         [ #  # ]:          0 :     updateGraphicsState();
    9312                 :            : 
    9313 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) )
    9314                 :          0 :         return;
    9315                 :            : 
    9316                 :          0 :     OStringBuffer aLine;
    9317         [ #  # ]:          0 :     aLine.append( "q " );
    9318 [ #  # ][ #  # ]:          0 :     if( m_aPages.back().appendLineInfo( rInfo, aLine ) )
                 [ #  # ]
    9319                 :            :     {
    9320         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
    9321         [ #  # ]:          0 :         drawPolyLine( rPoly );
    9322         [ #  # ]:          0 :         writeBuffer( "Q\n", 2 );
    9323                 :            :     }
    9324                 :            :     else
    9325                 :            :     {
    9326         [ #  # ]:          0 :         PDFWriter::ExtLineInfo aInfo;
    9327         [ #  # ]:          0 :         convertLineInfoToExtLineInfo( rInfo, aInfo );
    9328         [ #  # ]:          0 :         drawPolyLine( rPoly, aInfo );
    9329                 :          0 :     }
    9330                 :            : }
    9331                 :            : 
    9332                 :          0 : void PDFWriterImpl::convertLineInfoToExtLineInfo( const LineInfo& rIn, PDFWriter::ExtLineInfo& rOut )
    9333                 :            : {
    9334                 :            :     DBG_ASSERT( rIn.GetStyle() == LINE_DASH, "invalid conversion" );
    9335                 :          0 :     rOut.m_fLineWidth           = rIn.GetWidth();
    9336                 :          0 :     rOut.m_fTransparency        = 0.0;
    9337                 :          0 :     rOut.m_eCap                 = PDFWriter::capButt;
    9338                 :          0 :     rOut.m_eJoin                = PDFWriter::joinMiter;
    9339                 :          0 :     rOut.m_fMiterLimit          = 10;
    9340                 :          0 :     rOut.m_aDashArray.clear();
    9341                 :            : 
    9342                 :          0 :     int nDashes     = rIn.GetDashCount();
    9343                 :          0 :     int nDashLen    = rIn.GetDashLen();
    9344                 :          0 :     int nDistance   = rIn.GetDistance();
    9345         [ #  # ]:          0 :     for( int n  = 0; n < nDashes; n++ )
    9346                 :            :     {
    9347         [ #  # ]:          0 :         rOut.m_aDashArray.push_back( nDashLen );
    9348         [ #  # ]:          0 :         rOut.m_aDashArray.push_back( nDistance );
    9349                 :            :     }
    9350                 :          0 :     int nDots       = rIn.GetDotCount();
    9351                 :          0 :     int nDotLen     = rIn.GetDotLen();
    9352         [ #  # ]:          0 :     for( int n  = 0; n < nDots; n++ )
    9353                 :            :     {
    9354         [ #  # ]:          0 :         rOut.m_aDashArray.push_back( nDotLen );
    9355         [ #  # ]:          0 :         rOut.m_aDashArray.push_back( nDistance );
    9356                 :            :     }
    9357                 :          0 : }
    9358                 :            : 
    9359                 :          0 : void PDFWriterImpl::drawPolyLine( const Polygon& rPoly, const PDFWriter::ExtLineInfo& rInfo )
    9360                 :            : {
    9361         [ #  # ]:          0 :     MARK( "drawPolyLine with ExtLineInfo" );
    9362                 :            : 
    9363         [ #  # ]:          0 :     updateGraphicsState();
    9364                 :            : 
    9365 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor == Color( COL_TRANSPARENT ) )
    9366                 :            :         return;
    9367                 :            : 
    9368         [ #  # ]:          0 :     if( rInfo.m_fTransparency >= 1.0 )
    9369                 :            :         return;
    9370                 :            : 
    9371         [ #  # ]:          0 :     if( rInfo.m_fTransparency != 0.0 )
    9372         [ #  # ]:          0 :         beginTransparencyGroup();
    9373                 :            : 
    9374                 :          0 :     OStringBuffer aLine;
    9375         [ #  # ]:          0 :     aLine.append( "q " );
    9376 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( rInfo.m_fLineWidth, aLine );
    9377         [ #  # ]:          0 :     aLine.append( " w" );
    9378         [ #  # ]:          0 :     if( rInfo.m_aDashArray.size() < 10 ) // implmentation limit of acrobat reader
    9379                 :            :     {
    9380      [ #  #  # ]:          0 :         switch( rInfo.m_eCap )
    9381                 :            :         {
    9382                 :            :             default:
    9383         [ #  # ]:          0 :             case PDFWriter::capButt:   aLine.append( " 0 J" );break;
    9384         [ #  # ]:          0 :             case PDFWriter::capRound:  aLine.append( " 1 J" );break;
    9385         [ #  # ]:          0 :             case PDFWriter::capSquare: aLine.append( " 2 J" );break;
    9386                 :            :         }
    9387      [ #  #  # ]:          0 :         switch( rInfo.m_eJoin )
    9388                 :            :         {
    9389                 :            :             default:
    9390                 :            :             case PDFWriter::joinMiter:
    9391                 :            :             {
    9392                 :          0 :                 double fLimit = rInfo.m_fMiterLimit;
    9393         [ #  # ]:          0 :                 if( rInfo.m_fLineWidth < rInfo.m_fMiterLimit )
    9394                 :          0 :                     fLimit = fLimit / rInfo.m_fLineWidth;
    9395         [ #  # ]:          0 :                 if( fLimit < 1.0 )
    9396                 :          0 :                     fLimit = 1.0;
    9397         [ #  # ]:          0 :                 aLine.append( " 0 j " );
    9398         [ #  # ]:          0 :                 appendDouble( fLimit, aLine );
    9399         [ #  # ]:          0 :                 aLine.append( " M" );
    9400                 :            :             }
    9401                 :          0 :             break;
    9402         [ #  # ]:          0 :             case PDFWriter::joinRound:  aLine.append( " 1 j" );break;
    9403         [ #  # ]:          0 :             case PDFWriter::joinBevel:  aLine.append( " 2 j" );break;
    9404                 :            :         }
    9405         [ #  # ]:          0 :         if( rInfo.m_aDashArray.size() > 0 )
    9406                 :            :         {
    9407         [ #  # ]:          0 :             aLine.append( " [ " );
    9408   [ #  #  #  # ]:          0 :             for( std::vector<double>::const_iterator it = rInfo.m_aDashArray.begin();
                 [ #  # ]
    9409                 :          0 :                  it != rInfo.m_aDashArray.end(); ++it )
    9410                 :            :             {
    9411 [ #  # ][ #  # ]:          0 :                 m_aPages.back().appendMappedLength( *it, aLine );
                 [ #  # ]
    9412         [ #  # ]:          0 :                 aLine.append( ' ' );
    9413                 :            :             }
    9414         [ #  # ]:          0 :             aLine.append( "] 0 d" );
    9415                 :            :         }
    9416         [ #  # ]:          0 :         aLine.append( "\n" );
    9417         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
    9418         [ #  # ]:          0 :         drawPolyLine( rPoly );
    9419                 :            :     }
    9420                 :            :     else
    9421                 :            :     {
    9422         [ #  # ]:          0 :         basegfx::B2DPolygon aPoly(rPoly.getB2DPolygon());
    9423         [ #  # ]:          0 :         basegfx::B2DPolyPolygon aPolyPoly;
    9424                 :            : 
    9425         [ #  # ]:          0 :         basegfx::tools::applyLineDashing(aPoly, rInfo.m_aDashArray, &aPolyPoly);
    9426                 :            : 
    9427                 :            :         // Old applyLineDashing subdivided the polygon. New one will create bezier curve segments.
    9428                 :            :         // To mimic old behaviour, apply subdivide here. If beziers shall be written (better quality)
    9429                 :            :         // this line needs to be removed and the loop below adapted accordingly
    9430 [ #  # ][ #  # ]:          0 :         aPolyPoly = basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly);
                 [ #  # ]
    9431                 :            : 
    9432         [ #  # ]:          0 :         const sal_uInt32 nPolygonCount(aPolyPoly.count());
    9433                 :            : 
    9434         [ #  # ]:          0 :         for( sal_uInt32 nPoly = 0; nPoly < nPolygonCount; nPoly++ )
    9435                 :            :         {
    9436 [ #  # ][ #  # ]:          0 :             aLine.append( (nPoly != 0 && (nPoly & 7) == 0) ? "\n" : " " );
                 [ #  # ]
    9437 [ #  # ][ #  # ]:          0 :             aPoly = aPolyPoly.getB2DPolygon( nPoly );
                 [ #  # ]
    9438         [ #  # ]:          0 :             const sal_uInt32 nPointCount(aPoly.count());
    9439                 :            : 
    9440         [ #  # ]:          0 :             if(nPointCount)
    9441                 :            :             {
    9442 [ #  # ][ #  # ]:          0 :                 const sal_uInt32 nEdgeCount(aPoly.isClosed() ? nPointCount : nPointCount - 1);
    9443         [ #  # ]:          0 :                 basegfx::B2DPoint aCurrent(aPoly.getB2DPoint(0));
    9444                 :            : 
    9445         [ #  # ]:          0 :                 for(sal_uInt32 a(0); a < nEdgeCount; a++)
    9446                 :            :                 {
    9447         [ #  # ]:          0 :                     if( a > 0 )
    9448         [ #  # ]:          0 :                         aLine.append( " " );
    9449                 :          0 :                     const sal_uInt32 nNextIndex((a + 1) % nPointCount);
    9450         [ #  # ]:          0 :                     const basegfx::B2DPoint aNext(aPoly.getB2DPoint(nNextIndex));
    9451                 :            : 
    9452         [ #  # ]:          0 :                     m_aPages.back().appendPoint( Point( FRound(aCurrent.getX()),
    9453                 :            :                                                         FRound(aCurrent.getY()) ),
    9454         [ #  # ]:          0 :                                                  aLine );
    9455         [ #  # ]:          0 :                     aLine.append( " m " );
    9456         [ #  # ]:          0 :                     m_aPages.back().appendPoint( Point( FRound(aNext.getX()),
    9457                 :            :                                                         FRound(aNext.getY()) ),
    9458         [ #  # ]:          0 :                                                  aLine );
    9459         [ #  # ]:          0 :                     aLine.append( " l" );
    9460                 :            : 
    9461                 :            :                     // prepare next edge
    9462                 :          0 :                     aCurrent = aNext;
    9463                 :          0 :                 }
    9464                 :            :             }
    9465                 :            :         }
    9466         [ #  # ]:          0 :         aLine.append( " S " );
    9467 [ #  # ][ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
                 [ #  # ]
    9468                 :            :     }
    9469         [ #  # ]:          0 :     writeBuffer( "Q\n", 2 );
    9470                 :            : 
    9471         [ #  # ]:          0 :     if( rInfo.m_fTransparency != 0.0 )
    9472                 :            :     {
    9473                 :            :         // FIXME: actually this may be incorrect with bezier polygons
    9474         [ #  # ]:          0 :         Rectangle aBoundRect( rPoly.GetBoundRect() );
    9475                 :            :         // avoid clipping with thick lines
    9476         [ #  # ]:          0 :         if( rInfo.m_fLineWidth > 0.0 )
    9477                 :            :         {
    9478                 :          0 :             sal_Int32 nLW = sal_Int32(rInfo.m_fLineWidth);
    9479                 :          0 :             aBoundRect.Top()    -= nLW;
    9480                 :          0 :             aBoundRect.Left()   -= nLW;
    9481                 :          0 :             aBoundRect.Right()  += nLW;
    9482                 :          0 :             aBoundRect.Bottom() += nLW;
    9483                 :            :         }
    9484         [ #  # ]:          0 :         endTransparencyGroup( aBoundRect, (sal_uInt16)(100.0*rInfo.m_fTransparency) );
    9485                 :          0 :     }
    9486                 :            : }
    9487                 :            : 
    9488                 :          0 : void PDFWriterImpl::drawPixel( const Point& rPoint, const Color& rColor )
    9489                 :            : {
    9490         [ #  # ]:          0 :     MARK( "drawPixel" );
    9491                 :            : 
    9492 [ #  # ][ #  # ]:          0 :     Color aColor = ( rColor == Color( COL_TRANSPARENT ) ? m_aGraphicsStack.front().m_aLineColor : rColor );
    9493                 :            : 
    9494         [ #  # ]:          0 :     if( aColor == Color( COL_TRANSPARENT ) )
    9495                 :          0 :         return;
    9496                 :            : 
    9497                 :            :     // pixels are drawn in line color, so have to set
    9498                 :            :     // the nonstroking color to line color
    9499         [ #  # ]:          0 :     Color aOldFillColor = m_aGraphicsStack.front().m_aFillColor;
    9500         [ #  # ]:          0 :     setFillColor( aColor );
    9501                 :            : 
    9502         [ #  # ]:          0 :     updateGraphicsState();
    9503                 :            : 
    9504                 :          0 :     OStringBuffer aLine( 20 );
    9505 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( rPoint, aLine );
    9506         [ #  # ]:          0 :     aLine.append( ' ' );
    9507 [ #  # ][ #  # ]:          0 :     appendDouble( 1.0/double(getReferenceDevice()->ImplGetDPIX()), aLine );
    9508         [ #  # ]:          0 :     aLine.append( ' ' );
    9509 [ #  # ][ #  # ]:          0 :     appendDouble( 1.0/double(getReferenceDevice()->ImplGetDPIY()), aLine );
    9510         [ #  # ]:          0 :     aLine.append( " re f\n" );
    9511         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
    9512                 :            : 
    9513         [ #  # ]:          0 :     setFillColor( aOldFillColor );
    9514                 :            : }
    9515                 :            : 
    9516                 :            : class AccessReleaser
    9517                 :            : {
    9518                 :            :     BitmapReadAccess* m_pAccess;
    9519                 :            : public:
    9520                 :          0 :     AccessReleaser( BitmapReadAccess* pAccess ) : m_pAccess( pAccess ){}
    9521         [ #  # ]:          0 :     ~AccessReleaser() { delete m_pAccess; }
    9522                 :            : };
    9523                 :            : 
    9524                 :          0 : bool PDFWriterImpl::writeTransparentObject( TransparencyEmit& rObject )
    9525                 :            : {
    9526 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nObject ) );
    9527                 :            : 
    9528         [ #  # ]:          0 :     bool bFlateFilter = compressStream( rObject.m_pContentStream );
    9529         [ #  # ]:          0 :     rObject.m_pContentStream->Seek( STREAM_SEEK_TO_END );
    9530                 :          0 :     sal_uLong nSize = rObject.m_pContentStream->Tell();
    9531         [ #  # ]:          0 :     rObject.m_pContentStream->Seek( STREAM_SEEK_TO_BEGIN );
    9532                 :            :     #if OSL_DEBUG_LEVEL > 1
    9533                 :            :     emitComment( "PDFWriterImpl::writeTransparentObject" );
    9534                 :            :     #endif
    9535                 :          0 :     OStringBuffer aLine( 512 );
    9536 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nObject ) );
    9537         [ #  # ]:          0 :     aLine.append( rObject.m_nObject );
    9538                 :            :     aLine.append( " 0 obj\n"
    9539                 :            :                   "<</Type/XObject\n"
    9540                 :            :                   "/Subtype/Form\n"
    9541         [ #  # ]:          0 :                   "/BBox[ " );
    9542         [ #  # ]:          0 :     appendFixedInt( rObject.m_aBoundRect.Left(), aLine );
    9543         [ #  # ]:          0 :     aLine.append( ' ' );
    9544         [ #  # ]:          0 :     appendFixedInt( rObject.m_aBoundRect.Top(), aLine );
    9545         [ #  # ]:          0 :     aLine.append( ' ' );
    9546         [ #  # ]:          0 :     appendFixedInt( rObject.m_aBoundRect.Right(), aLine );
    9547         [ #  # ]:          0 :     aLine.append( ' ' );
    9548         [ #  # ]:          0 :     appendFixedInt( rObject.m_aBoundRect.Bottom()+1, aLine );
    9549         [ #  # ]:          0 :     aLine.append( " ]\n" );
    9550         [ #  # ]:          0 :     if( ! rObject.m_pSoftMaskStream )
    9551                 :            :     {
    9552         [ #  # ]:          0 :         if( ! m_bIsPDF_A1 )
    9553                 :            :         {
    9554         [ #  # ]:          0 :             aLine.append( "/Group<</S/Transparency/CS/DeviceRGB/K true>>\n" );
    9555                 :            :         }
    9556                 :            :     }
    9557                 :            :     /* #i42884# the PDF reference recommends that each Form XObject
    9558                 :            :     *  should have a resource dict; alas if that is the same object
    9559                 :            :     *  as the one of the page it triggers an endless recursion in
    9560                 :            :     *  acroread 5 (6 and up have that fixed). Since we have only one
    9561                 :            :     *  resource dict anyway, let's use the one from the page by NOT
    9562                 :            :     *  emitting a Resources entry.
    9563                 :            :     */
    9564                 :            : 
    9565         [ #  # ]:          0 :     aLine.append( "/Length " );
    9566         [ #  # ]:          0 :     aLine.append( (sal_Int32)(nSize) );
    9567         [ #  # ]:          0 :     aLine.append( "\n" );
    9568         [ #  # ]:          0 :     if( bFlateFilter )
    9569         [ #  # ]:          0 :         aLine.append( "/Filter/FlateDecode\n" );
    9570                 :            :     aLine.append( ">>\n"
    9571         [ #  # ]:          0 :                   "stream\n" );
    9572 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9573         [ #  # ]:          0 :     checkAndEnableStreamEncryption( rObject.m_nObject );
    9574 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( rObject.m_pContentStream->GetData(), nSize ) );
                 [ #  # ]
    9575                 :          0 :     disableStreamEncryption();
    9576         [ #  # ]:          0 :     aLine.setLength( 0 );
    9577                 :            :     aLine.append( "\n"
    9578                 :            :                   "endstream\n"
    9579         [ #  # ]:          0 :                   "endobj\n\n" );
    9580 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9581                 :            : 
    9582                 :            :     // write ExtGState dict for this XObject
    9583         [ #  # ]:          0 :     aLine.setLength( 0 );
    9584         [ #  # ]:          0 :     aLine.append( rObject.m_nExtGStateObject );
    9585                 :            :     aLine.append( " 0 obj\n"
    9586         [ #  # ]:          0 :                   "<<" );
    9587         [ #  # ]:          0 :     if( ! rObject.m_pSoftMaskStream )
    9588                 :            :     {
    9589                 :            : //i59651
    9590         [ #  # ]:          0 :         if( m_bIsPDF_A1 )
    9591                 :            :         {
    9592         [ #  # ]:          0 :             aLine.append( "/CA 1.0/ca 1.0" );
    9593         [ #  # ]:          0 :             m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDFA );
    9594                 :            :         }
    9595                 :            :         else
    9596                 :            :         {
    9597         [ #  # ]:          0 :             aLine.append(  "/CA " );
    9598         [ #  # ]:          0 :             appendDouble( rObject.m_fAlpha, aLine );
    9599                 :            :             aLine.append( "\n"
    9600         [ #  # ]:          0 :                           "   /ca " );
    9601         [ #  # ]:          0 :             appendDouble( rObject.m_fAlpha, aLine );
    9602                 :            :         }
    9603         [ #  # ]:          0 :         aLine.append( "\n" );
    9604                 :            :     }
    9605                 :            :     else
    9606                 :            :     {
    9607         [ #  # ]:          0 :         if( m_bIsPDF_A1 )
    9608                 :            :         {
    9609         [ #  # ]:          0 :             aLine.append( "/SMask/None" );
    9610         [ #  # ]:          0 :             m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDFA );
    9611                 :            :         }
    9612                 :            :         else
    9613                 :            :         {
    9614         [ #  # ]:          0 :             rObject.m_pSoftMaskStream->Seek( STREAM_SEEK_TO_END );
    9615                 :          0 :             sal_Int32 nMaskSize = (sal_Int32)rObject.m_pSoftMaskStream->Tell();
    9616         [ #  # ]:          0 :             rObject.m_pSoftMaskStream->Seek( STREAM_SEEK_TO_BEGIN );
    9617         [ #  # ]:          0 :             sal_Int32 nMaskObject = createObject();
    9618         [ #  # ]:          0 :             aLine.append( "/SMask<</Type/Mask/S/Luminosity/G " );
    9619         [ #  # ]:          0 :             aLine.append( nMaskObject );
    9620         [ #  # ]:          0 :             aLine.append( " 0 R>>\n" );
    9621                 :            : 
    9622                 :          0 :             OStringBuffer aMask;
    9623         [ #  # ]:          0 :             aMask.append( nMaskObject );
    9624                 :            :             aMask.append( " 0 obj\n"
    9625                 :            :                           "<</Type/XObject\n"
    9626                 :            :                           "/Subtype/Form\n"
    9627         [ #  # ]:          0 :                           "/BBox[" );
    9628         [ #  # ]:          0 :             appendFixedInt( rObject.m_aBoundRect.Left(), aMask );
    9629         [ #  # ]:          0 :             aMask.append( ' ' );
    9630         [ #  # ]:          0 :             appendFixedInt( rObject.m_aBoundRect.Top(), aMask );
    9631         [ #  # ]:          0 :             aMask.append( ' ' );
    9632         [ #  # ]:          0 :             appendFixedInt( rObject.m_aBoundRect.Right(), aMask );
    9633         [ #  # ]:          0 :             aMask.append( ' ' );
    9634         [ #  # ]:          0 :             appendFixedInt( rObject.m_aBoundRect.Bottom()+1, aMask );
    9635         [ #  # ]:          0 :             aMask.append( "]\n" );
    9636                 :            : 
    9637                 :            :             /* #i42884# see above */
    9638         [ #  # ]:          0 :             aMask.append( "/Group<</S/Transparency/CS/DeviceRGB>>\n" );
    9639         [ #  # ]:          0 :             aMask.append( "/Length " );
    9640         [ #  # ]:          0 :             aMask.append( nMaskSize );
    9641                 :            :             aMask.append( ">>\n"
    9642         [ #  # ]:          0 :                           "stream\n" );
    9643 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( updateObject( nMaskObject ) );
    9644         [ #  # ]:          0 :             checkAndEnableStreamEncryption(  nMaskObject );
    9645 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( writeBuffer( aMask.getStr(), aMask.getLength() ) );
    9646 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( writeBuffer( rObject.m_pSoftMaskStream->GetData(), nMaskSize ) );
                 [ #  # ]
    9647                 :          0 :             disableStreamEncryption();
    9648         [ #  # ]:          0 :             aMask.setLength( 0 );
    9649                 :            :             aMask.append( "\nendstream\n"
    9650         [ #  # ]:          0 :                           "endobj\n\n" );
    9651 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( writeBuffer( aMask.getStr(), aMask.getLength() ) );
                 [ #  # ]
    9652                 :            :         }
    9653                 :            :     }
    9654                 :            :     aLine.append( ">>\n"
    9655         [ #  # ]:          0 :                   "endobj\n\n" );
    9656 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nExtGStateObject ) );
    9657 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9658                 :            : 
    9659                 :          0 :     return true;
    9660                 :            : }
    9661                 :            : 
    9662                 :          0 : bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
    9663                 :            : {
    9664         [ #  # ]:          0 :     sal_Int32 nFunctionObject = createObject();
    9665 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nFunctionObject ) );
    9666                 :            : 
    9667         [ #  # ]:          0 :     VirtualDevice aDev;
    9668         [ #  # ]:          0 :     aDev.SetOutputSizePixel( rObject.m_aSize );
    9669 [ #  # ][ #  # ]:          0 :     aDev.SetMapMode( MapMode( MAP_PIXEL ) );
                 [ #  # ]
    9670         [ #  # ]:          0 :     if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
    9671                 :          0 :         aDev.SetDrawMode( aDev.GetDrawMode() |
    9672                 :            :                           ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT |
    9673         [ #  # ]:          0 :                             DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) );
    9674 [ #  # ][ #  # ]:          0 :     aDev.DrawGradient( Rectangle( Point( 0, 0 ), rObject.m_aSize ), rObject.m_aGradient );
    9675                 :            : 
    9676         [ #  # ]:          0 :     Bitmap aSample = aDev.GetBitmap( Point( 0, 0 ), rObject.m_aSize );
    9677         [ #  # ]:          0 :     BitmapReadAccess* pAccess = aSample.AcquireReadAccess();
    9678                 :          0 :     AccessReleaser aReleaser( pAccess );
    9679                 :            : 
    9680         [ #  # ]:          0 :     Size aSize = aSample.GetSizePixel();
    9681                 :            : 
    9682         [ #  # ]:          0 :     sal_Int32 nStreamLengthObject = createObject();
    9683                 :            :     #if OSL_DEBUG_LEVEL > 1
    9684                 :            :     emitComment( "PDFWriterImpl::writeGradientFunction" );
    9685                 :            :     #endif
    9686                 :          0 :     OStringBuffer aLine( 120 );
    9687         [ #  # ]:          0 :     aLine.append( nFunctionObject );
    9688                 :            :     aLine.append( " 0 obj\n"
    9689                 :            :                   "<</FunctionType 0\n"
    9690                 :            :                   "/Domain[ 0 1 0 1 ]\n"
    9691         [ #  # ]:          0 :                   "/Size[ " );
    9692         [ #  # ]:          0 :     aLine.append( (sal_Int32)aSize.Width() );
    9693         [ #  # ]:          0 :     aLine.append( ' ' );
    9694         [ #  # ]:          0 :     aLine.append( (sal_Int32)aSize.Height() );
    9695                 :            :     aLine.append( " ]\n"
    9696                 :            :                   "/BitsPerSample 8\n"
    9697                 :            :                   "/Range[ 0 1 0 1 0 1 ]\n"
    9698                 :            :                   "/Order 3\n"
    9699         [ #  # ]:          0 :                   "/Length " );
    9700         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
    9701                 :            :     aLine.append( " 0 R\n"
    9702                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    9703                 :            :                   "/Filter/FlateDecode"
    9704                 :            : #endif
    9705                 :            :                   ">>\n"
    9706         [ #  # ]:          0 :                   "stream\n" );
    9707 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9708                 :            : 
    9709                 :          0 :     sal_uInt64 nStartStreamPos = 0;
    9710 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartStreamPos )) );
    9711                 :            : 
    9712         [ #  # ]:          0 :     checkAndEnableStreamEncryption( nFunctionObject );
    9713         [ #  # ]:          0 :     beginCompression();
    9714         [ #  # ]:          0 :     for( int y = aSize.Height()-1; y >= 0; y-- )
    9715                 :            :     {
    9716         [ #  # ]:          0 :         for( int x = 0; x < aSize.Width(); x++ )
    9717                 :            :         {
    9718                 :            :             sal_uInt8 aCol[3];
    9719         [ #  # ]:          0 :             BitmapColor aColor = pAccess->GetColor( y, x );
    9720                 :          0 :             aCol[0] = aColor.GetRed();
    9721                 :          0 :             aCol[1] = aColor.GetGreen();
    9722                 :          0 :             aCol[2] = aColor.GetBlue();
    9723 [ #  # ][ #  # ]:          0 :             CHECK_RETURN( writeBuffer( aCol, 3 ) );
    9724         [ #  # ]:          0 :         }
    9725                 :            :     }
    9726         [ #  # ]:          0 :     endCompression();
    9727                 :          0 :     disableStreamEncryption();
    9728                 :            : 
    9729                 :          0 :     sal_uInt64 nEndStreamPos = 0;
    9730 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nEndStreamPos )) );
    9731                 :            : 
    9732         [ #  # ]:          0 :     aLine.setLength( 0 );
    9733         [ #  # ]:          0 :     aLine.append( "\nendstream\nendobj\n\n" );
    9734 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9735                 :            : 
    9736                 :            :     // write stream length
    9737 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nStreamLengthObject ) );
    9738         [ #  # ]:          0 :     aLine.setLength( 0 );
    9739         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
    9740         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
    9741         [ #  # ]:          0 :     aLine.append( (sal_Int64)(nEndStreamPos-nStartStreamPos) );
    9742         [ #  # ]:          0 :     aLine.append( "\nendobj\n\n" );
    9743 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9744                 :            : 
    9745 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nObject ) );
    9746         [ #  # ]:          0 :     aLine.setLength( 0 );
    9747         [ #  # ]:          0 :     aLine.append( rObject.m_nObject );
    9748                 :            :     aLine.append( " 0 obj\n"
    9749                 :            :                   "<</ShadingType 1\n"
    9750                 :            :                   "/ColorSpace/DeviceRGB\n"
    9751                 :            :                   "/AntiAlias true\n"
    9752                 :            :                   "/Domain[ 0 1 0 1 ]\n"
    9753         [ #  # ]:          0 :                   "/Matrix[ " );
    9754         [ #  # ]:          0 :     aLine.append( (sal_Int32)aSize.Width() );
    9755         [ #  # ]:          0 :     aLine.append( " 0 0 " );
    9756         [ #  # ]:          0 :     aLine.append( (sal_Int32)aSize.Height() );
    9757                 :            :     aLine.append( " 0 0 ]\n"
    9758         [ #  # ]:          0 :                   "/Function " );
    9759         [ #  # ]:          0 :     aLine.append( nFunctionObject );
    9760                 :            :     aLine.append( " 0 R\n"
    9761                 :            :                   ">>\n"
    9762         [ #  # ]:          0 :                   "endobj\n\n" );
    9763 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9764                 :            : 
    9765 [ #  # ][ #  # ]:          0 :     return true;
                 [ #  # ]
    9766                 :            : }
    9767                 :            : 
    9768                 :          0 : bool PDFWriterImpl::writeJPG( JPGEmit& rObject )
    9769                 :            : {
    9770         [ #  # ]:          0 :     CHECK_RETURN( rObject.m_pStream );
    9771 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nObject ) );
    9772                 :            : 
    9773                 :          0 :     sal_Int32 nLength = 0;
    9774         [ #  # ]:          0 :     rObject.m_pStream->Seek( STREAM_SEEK_TO_END );
    9775                 :          0 :     nLength = rObject.m_pStream->Tell();
    9776         [ #  # ]:          0 :     rObject.m_pStream->Seek( STREAM_SEEK_TO_BEGIN );
    9777                 :            : 
    9778                 :          0 :     sal_Int32 nMaskObject = 0;
    9779         [ #  # ]:          0 :     if( !!rObject.m_aMask )
    9780                 :            :     {
    9781 [ #  # ][ #  # ]:          0 :         if( rObject.m_aMask.GetBitCount() == 1 ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    9782         [ #  # ]:          0 :             ( rObject.m_aMask.GetBitCount() == 8 && m_aContext.Version >= PDFWriter::PDF_1_4 && !m_bIsPDF_A1 )//i59651
    9783                 :            :             )
    9784                 :            :         {
    9785         [ #  # ]:          0 :             nMaskObject = createObject();
    9786                 :            :         }
    9787         [ #  # ]:          0 :         else if( m_bIsPDF_A1 )
    9788         [ #  # ]:          0 :             m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDFA );
    9789         [ #  # ]:          0 :         else if( m_aContext.Version < PDFWriter::PDF_1_4 )
    9790         [ #  # ]:          0 :             m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDF13 );
    9791                 :            : 
    9792                 :            :     }
    9793                 :            :     #if OSL_DEBUG_LEVEL > 1
    9794                 :            :     emitComment( "PDFWriterImpl::writeJPG" );
    9795                 :            :     #endif
    9796                 :            : 
    9797                 :          0 :     OStringBuffer aLine(200);
    9798         [ #  # ]:          0 :     aLine.append( rObject.m_nObject );
    9799                 :            :     aLine.append( " 0 obj\n"
    9800         [ #  # ]:          0 :                   "<</Type/XObject/Subtype/Image/Width " );
    9801         [ #  # ]:          0 :     aLine.append( (sal_Int32)rObject.m_aID.m_aPixelSize.Width() );
    9802         [ #  # ]:          0 :     aLine.append( " /Height " );
    9803         [ #  # ]:          0 :     aLine.append( (sal_Int32)rObject.m_aID.m_aPixelSize.Height() );
    9804         [ #  # ]:          0 :     aLine.append( " /BitsPerComponent 8 " );
    9805         [ #  # ]:          0 :     if( rObject.m_bTrueColor )
    9806         [ #  # ]:          0 :         aLine.append( "/ColorSpace/DeviceRGB" );
    9807                 :            :     else
    9808         [ #  # ]:          0 :         aLine.append( "/ColorSpace/DeviceGray" );
    9809         [ #  # ]:          0 :     aLine.append( "/Filter/DCTDecode/Length " );
    9810         [ #  # ]:          0 :     aLine.append( nLength );
    9811         [ #  # ]:          0 :     if( nMaskObject )
    9812                 :            :     {
    9813 [ #  # ][ #  # ]:          0 :         aLine.append( rObject.m_aMask.GetBitCount() == 1 ? " /Mask " : " /SMask " );
                 [ #  # ]
    9814         [ #  # ]:          0 :         aLine.append( nMaskObject );
    9815         [ #  # ]:          0 :         aLine.append( " 0 R " );
    9816                 :            :     }
    9817         [ #  # ]:          0 :     aLine.append( ">>\nstream\n" );
    9818 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9819                 :            : 
    9820         [ #  # ]:          0 :     checkAndEnableStreamEncryption( rObject.m_nObject );
    9821 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( rObject.m_pStream->GetData(), nLength ) );
                 [ #  # ]
    9822                 :          0 :     disableStreamEncryption();
    9823                 :            : 
    9824         [ #  # ]:          0 :     aLine.setLength( 0 );
    9825         [ #  # ]:          0 :     aLine.append( "\nendstream\nendobj\n\n" );
    9826 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
    9827                 :            : 
    9828         [ #  # ]:          0 :     if( nMaskObject )
    9829                 :            :     {
    9830         [ #  # ]:          0 :         BitmapEmit aEmit;
    9831                 :          0 :         aEmit.m_nObject = nMaskObject;
    9832 [ #  # ][ #  # ]:          0 :         if( rObject.m_aMask.GetBitCount() == 1 )
    9833 [ #  # ][ #  # ]:          0 :             aEmit.m_aBitmap = BitmapEx( rObject.m_aMask, rObject.m_aMask );
                 [ #  # ]
    9834 [ #  # ][ #  # ]:          0 :         else if( rObject.m_aMask.GetBitCount() == 8 )
    9835 [ #  # ][ #  # ]:          0 :             aEmit.m_aBitmap = BitmapEx( rObject.m_aMask, AlphaMask( rObject.m_aMask ) );
         [ #  # ][ #  # ]
                 [ #  # ]
    9836 [ #  # ][ #  # ]:          0 :         writeBitmapObject( aEmit, true );
    9837                 :            :     }
    9838                 :            : 
    9839                 :          0 :     return true;
    9840                 :            : }
    9841                 :            : 
    9842                 :          0 : bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
    9843                 :            : {
    9844 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( rObject.m_nObject ) );
    9845                 :            : 
    9846         [ #  # ]:          0 :     Bitmap  aBitmap;
    9847                 :          0 :     Color   aTransparentColor( COL_TRANSPARENT );
    9848                 :          0 :     bool    bWriteMask = false;
    9849         [ #  # ]:          0 :     if( ! bMask )
    9850                 :            :     {
    9851 [ #  # ][ #  # ]:          0 :         aBitmap = rObject.m_aBitmap.GetBitmap();
                 [ #  # ]
    9852 [ #  # ][ #  # ]:          0 :         if( rObject.m_aBitmap.IsAlpha() )
    9853                 :            :         {
    9854         [ #  # ]:          0 :             if( m_aContext.Version >= PDFWriter::PDF_1_4 )
    9855                 :          0 :                 bWriteMask = true;
    9856                 :            :             // else draw without alpha channel
    9857                 :            :         }
    9858                 :            :         else
    9859                 :            :         {
    9860   [ #  #  #  # ]:          0 :             switch( rObject.m_aBitmap.GetTransparentType() )
    9861                 :            :             {
    9862                 :            :                 case TRANSPARENT_NONE:
    9863                 :            :                     // comes from drawMask function
    9864 [ #  # ][ #  # ]:          0 :                     if( aBitmap.GetBitCount() == 1 && rObject.m_bDrawMask )
         [ #  # ][ #  # ]
    9865                 :          0 :                         bMask = true;
    9866                 :          0 :                     break;
    9867                 :            :                 case TRANSPARENT_COLOR:
    9868                 :          0 :                     aTransparentColor = rObject.m_aBitmap.GetTransparentColor();
    9869                 :          0 :                     break;
    9870                 :            :                 case TRANSPARENT_BITMAP:
    9871                 :          0 :                     bWriteMask = true;
    9872                 :          0 :                     break;
    9873                 :            :             }
    9874                 :            :         }
    9875                 :            :     }
    9876                 :            :     else
    9877                 :            :     {
    9878 [ #  # ][ #  # ]:          0 :         if( m_aContext.Version < PDFWriter::PDF_1_4 || ! rObject.m_aBitmap.IsAlpha() )
         [ #  # ][ #  # ]
    9879                 :            :         {
    9880 [ #  # ][ #  # ]:          0 :             aBitmap = rObject.m_aBitmap.GetMask();
                 [ #  # ]
    9881         [ #  # ]:          0 :             aBitmap.Convert( BMP_CONVERSION_1BIT_THRESHOLD );
    9882                 :            :             DBG_ASSERT( aBitmap.GetBitCount() == 1, "mask conversion failed" );
    9883                 :            :         }
    9884 [ #  # ][ #  # ]:          0 :         else if( aBitmap.GetBitCount() != 8 )
    9885                 :            :         {
    9886 [ #  # ][ #  # ]:          0 :             aBitmap = rObject.m_aBitmap.GetAlpha().GetBitmap();
         [ #  # ][ #  # ]
                 [ #  # ]
    9887         [ #  # ]:          0 :             aBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
    9888                 :            :             DBG_ASSERT( aBitmap.GetBitCount() == 8, "alpha mask conversion failed" );
    9889                 :            :         }
    9890                 :            :     }
    9891                 :            : 
    9892         [ #  # ]:          0 :     BitmapReadAccess* pAccess = aBitmap.AcquireReadAccess();
    9893                 :          0 :     AccessReleaser aReleaser( pAccess );
    9894                 :            : 
    9895                 :            :     bool bTrueColor;
    9896                 :            :     sal_Int32 nBitsPerComponent;
    9897 [ #  # ][ #  # ]:          0 :     switch( aBitmap.GetBitCount() )
    9898                 :            :     {
    9899                 :            :         case 1:
    9900                 :            :         case 2:
    9901                 :            :         case 4:
    9902                 :            :         case 8:
    9903                 :          0 :             bTrueColor = false;
    9904         [ #  # ]:          0 :             nBitsPerComponent = aBitmap.GetBitCount();
    9905                 :          0 :             break;
    9906                 :            :         default:
    9907                 :          0 :             bTrueColor = true;
    9908                 :          0 :             nBitsPerComponent = 8;
    9909                 :          0 :             break;
    9910                 :            :     }
    9911                 :            : 
    9912         [ #  # ]:          0 :     sal_Int32 nStreamLengthObject   = createObject();
    9913                 :          0 :     sal_Int32 nMaskObject           = 0;
    9914                 :            : 
    9915                 :            :     #if OSL_DEBUG_LEVEL > 1
    9916                 :            :     emitComment( "PDFWriterImpl::writeBitmapObject" );
    9917                 :            :     #endif
    9918                 :          0 :     OStringBuffer aLine(1024);
    9919         [ #  # ]:          0 :     aLine.append( rObject.m_nObject );
    9920                 :            :     aLine.append( " 0 obj\n"
    9921         [ #  # ]:          0 :                   "<</Type/XObject/Subtype/Image/Width " );
    9922 [ #  # ][ #  # ]:          0 :     aLine.append( (sal_Int32)aBitmap.GetSizePixel().Width() );
    9923         [ #  # ]:          0 :     aLine.append( "/Height " );
    9924 [ #  # ][ #  # ]:          0 :     aLine.append( (sal_Int32)aBitmap.GetSizePixel().Height() );
    9925         [ #  # ]:          0 :     aLine.append( "/BitsPerComponent " );
    9926         [ #  # ]:          0 :     aLine.append( nBitsPerComponent );
    9927         [ #  # ]:          0 :     aLine.append( "/Length " );
    9928         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
    9929         [ #  # ]:          0 :     aLine.append( " 0 R\n" );
    9930                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
    9931         [ #  # ]:          0 :     if( nBitsPerComponent != 1 )
    9932                 :            :     {
    9933         [ #  # ]:          0 :         aLine.append( "/Filter/FlateDecode" );
    9934                 :            :     }
    9935                 :            :     else
    9936                 :            :     {
    9937         [ #  # ]:          0 :         aLine.append( "/Filter/CCITTFaxDecode/DecodeParms<</K -1/BlackIs1 true/Columns " );
    9938 [ #  # ][ #  # ]:          0 :         aLine.append( (sal_Int32)aBitmap.GetSizePixel().Width() );
    9939         [ #  # ]:          0 :         aLine.append( ">>\n" );
    9940                 :            :     }
    9941                 :            : #endif
    9942         [ #  # ]:          0 :     if( ! bMask )
    9943                 :            :     {
    9944         [ #  # ]:          0 :         aLine.append( "/ColorSpace" );
    9945         [ #  # ]:          0 :         if( bTrueColor )
    9946         [ #  # ]:          0 :             aLine.append( "/DeviceRGB\n" );
    9947 [ #  # ][ #  # ]:          0 :         else if( aBitmap.HasGreyPalette() )
    9948                 :            :         {
    9949         [ #  # ]:          0 :             aLine.append( "/DeviceGray\n" );
    9950 [ #  # ][ #  # ]:          0 :             if( aBitmap.GetBitCount() == 1 )
    9951                 :            :             {
    9952                 :            :                 // #i47395# 1 bit bitmaps occasionally have an inverted grey palette
    9953         [ #  # ]:          0 :                 sal_Int32 nBlackIndex = pAccess->GetBestPaletteIndex( BitmapColor( Color( COL_BLACK ) ) );
    9954                 :            :                 DBG_ASSERT( nBlackIndex == 0 || nBlackIndex == 1, "wrong black index" );
    9955         [ #  # ]:          0 :                 if( nBlackIndex == 1 )
    9956         [ #  # ]:          0 :                     aLine.append( "/Decode[1 0]\n" );
    9957                 :            :             }
    9958                 :            :         }
    9959                 :            :         else
    9960                 :            :         {
    9961         [ #  # ]:          0 :             aLine.append( "[ /Indexed/DeviceRGB " );
    9962         [ #  # ]:          0 :             aLine.append( (sal_Int32)(pAccess->GetPaletteEntryCount()-1) );
    9963         [ #  # ]:          0 :             aLine.append( "\n<" );
    9964         [ #  # ]:          0 :             if( m_aContext.Encryption.Encrypt() )
    9965                 :            :             {
    9966         [ #  # ]:          0 :                 enableStringEncryption( rObject.m_nObject );
    9967                 :            :                 //check encryption buffer size
    9968 [ #  # ][ #  # ]:          0 :                 if( checkEncryptionBufferSize( pAccess->GetPaletteEntryCount()*3 ) )
    9969                 :            :                 {
    9970                 :          0 :                     int nChar = 0;
    9971                 :            :                     //fill the encryption buffer
    9972         [ #  # ]:          0 :                     for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ )
    9973                 :            :                     {
    9974                 :          0 :                         const BitmapColor& rColor = pAccess->GetPaletteColor( i );
    9975                 :          0 :                         m_pEncryptionBuffer[nChar++] = rColor.GetRed();
    9976                 :          0 :                         m_pEncryptionBuffer[nChar++] = rColor.GetGreen();
    9977                 :          0 :                         m_pEncryptionBuffer[nChar++] = rColor.GetBlue();
    9978                 :            :                     }
    9979                 :            :                     //encrypt the colorspace lookup table
    9980                 :          0 :                     rtl_cipher_encodeARCFOUR( m_aCipher, m_pEncryptionBuffer, nChar, m_pEncryptionBuffer, nChar );
    9981                 :            :                     //now queue the data for output
    9982                 :          0 :                     nChar = 0;
    9983         [ #  # ]:          0 :                     for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ )
    9984                 :            :                     {
    9985         [ #  # ]:          0 :                         appendHex(m_pEncryptionBuffer[nChar++], aLine );
    9986         [ #  # ]:          0 :                         appendHex(m_pEncryptionBuffer[nChar++], aLine );
    9987         [ #  # ]:          0 :                         appendHex(m_pEncryptionBuffer[nChar++], aLine );
    9988                 :            :                     }
    9989                 :            :                 }
    9990                 :            :             }
    9991                 :            :             else //no encryption requested (PDF/A-1a program flow drops here)
    9992                 :            :             {
    9993         [ #  # ]:          0 :                 for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ )
    9994                 :            :                 {
    9995                 :          0 :                     const BitmapColor& rColor = pAccess->GetPaletteColor( i );
    9996         [ #  # ]:          0 :                     appendHex( rColor.GetRed(), aLine );
    9997         [ #  # ]:          0 :                     appendHex( rColor.GetGreen(), aLine );
    9998         [ #  # ]:          0 :                     appendHex( rColor.GetBlue(), aLine );
    9999                 :            :                 }
   10000                 :            :             }
   10001         [ #  # ]:          0 :             aLine.append( ">\n]\n" );
   10002                 :            :         }
   10003                 :            :     }
   10004                 :            :     else
   10005                 :            :     {
   10006 [ #  # ][ #  # ]:          0 :         if( aBitmap.GetBitCount() == 1 )
   10007                 :            :         {
   10008         [ #  # ]:          0 :             aLine.append( "/ImageMask true\n" );
   10009         [ #  # ]:          0 :             sal_Int32 nBlackIndex = pAccess->GetBestPaletteIndex( BitmapColor( Color( COL_BLACK ) ) );
   10010                 :            :             DBG_ASSERT( nBlackIndex == 0 || nBlackIndex == 1, "wrong black index" );
   10011         [ #  # ]:          0 :             if( nBlackIndex )
   10012         [ #  # ]:          0 :                 aLine.append( "/Decode[ 1 0 ]\n" );
   10013                 :            :             else
   10014         [ #  # ]:          0 :                 aLine.append( "/Decode[ 0 1 ]\n" );
   10015                 :            :         }
   10016 [ #  # ][ #  # ]:          0 :         else if( aBitmap.GetBitCount() == 8 )
   10017                 :            :         {
   10018                 :            :             aLine.append( "/ColorSpace/DeviceGray\n"
   10019         [ #  # ]:          0 :                           "/Decode [ 1 0 ]\n" );
   10020                 :            :         }
   10021                 :            :     }
   10022                 :            : 
   10023 [ #  # ][ #  # ]:          0 :     if( ! bMask && m_aContext.Version > PDFWriter::PDF_1_2 && !m_bIsPDF_A1 )//i59651
                 [ #  # ]
   10024                 :            :     {
   10025         [ #  # ]:          0 :         if( bWriteMask )
   10026                 :            :         {
   10027         [ #  # ]:          0 :             nMaskObject = createObject();
   10028 [ #  # ][ #  # ]:          0 :             if( rObject.m_aBitmap.IsAlpha() && m_aContext.Version > PDFWriter::PDF_1_3 )
         [ #  # ][ #  # ]
   10029         [ #  # ]:          0 :                 aLine.append( "/SMask " );
   10030                 :            :             else
   10031         [ #  # ]:          0 :                 aLine.append( "/Mask " );
   10032         [ #  # ]:          0 :             aLine.append( nMaskObject );
   10033         [ #  # ]:          0 :             aLine.append( " 0 R\n" );
   10034                 :            :         }
   10035         [ #  # ]:          0 :         else if( aTransparentColor != Color( COL_TRANSPARENT ) )
   10036                 :            :         {
   10037         [ #  # ]:          0 :             aLine.append( "/Mask[ " );
   10038         [ #  # ]:          0 :             if( bTrueColor )
   10039                 :            :             {
   10040         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetRed() );
   10041         [ #  # ]:          0 :                 aLine.append( ' ' );
   10042         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetRed() );
   10043         [ #  # ]:          0 :                 aLine.append( ' ' );
   10044         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetGreen() );
   10045         [ #  # ]:          0 :                 aLine.append( ' ' );
   10046         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetGreen() );
   10047         [ #  # ]:          0 :                 aLine.append( ' ' );
   10048         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetBlue() );
   10049         [ #  # ]:          0 :                 aLine.append( ' ' );
   10050         [ #  # ]:          0 :                 aLine.append( (sal_Int32)aTransparentColor.GetBlue() );
   10051                 :            :             }
   10052                 :            :             else
   10053                 :            :             {
   10054         [ #  # ]:          0 :                 sal_Int32 nIndex = pAccess->GetBestPaletteIndex( BitmapColor( aTransparentColor ) );
   10055         [ #  # ]:          0 :                 aLine.append( nIndex );
   10056                 :            :             }
   10057         [ #  # ]:          0 :             aLine.append( " ]\n" );
   10058                 :          0 :         }
   10059                 :            :     }
   10060 [ #  # ][ #  # ]:          0 :     else if( m_bIsPDF_A1 && (bWriteMask || aTransparentColor != Color( COL_TRANSPARENT )) )
         [ #  # ][ #  # ]
                 [ #  # ]
   10061         [ #  # ]:          0 :         m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDFA );
   10062                 :            : 
   10063                 :            :     aLine.append( ">>\n"
   10064         [ #  # ]:          0 :                   "stream\n" );
   10065 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
   10066                 :          0 :     sal_uInt64 nStartPos = 0;
   10067 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos )) );
   10068                 :            : 
   10069         [ #  # ]:          0 :     checkAndEnableStreamEncryption( rObject.m_nObject );
   10070                 :            : #ifndef DEBUG_DISABLE_PDFCOMPRESSION
   10071         [ #  # ]:          0 :     if( nBitsPerComponent == 1 )
   10072                 :            :     {
   10073         [ #  # ]:          0 :         writeG4Stream( pAccess );
   10074                 :            :     }
   10075                 :            :     else
   10076                 :            : #endif
   10077                 :            :     {
   10078         [ #  # ]:          0 :         beginCompression();
   10079 [ #  # ][ #  # ]:          0 :         if( ! bTrueColor || pAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
                 [ #  # ]
   10080                 :            :         {
   10081                 :          0 :             const int nScanLineBytes = 1 + ( pAccess->GetBitCount() * ( pAccess->Width() - 1 ) / 8U );
   10082                 :            : 
   10083         [ #  # ]:          0 :             for( int i = 0; i < pAccess->Height(); i++ )
   10084                 :            :             {
   10085 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( pAccess->GetScanline( i ), nScanLineBytes ) );
   10086                 :            :             }
   10087                 :            :         }
   10088                 :            :         else
   10089                 :            :         {
   10090                 :          0 :             const int nScanLineBytes = pAccess->Width()*3;
   10091 [ #  # ][ #  # ]:          0 :             boost::shared_array<sal_uInt8> pCol( new sal_uInt8[ nScanLineBytes ] );
   10092         [ #  # ]:          0 :             for( int y = 0; y < pAccess->Height(); y++ )
   10093                 :            :             {
   10094         [ #  # ]:          0 :                 for( int x = 0; x < pAccess->Width(); x++ )
   10095                 :            :                 {
   10096         [ #  # ]:          0 :                     BitmapColor aColor = pAccess->GetColor( y, x );
   10097                 :          0 :                     pCol[3*x+0] = aColor.GetRed();
   10098                 :          0 :                     pCol[3*x+1] = aColor.GetGreen();
   10099                 :          0 :                     pCol[3*x+2] = aColor.GetBlue();
   10100                 :          0 :                 }
   10101 [ #  # ][ #  # ]:          0 :                 CHECK_RETURN( writeBuffer( pCol.get(), nScanLineBytes ) );
   10102 [ #  # ][ #  # ]:          0 :             }
   10103                 :            :         }
   10104         [ #  # ]:          0 :         endCompression();
   10105                 :            :     }
   10106                 :          0 :     disableStreamEncryption();
   10107                 :            : 
   10108                 :          0 :     sal_uInt64 nEndPos = 0;
   10109 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nEndPos )) );
   10110         [ #  # ]:          0 :     aLine.setLength( 0 );
   10111         [ #  # ]:          0 :     aLine.append( "\nendstream\nendobj\n\n" );
   10112 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
   10113 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( updateObject( nStreamLengthObject ) );
   10114         [ #  # ]:          0 :     aLine.setLength( 0 );
   10115         [ #  # ]:          0 :     aLine.append( nStreamLengthObject );
   10116         [ #  # ]:          0 :     aLine.append( " 0 obj\n" );
   10117         [ #  # ]:          0 :     aLine.append( (sal_Int64)(nEndPos-nStartPos) );
   10118         [ #  # ]:          0 :     aLine.append( "\nendobj\n\n" );
   10119 [ #  # ][ #  # ]:          0 :     CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
   10120                 :            : 
   10121         [ #  # ]:          0 :     if( nMaskObject )
   10122                 :            :     {
   10123         [ #  # ]:          0 :         BitmapEmit aEmit;
   10124                 :          0 :         aEmit.m_nObject             = nMaskObject;
   10125         [ #  # ]:          0 :         aEmit.m_aBitmap             = rObject.m_aBitmap;
   10126 [ #  # ][ #  # ]:          0 :         return writeBitmapObject( aEmit, true );
   10127                 :            :     }
   10128                 :            : 
   10129 [ #  # ][ #  # ]:          0 :     return true;
   10130                 :            : }
   10131                 :            : 
   10132                 :          0 : void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask )
   10133                 :            : {
   10134         [ #  # ]:          0 :     MARK( "drawJPGBitmap" );
   10135                 :            : 
   10136                 :          0 :     OStringBuffer aLine( 80 );
   10137         [ #  # ]:          0 :     updateGraphicsState();
   10138                 :            : 
   10139                 :            :     // #i40055# sanity check
   10140 [ #  # ][ #  # ]:          0 :     if( ! (rTargetArea.GetWidth() && rTargetArea.GetHeight() ) )
         [ #  # ][ #  # ]
                 [ #  # ]
   10141                 :            :         return;
   10142 [ #  # ][ #  # ]:          0 :     if( ! (rSizePixel.Width() && rSizePixel.Height()) )
                 [ #  # ]
   10143                 :            :         return;
   10144                 :            : 
   10145         [ #  # ]:          0 :     rDCTData.Seek( 0 );
   10146 [ #  # ][ #  # ]:          0 :     if( bIsTrueColor && m_aContext.ColorMode == PDFWriter::DrawGreyscale )
   10147                 :            :     {
   10148                 :            :         // need to convert to grayscale;
   10149                 :            :         // load stream to bitmap and draw the bitmap instead
   10150         [ #  # ]:          0 :         Graphic aGraphic;
   10151         [ #  # ]:          0 :         GraphicConverter::Import( rDCTData, aGraphic, CVT_JPG );
   10152         [ #  # ]:          0 :         Bitmap aBmp( aGraphic.GetBitmap() );
   10153 [ #  # ][ #  # ]:          0 :         if( !!rMask && rMask.GetSizePixel() == aBmp.GetSizePixel() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
                   #  # ]
   10154                 :            :         {
   10155         [ #  # ]:          0 :             BitmapEx aBmpEx( aBmp, rMask );
   10156 [ #  # ][ #  # ]:          0 :             drawBitmap( rTargetArea.TopLeft(), rTargetArea.GetSize(), aBmpEx );
                 [ #  # ]
   10157                 :            :         }
   10158                 :            :         else
   10159 [ #  # ][ #  # ]:          0 :             drawBitmap( rTargetArea.TopLeft(), rTargetArea.GetSize(), aBmp );
   10160 [ #  # ][ #  # ]:          0 :         return;
   10161                 :            :     }
   10162                 :            : 
   10163 [ #  # ][ #  # ]:          0 :     SvMemoryStream* pStream = new SvMemoryStream;
   10164         [ #  # ]:          0 :     *pStream << rDCTData;
   10165         [ #  # ]:          0 :     pStream->Seek( STREAM_SEEK_TO_END );
   10166                 :            : 
   10167                 :          0 :     BitmapID aID;
   10168                 :          0 :     aID.m_aPixelSize    = rSizePixel;
   10169                 :          0 :     aID.m_nSize         = pStream->Tell();
   10170         [ #  # ]:          0 :     pStream->Seek( STREAM_SEEK_TO_BEGIN );
   10171         [ #  # ]:          0 :     aID.m_nChecksum     = rtl_crc32( 0, pStream->GetData(), aID.m_nSize );
   10172         [ #  # ]:          0 :     if( ! rMask.IsEmpty() )
   10173         [ #  # ]:          0 :         aID.m_nMaskChecksum = rMask.GetChecksum();
   10174                 :            : 
   10175                 :          0 :     std::list< JPGEmit >::const_iterator it;
   10176 [ #  # ][ #  # ]:          0 :     for( it = m_aJPGs.begin(); it != m_aJPGs.end() && ! (aID == it->m_aID); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
   10177                 :            :         ;
   10178         [ #  # ]:          0 :     if( it == m_aJPGs.end() )
   10179                 :            :     {
   10180 [ #  # ][ #  # ]:          0 :         m_aJPGs.push_front( JPGEmit() );
                 [ #  # ]
   10181                 :          0 :         JPGEmit& rEmit = m_aJPGs.front();
   10182         [ #  # ]:          0 :         rEmit.m_nObject     = createObject();
   10183                 :          0 :         rEmit.m_aID         = aID;
   10184                 :          0 :         rEmit.m_pStream     = pStream;
   10185                 :          0 :         rEmit.m_bTrueColor  = bIsTrueColor;
   10186 [ #  # ][ #  # ]:          0 :         if( !! rMask && rMask.GetSizePixel() == rSizePixel )
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
   10187         [ #  # ]:          0 :             rEmit.m_aMask   = rMask;
   10188                 :            : 
   10189                 :          0 :         it = m_aJPGs.begin();
   10190                 :            :     }
   10191                 :            :     else
   10192 [ #  # ][ #  # ]:          0 :         delete pStream;
   10193                 :            : 
   10194         [ #  # ]:          0 :     aLine.append( "q " );
   10195                 :          0 :     sal_Int32 nCheckWidth = 0;
   10196 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetWidth(), aLine, false, &nCheckWidth );
                 [ #  # ]
   10197         [ #  # ]:          0 :     aLine.append( " 0 0 " );
   10198                 :          0 :     sal_Int32 nCheckHeight = 0;
   10199 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rTargetArea.GetHeight(), aLine, true, &nCheckHeight );
                 [ #  # ]
   10200         [ #  # ]:          0 :     aLine.append( ' ' );
   10201 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( rTargetArea.BottomLeft(), aLine );
                 [ #  # ]
   10202         [ #  # ]:          0 :     aLine.append( " cm\n/Im" );
   10203         [ #  # ]:          0 :     aLine.append( it->m_nObject );
   10204         [ #  # ]:          0 :     aLine.append( " Do Q\n" );
   10205 [ #  # ][ #  # ]:          0 :     if( nCheckWidth == 0 || nCheckHeight == 0 )
   10206                 :            :     {
   10207                 :            :         // #i97512# avoid invalid current matrix
   10208         [ #  # ]:          0 :         aLine.setLength( 0 );
   10209         [ #  # ]:          0 :         aLine.append( "\n%jpeg image /Im" );
   10210         [ #  # ]:          0 :         aLine.append( it->m_nObject );
   10211         [ #  # ]:          0 :         aLine.append( " scaled to zero size, omitted\n" );
   10212                 :            :     }
   10213         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
   10214                 :            : 
   10215                 :          0 :     OStringBuffer aObjName( 16 );
   10216         [ #  # ]:          0 :     aObjName.append( "Im" );
   10217         [ #  # ]:          0 :     aObjName.append( it->m_nObject );
   10218 [ #  # ][ #  # ]:          0 :     pushResource( ResXObject, aObjName.makeStringAndClear(), it->m_nObject );
   10219                 :            : 
   10220                 :            : }
   10221                 :            : 
   10222                 :          0 : void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize, const BitmapEmit& rBitmap, const Color& rFillColor )
   10223                 :            : {
   10224                 :          0 :     OStringBuffer aLine( 80 );
   10225         [ #  # ]:          0 :     updateGraphicsState();
   10226                 :            : 
   10227         [ #  # ]:          0 :     aLine.append( "q " );
   10228         [ #  # ]:          0 :     if( rFillColor != Color( COL_TRANSPARENT ) )
   10229                 :            :     {
   10230         [ #  # ]:          0 :         appendNonStrokingColor( rFillColor, aLine );
   10231         [ #  # ]:          0 :         aLine.append( ' ' );
   10232                 :            :     }
   10233                 :          0 :     sal_Int32 nCheckWidth = 0;
   10234 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Width(), aLine, false, &nCheckWidth );
   10235         [ #  # ]:          0 :     aLine.append( " 0 0 " );
   10236                 :          0 :     sal_Int32 nCheckHeight = 0;
   10237 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rDestSize.Height(), aLine, true, &nCheckHeight );
   10238         [ #  # ]:          0 :     aLine.append( ' ' );
   10239 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( rDestPoint + Point( 0, rDestSize.Height()-1 ), aLine );
   10240         [ #  # ]:          0 :     aLine.append( " cm\n/Im" );
   10241         [ #  # ]:          0 :     aLine.append( rBitmap.m_nObject );
   10242         [ #  # ]:          0 :     aLine.append( " Do Q\n" );
   10243 [ #  # ][ #  # ]:          0 :     if( nCheckWidth == 0 || nCheckHeight == 0 )
   10244                 :            :     {
   10245                 :            :         // #i97512# avoid invalid current matrix
   10246         [ #  # ]:          0 :         aLine.setLength( 0 );
   10247         [ #  # ]:          0 :         aLine.append( "\n%bitmap image /Im" );
   10248         [ #  # ]:          0 :         aLine.append( rBitmap.m_nObject );
   10249         [ #  # ]:          0 :         aLine.append( " scaled to zero size, omitted\n" );
   10250                 :            :     }
   10251         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
   10252                 :          0 : }
   10253                 :            : 
   10254                 :          0 : const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx& i_rBitmap, bool bDrawMask )
   10255                 :            : {
   10256         [ #  # ]:          0 :     BitmapEx aBitmap( i_rBitmap );
   10257         [ #  # ]:          0 :     if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
   10258                 :            :     {
   10259                 :          0 :         BmpConversion eConv = BMP_CONVERSION_8BIT_GREYS;
   10260 [ #  # ][ #  # ]:          0 :         int nDepth = aBitmap.GetBitmap().GetBitCount();
                 [ #  # ]
   10261         [ #  # ]:          0 :         if( nDepth <= 4 )
   10262                 :          0 :             eConv = BMP_CONVERSION_4BIT_GREYS;
   10263         [ #  # ]:          0 :         if( nDepth > 1 )
   10264         [ #  # ]:          0 :             aBitmap.Convert( eConv );
   10265                 :            :     }
   10266                 :          0 :     BitmapID aID;
   10267                 :          0 :     aID.m_aPixelSize        = aBitmap.GetSizePixel();
   10268         [ #  # ]:          0 :     aID.m_nSize             = aBitmap.GetBitCount();
   10269 [ #  # ][ #  # ]:          0 :     aID.m_nChecksum         = aBitmap.GetBitmap().GetChecksum();
                 [ #  # ]
   10270                 :          0 :     aID.m_nMaskChecksum     = 0;
   10271 [ #  # ][ #  # ]:          0 :     if( aBitmap.IsAlpha() )
   10272 [ #  # ][ #  # ]:          0 :         aID.m_nMaskChecksum = aBitmap.GetAlpha().GetChecksum();
                 [ #  # ]
   10273                 :            :     else
   10274                 :            :     {
   10275         [ #  # ]:          0 :         Bitmap aMask = aBitmap.GetMask();
   10276         [ #  # ]:          0 :         if( ! aMask.IsEmpty() )
   10277 [ #  # ][ #  # ]:          0 :             aID.m_nMaskChecksum = aMask.GetChecksum();
   10278                 :            :     }
   10279                 :          0 :     std::list< BitmapEmit >::const_iterator it;
   10280         [ #  # ]:          0 :     for( it = m_aBitmaps.begin(); it != m_aBitmaps.end(); ++it )
   10281                 :            :     {
   10282         [ #  # ]:          0 :         if( aID == it->m_aID )
   10283                 :          0 :             break;
   10284                 :            :     }
   10285         [ #  # ]:          0 :     if( it == m_aBitmaps.end() )
   10286                 :            :     {
   10287 [ #  # ][ #  # ]:          0 :         m_aBitmaps.push_front( BitmapEmit() );
                 [ #  # ]
   10288                 :          0 :         m_aBitmaps.front().m_aID        = aID;
   10289         [ #  # ]:          0 :         m_aBitmaps.front().m_aBitmap    = aBitmap;
   10290         [ #  # ]:          0 :         m_aBitmaps.front().m_nObject    = createObject();
   10291                 :          0 :         m_aBitmaps.front().m_bDrawMask  = bDrawMask;
   10292                 :          0 :         it = m_aBitmaps.begin();
   10293                 :            :     }
   10294                 :            : 
   10295                 :          0 :     OStringBuffer aObjName( 16 );
   10296         [ #  # ]:          0 :     aObjName.append( "Im" );
   10297         [ #  # ]:          0 :     aObjName.append( it->m_nObject );
   10298         [ #  # ]:          0 :     pushResource( ResXObject, aObjName.makeStringAndClear(), it->m_nObject );
   10299                 :            : 
   10300         [ #  # ]:          0 :     return *it;
   10301                 :            : }
   10302                 :            : 
   10303                 :          0 : void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize, const Bitmap& rBitmap )
   10304                 :            : {
   10305                 :          0 :     MARK( "drawBitmap (Bitmap)" );
   10306                 :            : 
   10307                 :            :     // #i40055# sanity check
   10308 [ #  # ][ #  # ]:          0 :     if( ! (rDestSize.Width() && rDestSize.Height()) )
                 [ #  # ]
   10309                 :          0 :         return;
   10310                 :            : 
   10311         [ #  # ]:          0 :     const BitmapEmit& rEmit = createBitmapEmit( BitmapEx( rBitmap ) );
   10312         [ #  # ]:          0 :     drawBitmap( rDestPoint, rDestSize, rEmit, Color( COL_TRANSPARENT ) );
   10313                 :            : }
   10314                 :            : 
   10315                 :          0 : void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize, const BitmapEx& rBitmap )
   10316                 :            : {
   10317                 :          0 :     MARK( "drawBitmap (BitmapEx)" );
   10318                 :            : 
   10319                 :            :     // #i40055# sanity check
   10320 [ #  # ][ #  # ]:          0 :     if( ! (rDestSize.Width() && rDestSize.Height()) )
                 [ #  # ]
   10321                 :          0 :         return;
   10322                 :            : 
   10323                 :          0 :     const BitmapEmit& rEmit = createBitmapEmit( rBitmap );
   10324         [ #  # ]:          0 :     drawBitmap( rDestPoint, rDestSize, rEmit, Color( COL_TRANSPARENT ) );
   10325                 :            : }
   10326                 :            : 
   10327                 :          0 : sal_Int32 PDFWriterImpl::createGradient( const Gradient& rGradient, const Size& rSize )
   10328                 :            : {
   10329         [ #  # ]:          0 :     Size aPtSize( lcl_convert( m_aGraphicsStack.front().m_aMapMode,
   10330                 :            :                                MapMode( MAP_POINT ),
   10331                 :            :                                getReferenceDevice(),
   10332 [ #  # ][ #  # ]:          0 :                                rSize ) );
         [ #  # ][ #  # ]
   10333                 :            :     // check if we already have this gradient
   10334                 :          0 :     std::list<GradientEmit>::iterator it;
   10335                 :            :     // rounding to point will generally lose some pixels
   10336                 :            :     // round up to point boundary
   10337                 :          0 :     aPtSize.Width()++;
   10338                 :          0 :     aPtSize.Height()++;
   10339         [ #  # ]:          0 :     for( it = m_aGradients.begin(); it != m_aGradients.end(); ++it )
   10340                 :            :     {
   10341 [ #  # ][ #  # ]:          0 :         if( it->m_aGradient == rGradient )
   10342                 :            :         {
   10343         [ #  # ]:          0 :             if( it->m_aSize == aPtSize )
   10344                 :          0 :                 break;
   10345                 :            :         }
   10346                 :            :     }
   10347         [ #  # ]:          0 :     if( it == m_aGradients.end() )
   10348                 :            :     {
   10349 [ #  # ][ #  # ]:          0 :         m_aGradients.push_front( GradientEmit() );
                 [ #  # ]
   10350         [ #  # ]:          0 :         m_aGradients.front().m_aGradient    = rGradient;
   10351         [ #  # ]:          0 :         m_aGradients.front().m_nObject      = createObject();
   10352                 :          0 :         m_aGradients.front().m_aSize        = aPtSize;
   10353                 :          0 :         it = m_aGradients.begin();
   10354                 :            :     }
   10355                 :            : 
   10356                 :          0 :     OStringBuffer aObjName( 16 );
   10357         [ #  # ]:          0 :     aObjName.append( 'P' );
   10358         [ #  # ]:          0 :     aObjName.append( it->m_nObject );
   10359         [ #  # ]:          0 :     pushResource( ResShading, aObjName.makeStringAndClear(), it->m_nObject );
   10360                 :            : 
   10361                 :          0 :     return it->m_nObject;
   10362                 :            : }
   10363                 :            : 
   10364                 :          0 : void PDFWriterImpl::drawGradient( const Rectangle& rRect, const Gradient& rGradient )
   10365                 :            : {
   10366         [ #  # ]:          0 :     MARK( "drawGradient (Rectangle)" );
   10367                 :            : 
   10368         [ #  # ]:          0 :     if( m_aContext.Version == PDFWriter::PDF_1_2 )
   10369                 :            :     {
   10370         [ #  # ]:          0 :         drawRectangle( rRect );
   10371                 :          0 :         return;
   10372                 :            :     }
   10373                 :            : 
   10374 [ #  # ][ #  # ]:          0 :     sal_Int32 nGradient = createGradient( rGradient, rRect.GetSize() );
   10375                 :            : 
   10376         [ #  # ]:          0 :     Point aTranslate( rRect.BottomLeft() );
   10377                 :          0 :     aTranslate += Point( 0, 1 );
   10378                 :            : 
   10379         [ #  # ]:          0 :     updateGraphicsState();
   10380                 :            : 
   10381                 :          0 :     OStringBuffer aLine( 80 );
   10382         [ #  # ]:          0 :     aLine.append( "q 1 0 0 1 " );
   10383 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendPoint( aTranslate, aLine );
   10384         [ #  # ]:          0 :     aLine.append( " cm " );
   10385                 :            :     // if a stroke is appended reset the clip region before stroke
   10386 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
   10387         [ #  # ]:          0 :         aLine.append( "q " );
   10388         [ #  # ]:          0 :     aLine.append( "0 0 " );
   10389 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rRect.GetWidth(), aLine, false );
                 [ #  # ]
   10390         [ #  # ]:          0 :     aLine.append( ' ' );
   10391 [ #  # ][ #  # ]:          0 :     m_aPages.back().appendMappedLength( (sal_Int32)rRect.GetHeight(), aLine, true );
                 [ #  # ]
   10392         [ #  # ]:          0 :     aLine.append( " re W n\n" );
   10393                 :            : 
   10394         [ #  # ]:          0 :     aLine.append( "/P" );
   10395         [ #  # ]:          0 :     aLine.append( nGradient );
   10396         [ #  # ]:          0 :     aLine.append( " sh " );
   10397 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_aLineColor != Color( COL_TRANSPARENT ) )
   10398                 :            :     {
   10399         [ #  # ]:          0 :         aLine.append( "Q 0 0 " );
   10400 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendMappedLength( (sal_Int32)rRect.GetWidth(), aLine, false );
                 [ #  # ]
   10401         [ #  # ]:          0 :         aLine.append( ' ' );
   10402 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendMappedLength( (sal_Int32)rRect.GetHeight(), aLine, true );
                 [ #  # ]
   10403         [ #  # ]:          0 :         aLine.append( " re S " );
   10404                 :            :     }
   10405         [ #  # ]:          0 :     aLine.append( "Q\n" );
   10406         [ #  # ]:          0 :     writeBuffer( aLine.getStr(), aLine.getLength() );
   10407                 :            : }
   10408                 :            : 
   10409                 :          0 : void PDFWriterImpl::drawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch )
   10410                 :            : {
   10411                 :          0 :     MARK( "drawHatch" );
   10412                 :            : 
   10413                 :          0 :     updateGraphicsState();
   10414                 :            : 
   10415         [ #  # ]:          0 :     if( rPolyPoly.Count() )
   10416                 :            :     {
   10417         [ #  # ]:          0 :         PolyPolygon     aPolyPoly( rPolyPoly );
   10418                 :            : 
   10419         [ #  # ]:          0 :         aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME );
   10420         [ #  # ]:          0 :         push( PUSH_LINECOLOR );
   10421         [ #  # ]:          0 :         setLineColor( rHatch.GetColor() );
   10422 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->ImplDrawHatch( aPolyPoly, rHatch, sal_False );
   10423 [ #  # ][ #  # ]:          0 :         pop();
   10424                 :            :     }
   10425                 :          0 : }
   10426                 :            : 
   10427                 :          0 : void PDFWriterImpl::drawWallpaper( const Rectangle& rRect, const Wallpaper& rWall )
   10428                 :            : {
   10429         [ #  # ]:          0 :     MARK( "drawWallpaper" );
   10430                 :            : 
   10431                 :          0 :     bool bDrawColor         = false;
   10432                 :          0 :     bool bDrawGradient      = false;
   10433                 :          0 :     bool bDrawBitmap        = false;
   10434                 :            : 
   10435         [ #  # ]:          0 :     BitmapEx aBitmap;
   10436                 :          0 :     Point aBmpPos = rRect.TopLeft();
   10437                 :          0 :     Size aBmpSize;
   10438 [ #  # ][ #  # ]:          0 :     if( rWall.IsBitmap() )
   10439                 :            :     {
   10440 [ #  # ][ #  # ]:          0 :         aBitmap = rWall.GetBitmap();
                 [ #  # ]
   10441                 :          0 :         aBmpSize = lcl_convert( aBitmap.GetPrefMapMode(),
   10442         [ #  # ]:          0 :                                 getMapMode(),
   10443                 :            :                                 getReferenceDevice(),
   10444   [ #  #  #  # ]:          0 :                                 aBitmap.GetPrefSize() );
   10445                 :          0 :         Rectangle aRect( rRect );
   10446 [ #  # ][ #  # ]:          0 :         if( rWall.IsRect() )
   10447                 :            :         {
   10448         [ #  # ]:          0 :             aRect = rWall.GetRect();
   10449                 :          0 :             aBmpPos = aRect.TopLeft();
   10450         [ #  # ]:          0 :             aBmpSize = aRect.GetSize();
   10451                 :            :         }
   10452 [ #  # ][ #  # ]:          0 :         if( rWall.GetStyle() != WALLPAPER_SCALE )
   10453                 :            :         {
   10454 [ #  # ][ #  # ]:          0 :             if( rWall.GetStyle() != WALLPAPER_TILE )
   10455                 :            :             {
   10456                 :          0 :                 bDrawBitmap     = true;
   10457 [ #  # ][ #  # ]:          0 :                 if( rWall.IsGradient() )
   10458                 :          0 :                     bDrawGradient = true;
   10459                 :            :                 else
   10460                 :          0 :                     bDrawColor = true;
   10461 [ #  # ][ #  #  :          0 :                 switch( rWall.GetStyle() )
          #  #  #  #  #  
                #  #  # ]
   10462                 :            :                 {
   10463                 :            :                     case WALLPAPER_TOPLEFT:
   10464                 :          0 :                         break;
   10465                 :            :                     case WALLPAPER_TOP:
   10466         [ #  # ]:          0 :                         aBmpPos.X() += (aRect.GetWidth()-aBmpSize.Width())/2;
   10467                 :          0 :                         break;
   10468                 :            :                     case WALLPAPER_LEFT:
   10469         [ #  # ]:          0 :                         aBmpPos.Y() += (aRect.GetHeight()-aBmpSize.Height())/2;
   10470                 :          0 :                         break;
   10471                 :            :                     case WALLPAPER_TOPRIGHT:
   10472         [ #  # ]:          0 :                         aBmpPos.X() += aRect.GetWidth()-aBmpSize.Width();
   10473                 :          0 :                         break;
   10474                 :            :                     case WALLPAPER_CENTER:
   10475         [ #  # ]:          0 :                         aBmpPos.X() += (aRect.GetWidth()-aBmpSize.Width())/2;
   10476         [ #  # ]:          0 :                         aBmpPos.Y() += (aRect.GetHeight()-aBmpSize.Height())/2;
   10477                 :          0 :                         break;
   10478                 :            :                     case WALLPAPER_RIGHT:
   10479         [ #  # ]:          0 :                         aBmpPos.X() += aRect.GetWidth()-aBmpSize.Width();
   10480         [ #  # ]:          0 :                         aBmpPos.Y() += (aRect.GetHeight()-aBmpSize.Height())/2;
   10481                 :          0 :                         break;
   10482                 :            :                     case WALLPAPER_BOTTOMLEFT:
   10483         [ #  # ]:          0 :                         aBmpPos.Y() += aRect.GetHeight()-aBmpSize.Height();
   10484                 :          0 :                         break;
   10485                 :            :                     case WALLPAPER_BOTTOM:
   10486         [ #  # ]:          0 :                         aBmpPos.X() += (aRect.GetWidth()-aBmpSize.Width())/2;
   10487         [ #  # ]:          0 :                         aBmpPos.Y() += aRect.GetHeight()-aBmpSize.Height();
   10488                 :          0 :                         break;
   10489                 :            :                     case WALLPAPER_BOTTOMRIGHT:
   10490         [ #  # ]:          0 :                         aBmpPos.X() += aRect.GetWidth()-aBmpSize.Width();
   10491         [ #  # ]:          0 :                         aBmpPos.Y() += aRect.GetHeight()-aBmpSize.Height();
   10492                 :          0 :                         break;
   10493                 :            :                     default: ;
   10494                 :            :                 }
   10495                 :            :             }
   10496                 :            :             else
   10497                 :            :             {
   10498                 :            :                 // push the bitmap
   10499 [ #  # ][ #  # ]:          0 :                 const BitmapEmit& rEmit = createBitmapEmit( BitmapEx( aBitmap ) );
                 [ #  # ]
   10500                 :            : 
   10501                 :            :                 // convert to page coordinates; this needs to be done here
   10502                 :            :                 // since the emit does not know the page anymore
   10503         [ #  # ]:          0 :                 Rectangle aConvertRect( aBmpPos, aBmpSize );
   10504 [ #  # ][ #  # ]:          0 :                 m_aPages.back().convertRect( aConvertRect );
   10505                 :            : 
   10506                 :          0 :                 OStringBuffer aNameBuf(16);
   10507         [ #  # ]:          0 :                 aNameBuf.append( "Im" );
   10508         [ #  # ]:          0 :                 aNameBuf.append( rEmit.m_nObject );
   10509                 :          0 :                 OString aImageName( aNameBuf.makeStringAndClear() );
   10510                 :            : 
   10511                 :            :                 // push the pattern
   10512                 :          0 :                 OStringBuffer aTilingStream( 32 );
   10513 [ #  # ][ #  # ]:          0 :                 appendFixedInt( aConvertRect.GetWidth(), aTilingStream );
   10514         [ #  # ]:          0 :                 aTilingStream.append( " 0 0 " );
   10515 [ #  # ][ #  # ]:          0 :                 appendFixedInt( aConvertRect.GetHeight(), aTilingStream );
   10516         [ #  # ]:          0 :                 aTilingStream.append( " 0 0 cm\n/" );
   10517         [ #  # ]:          0 :                 aTilingStream.append( aImageName );
   10518         [ #  # ]:          0 :                 aTilingStream.append( " Do\n" );
   10519                 :            : 
   10520 [ #  # ][ #  # ]:          0 :                 m_aTilings.push_back( TilingEmit() );
   10521 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_nObject         = createObject();
   10522 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_aRectangle      = Rectangle( Point( 0, 0 ), aConvertRect.GetSize() );
                 [ #  # ]
   10523 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_pTilingStream   = new SvMemoryStream();
                 [ #  # ]
   10524 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_pTilingStream->Write( aTilingStream.getStr(), aTilingStream.getLength() );
   10525                 :            :                 // phase the tiling so wallpaper begins on upper left
   10526 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_aTransform.matrix[2] = double(aConvertRect.Left() % aConvertRect.GetWidth()) / fDivisor;
   10527 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_aTransform.matrix[5] = double(aConvertRect.Top() % aConvertRect.GetHeight()) / fDivisor;
   10528 [ #  # ][ #  # ]:          0 :                 m_aTilings.back().m_aResources.m_aXObjects[aImageName] = rEmit.m_nObject;
   10529                 :            : 
   10530         [ #  # ]:          0 :                 updateGraphicsState();
   10531                 :            : 
   10532                 :          0 :                 OStringBuffer aObjName( 16 );
   10533         [ #  # ]:          0 :                 aObjName.append( 'P' );
   10534 [ #  # ][ #  # ]:          0 :                 aObjName.append( m_aTilings.back().m_nObject );
   10535                 :          0 :                 OString aPatternName( aObjName.makeStringAndClear() );
   10536 [ #  # ][ #  # ]:          0 :                 pushResource( ResPattern, aPatternName, m_aTilings.back().m_nObject );
   10537                 :            : 
   10538                 :            :                 // fill a rRect with the pattern
   10539                 :          0 :                 OStringBuffer aLine( 100 );
   10540         [ #  # ]:          0 :                 aLine.append( "q /Pattern cs /" );
   10541         [ #  # ]:          0 :                 aLine.append( aPatternName );
   10542         [ #  # ]:          0 :                 aLine.append( " scn " );
   10543 [ #  # ][ #  # ]:          0 :                 m_aPages.back().appendRect( rRect, aLine );
   10544         [ #  # ]:          0 :                 aLine.append( " f Q\n" );
   10545         [ #  # ]:          0 :                 writeBuffer( aLine.getStr(), aLine.getLength() );
   10546                 :            :             }
   10547                 :            :         }
   10548                 :            :         else
   10549                 :            :         {
   10550                 :          0 :             aBmpPos     = aRect.TopLeft();
   10551         [ #  # ]:          0 :             aBmpSize    = aRect.GetSize();
   10552                 :          0 :             bDrawBitmap = true;
   10553                 :            :         }
   10554                 :            : 
   10555 [ #  # ][ #  # ]:          0 :         if( aBitmap.IsTransparent() )
   10556                 :            :         {
   10557 [ #  # ][ #  # ]:          0 :             if( rWall.IsGradient() )
   10558                 :          0 :                 bDrawGradient = true;
   10559                 :            :             else
   10560                 :          0 :                 bDrawColor = true;
   10561                 :            :         }
   10562                 :            :     }
   10563 [ #  # ][ #  # ]:          0 :     else if( rWall.IsGradient() )
   10564                 :          0 :         bDrawGradient = true;
   10565                 :            :     else
   10566                 :          0 :         bDrawColor = true;
   10567                 :            : 
   10568         [ #  # ]:          0 :     if( bDrawGradient )
   10569                 :            :     {
   10570 [ #  # ][ #  # ]:          0 :         drawGradient( rRect, rWall.GetGradient() );
                 [ #  # ]
   10571                 :            :     }
   10572         [ #  # ]:          0 :     if( bDrawColor )
   10573                 :            :     {
   10574         [ #  # ]:          0 :         Color aOldLineColor = m_aGraphicsStack.front().m_aLineColor;
   10575         [ #  # ]:          0 :         Color aOldFillColor = m_aGraphicsStack.front().m_aFillColor;
   10576         [ #  # ]:          0 :         setLineColor( Color( COL_TRANSPARENT ) );
   10577 [ #  # ][ #  # ]:          0 :         setFillColor( rWall.GetColor() );
   10578         [ #  # ]:          0 :         drawRectangle( rRect );
   10579         [ #  # ]:          0 :         setLineColor( aOldLineColor );
   10580         [ #  # ]:          0 :         setFillColor( aOldFillColor );
   10581                 :            :     }
   10582         [ #  # ]:          0 :     if( bDrawBitmap )
   10583                 :            :     {
   10584                 :            :         // set temporary clip region since aBmpPos and aBmpSize
   10585                 :            :         // may be outside rRect
   10586                 :          0 :         OStringBuffer aLine( 20 );
   10587         [ #  # ]:          0 :         aLine.append( "q " );
   10588 [ #  # ][ #  # ]:          0 :         m_aPages.back().appendRect( rRect, aLine );
   10589         [ #  # ]:          0 :         aLine.append( " W n\n" );
   10590         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
   10591         [ #  # ]:          0 :         drawBitmap( aBmpPos, aBmpSize, aBitmap );
   10592         [ #  # ]:          0 :         writeBuffer( "Q\n", 2 );
   10593         [ #  # ]:          0 :     }
   10594                 :          0 : }
   10595                 :            : 
   10596                 :          0 : void PDFWriterImpl::updateGraphicsState()
   10597                 :            : {
   10598                 :          0 :     OStringBuffer aLine( 256 );
   10599         [ #  # ]:          0 :     GraphicsState& rNewState = m_aGraphicsStack.front();
   10600                 :            :     // first set clip region since it might invalidate everything else
   10601                 :            : 
   10602         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateClipRegion) )
   10603                 :            :     {
   10604                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateClipRegion;
   10605                 :            : 
   10606 [ #  # ][ #  # ]:          0 :         if( m_aCurrentPDFState.m_bClipRegion != rNewState.m_bClipRegion ||
         [ #  # ][ #  # ]
   10607         [ #  # ]:          0 :             ( rNewState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion != rNewState.m_aClipRegion ) )
   10608                 :            :         {
   10609 [ #  # ][ #  # ]:          0 :             if( m_aCurrentPDFState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion.count() )
         [ #  # ][ #  # ]
   10610                 :            :             {
   10611         [ #  # ]:          0 :                 aLine.append( "Q " );
   10612                 :            :                 // invalidate everything but the clip region
   10613 [ #  # ][ #  # ]:          0 :                 m_aCurrentPDFState = GraphicsState();
                 [ #  # ]
   10614                 :          0 :                 rNewState.m_nUpdateFlags = sal::static_int_cast<sal_uInt16>(~GraphicsState::updateClipRegion);
   10615                 :            :             }
   10616 [ #  # ][ #  # ]:          0 :             if( rNewState.m_bClipRegion && rNewState.m_aClipRegion.count() )
         [ #  # ][ #  # ]
   10617                 :            :             {
   10618                 :            :                 // clip region is always stored in private PDF mapmode
   10619         [ #  # ]:          0 :                 MapMode aNewMapMode = rNewState.m_aMapMode;
   10620         [ #  # ]:          0 :                 rNewState.m_aMapMode = m_aMapMode;
   10621 [ #  # ][ #  # ]:          0 :                 getReferenceDevice()->SetMapMode( rNewState.m_aMapMode );
   10622         [ #  # ]:          0 :                 m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode;
   10623                 :            : 
   10624         [ #  # ]:          0 :                 aLine.append( "q " );
   10625 [ #  # ][ #  # ]:          0 :                 m_aPages.back().appendPolyPolygon( rNewState.m_aClipRegion, aLine );
   10626         [ #  # ]:          0 :                 aLine.append( "W* n\n" );
   10627         [ #  # ]:          0 :                 rNewState.m_aMapMode = aNewMapMode;
   10628 [ #  # ][ #  # ]:          0 :                 getReferenceDevice()->SetMapMode( rNewState.m_aMapMode );
   10629 [ #  # ][ #  # ]:          0 :                 m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode;
   10630                 :            :             }
   10631                 :            :         }
   10632                 :            :     }
   10633                 :            : 
   10634         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateMapMode) )
   10635                 :            :     {
   10636                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateMapMode;
   10637 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->SetMapMode( rNewState.m_aMapMode );
   10638                 :            :     }
   10639                 :            : 
   10640         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateFont) )
   10641                 :            :     {
   10642                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateFont;
   10643 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->SetFont( rNewState.m_aFont );
   10644 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->ImplNewFont();
   10645                 :            :     }
   10646                 :            : 
   10647         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateLayoutMode) )
   10648                 :            :     {
   10649                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateLayoutMode;
   10650 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->SetLayoutMode( rNewState.m_nLayoutMode );
   10651                 :            :     }
   10652                 :            : 
   10653         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateDigitLanguage) )
   10654                 :            :     {
   10655                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateDigitLanguage;
   10656 [ #  # ][ #  # ]:          0 :         getReferenceDevice()->SetDigitLanguage( rNewState.m_aDigitLanguage );
   10657                 :            :     }
   10658                 :            : 
   10659         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateLineColor) )
   10660                 :            :     {
   10661                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateLineColor;
   10662   [ #  #  #  # ]:          0 :         if( m_aCurrentPDFState.m_aLineColor != rNewState.m_aLineColor &&
                 [ #  # ]
   10663         [ #  # ]:          0 :             rNewState.m_aLineColor != Color( COL_TRANSPARENT ) )
   10664                 :            :         {
   10665         [ #  # ]:          0 :             appendStrokingColor( rNewState.m_aLineColor, aLine );
   10666         [ #  # ]:          0 :             aLine.append( "\n" );
   10667                 :            :         }
   10668                 :            :     }
   10669                 :            : 
   10670         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateFillColor) )
   10671                 :            :     {
   10672                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateFillColor;
   10673   [ #  #  #  # ]:          0 :         if( m_aCurrentPDFState.m_aFillColor != rNewState.m_aFillColor &&
                 [ #  # ]
   10674         [ #  # ]:          0 :             rNewState.m_aFillColor != Color( COL_TRANSPARENT ) )
   10675                 :            :         {
   10676         [ #  # ]:          0 :             appendNonStrokingColor( rNewState.m_aFillColor, aLine );
   10677         [ #  # ]:          0 :             aLine.append( "\n" );
   10678                 :            :         }
   10679                 :            :     }
   10680                 :            : 
   10681         [ #  # ]:          0 :     if( (rNewState.m_nUpdateFlags & GraphicsState::updateTransparentPercent) )
   10682                 :            :     {
   10683                 :          0 :         rNewState.m_nUpdateFlags &= ~GraphicsState::updateTransparentPercent;
   10684         [ #  # ]:          0 :         if( m_aContext.Version >= PDFWriter::PDF_1_4 && m_aCurrentPDFState.m_nTransparentPercent != rNewState.m_nTransparentPercent )
   10685                 :            :         {
   10686                 :            :             // TODO: switch extended graphicsstate
   10687                 :            :         }
   10688                 :            :     }
   10689                 :            : 
   10690                 :            :     // everything is up to date now
   10691 [ #  # ][ #  # ]:          0 :     m_aCurrentPDFState = m_aGraphicsStack.front();
   10692         [ #  # ]:          0 :     if( aLine.getLength() )
   10693         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
   10694                 :          0 : }
   10695                 :            : 
   10696                 :            : /* #i47544# imitate OutputDevice behaviour:
   10697                 :            : *  if a font with a nontransparent color is set, it overwrites the current
   10698                 :            : *  text color. OTOH setting the text color will overwrite the color of the font.
   10699                 :            : */
   10700                 :          0 : void PDFWriterImpl::setFont( const Font& rFont )
   10701                 :            : {
   10702         [ #  # ]:          0 :     Color aColor = rFont.GetColor();
   10703         [ #  # ]:          0 :     if( aColor == Color( COL_TRANSPARENT ) )
   10704 [ #  # ][ #  # ]:          0 :         aColor = m_aGraphicsStack.front().m_aFont.GetColor();
   10705 [ #  # ][ #  # ]:          0 :     m_aGraphicsStack.front().m_aFont = rFont;
   10706 [ #  # ][ #  # ]:          0 :     m_aGraphicsStack.front().m_aFont.SetColor( aColor );
   10707         [ #  # ]:          0 :     m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateFont;
   10708                 :          0 : }
   10709                 :            : 
   10710                 :          0 : void PDFWriterImpl::push( sal_uInt16 nFlags )
   10711                 :            : {
   10712                 :            :     OSL_ENSURE( m_aGraphicsStack.size() > 0, "invalid graphics stack" );
   10713                 :          0 :     m_aGraphicsStack.push_front( m_aGraphicsStack.front() );
   10714                 :          0 :     m_aGraphicsStack.front().m_nFlags = nFlags;
   10715                 :          0 : }
   10716                 :            : 
   10717                 :          0 : void PDFWriterImpl::pop()
   10718                 :            : {
   10719                 :            :     OSL_ENSURE( m_aGraphicsStack.size() > 1, "pop without push" );
   10720         [ #  # ]:          0 :     if( m_aGraphicsStack.size() < 2 )
   10721                 :          0 :         return;
   10722                 :            : 
   10723 [ #  # ][ #  # ]:          0 :     GraphicsState aState = m_aGraphicsStack.front();
   10724         [ #  # ]:          0 :     m_aGraphicsStack.pop_front();
   10725         [ #  # ]:          0 :     GraphicsState& rOld = m_aGraphicsStack.front();
   10726                 :            : 
   10727                 :            :     // move those parameters back that were not pushed
   10728                 :            :     // in the first place
   10729         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_LINECOLOR) )
   10730         [ #  # ]:          0 :         setLineColor( aState.m_aLineColor );
   10731         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_FILLCOLOR) )
   10732         [ #  # ]:          0 :         setFillColor( aState.m_aFillColor );
   10733         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_FONT) )
   10734         [ #  # ]:          0 :         setFont( aState.m_aFont );
   10735         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_TEXTCOLOR) )
   10736 [ #  # ][ #  # ]:          0 :         setTextColor( aState.m_aFont.GetColor() );
   10737         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_MAPMODE) )
   10738         [ #  # ]:          0 :         setMapMode( aState.m_aMapMode );
   10739         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_CLIPREGION) )
   10740                 :            :     {
   10741                 :            :         // do not use setClipRegion here
   10742                 :            :         // it would convert again assuming the current mapmode
   10743         [ #  # ]:          0 :         rOld.m_aClipRegion = aState.m_aClipRegion;
   10744                 :          0 :         rOld.m_bClipRegion = aState.m_bClipRegion;
   10745                 :            :     }
   10746         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_TEXTLINECOLOR ) )
   10747         [ #  # ]:          0 :         setTextLineColor( aState.m_aTextLineColor );
   10748         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_OVERLINECOLOR ) )
   10749         [ #  # ]:          0 :         setOverlineColor( aState.m_aOverlineColor );
   10750         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_TEXTALIGN ) )
   10751 [ #  # ][ #  # ]:          0 :         setTextAlign( aState.m_aFont.GetAlign() );
   10752         [ #  # ]:          0 :     if( ! (aState.m_nFlags & PUSH_TEXTFILLCOLOR) )
   10753 [ #  # ][ #  # ]:          0 :         setTextFillColor( aState.m_aFont.GetFillColor() );
   10754                 :          0 :     if( ! (aState.m_nFlags & PUSH_REFPOINT) )
   10755                 :            :     {
   10756                 :            :         // what ?
   10757                 :            :     }
   10758                 :            :     // invalidate graphics state
   10759 [ #  # ][ #  # ]:          0 :     m_aGraphicsStack.front().m_nUpdateFlags = sal::static_int_cast<sal_uInt16>(~0U);
   10760                 :            : }
   10761                 :            : 
   10762                 :          0 : void PDFWriterImpl::setMapMode( const MapMode& rMapMode )
   10763                 :            : {
   10764                 :          0 :     m_aGraphicsStack.front().m_aMapMode = rMapMode;
   10765                 :          0 :     getReferenceDevice()->SetMapMode( rMapMode );
   10766                 :          0 :     m_aCurrentPDFState.m_aMapMode = rMapMode;
   10767                 :          0 : }
   10768                 :            : 
   10769                 :          0 : void PDFWriterImpl::setClipRegion( const basegfx::B2DPolyPolygon& rRegion )
   10770                 :            : {
   10771 [ #  # ][ #  # ]:          0 :     basegfx::B2DPolyPolygon aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode );
                 [ #  # ]
   10772 [ #  # ][ #  # ]:          0 :     aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode );
         [ #  # ][ #  # ]
   10773 [ #  # ][ #  # ]:          0 :     m_aGraphicsStack.front().m_aClipRegion = aRegion;
   10774         [ #  # ]:          0 :     m_aGraphicsStack.front().m_bClipRegion = true;
   10775 [ #  # ][ #  # ]:          0 :     m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion;
   10776                 :          0 : }
   10777                 :            : 
   10778                 :          0 : void PDFWriterImpl::moveClipRegion( sal_Int32 nX, sal_Int32 nY )
   10779                 :            : {
   10780 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_bClipRegion && m_aGraphicsStack.front().m_aClipRegion.count() )
                 [ #  # ]
   10781                 :            :     {
   10782         [ #  # ]:          0 :         Point aPoint( lcl_convert( m_aGraphicsStack.front().m_aMapMode,
   10783                 :            :                                    m_aMapMode,
   10784                 :            :                                    getReferenceDevice(),
   10785 [ #  # ][ #  # ]:          0 :                                    Point( nX, nY ) ) );
   10786         [ #  # ]:          0 :         aPoint -= lcl_convert( m_aGraphicsStack.front().m_aMapMode,
   10787                 :            :                                m_aMapMode,
   10788                 :            :                                getReferenceDevice(),
   10789 [ #  # ][ #  # ]:          0 :                                Point() );
   10790         [ #  # ]:          0 :         basegfx::B2DHomMatrix aMat;
   10791         [ #  # ]:          0 :         aMat.translate( aPoint.X(), aPoint.Y() );
   10792 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aClipRegion.transform( aMat );
   10793 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion;
   10794                 :            :     }
   10795                 :          0 : }
   10796                 :            : 
   10797                 :          0 : bool PDFWriterImpl::intersectClipRegion( const Rectangle& rRect )
   10798                 :            : {
   10799                 :            :     basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect(
   10800 [ #  # ][ #  # ]:          0 :         basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
         [ #  # ][ #  # ]
   10801 [ #  # ][ #  # ]:          0 :     return intersectClipRegion( aRect );
   10802                 :            : }
   10803                 :            : 
   10804                 :            : 
   10805                 :          0 : bool PDFWriterImpl::intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion )
   10806                 :            : {
   10807 [ #  # ][ #  # ]:          0 :     basegfx::B2DPolyPolygon aRegion( getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ) );
                 [ #  # ]
   10808 [ #  # ][ #  # ]:          0 :     aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode );
         [ #  # ][ #  # ]
   10809         [ #  # ]:          0 :     m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion;
   10810 [ #  # ][ #  # ]:          0 :     if( m_aGraphicsStack.front().m_bClipRegion )
   10811                 :            :     {
   10812 [ #  # ][ #  # ]:          0 :         basegfx::B2DPolyPolygon aOld( basegfx::tools::prepareForPolygonOperation( m_aGraphicsStack.front().m_aClipRegion ) );
   10813 [ #  # ][ #  # ]:          0 :         aRegion = basegfx::tools::prepareForPolygonOperation( aRegion );
                 [ #  # ]
   10814 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aClipRegion = basegfx::tools::solvePolygonOperationAnd( aOld, aRegion );
         [ #  # ][ #  # ]
                 [ #  # ]
   10815                 :            :     }
   10816                 :            :     else
   10817                 :            :     {
   10818 [ #  # ][ #  # ]:          0 :         m_aGraphicsStack.front().m_aClipRegion = aRegion;
   10819         [ #  # ]:          0 :         m_aGraphicsStack.front().m_bClipRegion = true;
   10820                 :            :     }
   10821         [ #  # ]:          0 :     return true;
   10822                 :            : }
   10823                 :            : 
   10824                 :          0 : void PDFWriterImpl::createNote( const Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr )
   10825                 :            : {
   10826         [ #  # ]:          0 :     if( nPageNr < 0 )
   10827                 :          0 :         nPageNr = m_nCurrentPage;
   10828                 :            : 
   10829 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   10830                 :          0 :         return;
   10831                 :            : 
   10832         [ #  # ]:          0 :     m_aNotes.push_back( PDFNoteEntry() );
   10833                 :          0 :     m_aNotes.back().m_nObject       = createObject();
   10834                 :          0 :     m_aNotes.back().m_aContents     = rNote;
   10835                 :          0 :     m_aNotes.back().m_aRect         = rRect;
   10836                 :            :     // convert to default user space now, since the mapmode may change
   10837                 :          0 :     m_aPages[nPageNr].convertRect( m_aNotes.back().m_aRect );
   10838                 :            : 
   10839                 :            :     // insert note to page's annotation list
   10840                 :          0 :     m_aPages[ nPageNr ].m_aAnnotations.push_back( m_aNotes.back().m_nObject );
   10841                 :            : }
   10842                 :            : 
   10843                 :          0 : sal_Int32 PDFWriterImpl::createLink( const Rectangle& rRect, sal_Int32 nPageNr )
   10844                 :            : {
   10845         [ #  # ]:          0 :     if( nPageNr < 0 )
   10846                 :          0 :         nPageNr = m_nCurrentPage;
   10847                 :            : 
   10848 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   10849                 :          0 :         return -1;
   10850                 :            : 
   10851                 :          0 :     sal_Int32 nRet = m_aLinks.size();
   10852                 :            : 
   10853         [ #  # ]:          0 :     m_aLinks.push_back( PDFLink() );
   10854                 :          0 :     m_aLinks.back().m_nObject   = createObject();
   10855                 :          0 :     m_aLinks.back().m_nPage     = nPageNr;
   10856                 :          0 :     m_aLinks.back().m_aRect     = rRect;
   10857                 :            :     // convert to default user space now, since the mapmode may change
   10858                 :          0 :     m_aPages[nPageNr].convertRect( m_aLinks.back().m_aRect );
   10859                 :            : 
   10860                 :            :     // insert link to page's annotation list
   10861                 :          0 :     m_aPages[ nPageNr ].m_aAnnotations.push_back( m_aLinks.back().m_nObject );
   10862                 :            : 
   10863                 :          0 :     return nRet;
   10864                 :            : }
   10865                 :            : 
   10866                 :            : //--->i56629
   10867                 :          0 : sal_Int32 PDFWriterImpl::createNamedDest( const rtl::OUString& sDestName, const Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
   10868                 :            : {
   10869         [ #  # ]:          0 :     if( nPageNr < 0 )
   10870                 :          0 :         nPageNr = m_nCurrentPage;
   10871                 :            : 
   10872 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   10873                 :          0 :         return -1;
   10874                 :            : 
   10875                 :          0 :     sal_Int32 nRet = m_aNamedDests.size();
   10876                 :            : 
   10877         [ #  # ]:          0 :     m_aNamedDests.push_back( PDFNamedDest() );
   10878                 :          0 :     m_aNamedDests.back().m_aDestName = sDestName;
   10879                 :          0 :     m_aNamedDests.back().m_nPage = nPageNr;
   10880                 :          0 :     m_aNamedDests.back().m_eType = eType;
   10881                 :          0 :     m_aNamedDests.back().m_aRect = rRect;
   10882                 :            :     // convert to default user space now, since the mapmode may change
   10883                 :          0 :     m_aPages[nPageNr].convertRect( m_aNamedDests.back().m_aRect );
   10884                 :            : 
   10885                 :          0 :     return nRet;
   10886                 :            : }
   10887                 :            : //<---i56629
   10888                 :            : 
   10889                 :          0 : sal_Int32 PDFWriterImpl::createDest( const Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
   10890                 :            : {
   10891         [ #  # ]:          0 :     if( nPageNr < 0 )
   10892                 :          0 :         nPageNr = m_nCurrentPage;
   10893                 :            : 
   10894 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   10895                 :          0 :         return -1;
   10896                 :            : 
   10897                 :          0 :     sal_Int32 nRet = m_aDests.size();
   10898                 :            : 
   10899         [ #  # ]:          0 :     m_aDests.push_back( PDFDest() );
   10900                 :          0 :     m_aDests.back().m_nPage = nPageNr;
   10901                 :          0 :     m_aDests.back().m_eType = eType;
   10902                 :          0 :     m_aDests.back().m_aRect = rRect;
   10903                 :            :     // convert to default user space now, since the mapmode may change
   10904                 :          0 :     m_aPages[nPageNr].convertRect( m_aDests.back().m_aRect );
   10905                 :            : 
   10906                 :          0 :     return nRet;
   10907                 :            : }
   10908                 :            : 
   10909                 :          0 : sal_Int32 PDFWriterImpl::registerDestReference( sal_Int32 nDestId, const Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
   10910                 :            : {
   10911                 :          0 :     return m_aDestinationIdTranslation[ nDestId ] = createDest( rRect, nPageNr, eType );
   10912                 :            : }
   10913                 :            : 
   10914                 :          0 : sal_Int32 PDFWriterImpl::setLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId )
   10915                 :            : {
   10916 [ #  # ][ #  # ]:          0 :     if( nLinkId < 0 || nLinkId >= (sal_Int32)m_aLinks.size() )
                 [ #  # ]
   10917                 :          0 :         return -1;
   10918 [ #  # ][ #  # ]:          0 :     if( nDestId < 0 || nDestId >= (sal_Int32)m_aDests.size() )
                 [ #  # ]
   10919                 :          0 :         return -2;
   10920                 :            : 
   10921                 :          0 :     m_aLinks[ nLinkId ].m_nDest = nDestId;
   10922                 :            : 
   10923                 :          0 :     return 0;
   10924                 :            : }
   10925                 :            : 
   10926                 :          0 : sal_Int32 PDFWriterImpl::setLinkURL( sal_Int32 nLinkId, const OUString& rURL )
   10927                 :            : {
   10928 [ #  # ][ #  # ]:          0 :     if( nLinkId < 0 || nLinkId >= (sal_Int32)m_aLinks.size() )
                 [ #  # ]
   10929                 :          0 :         return -1;
   10930                 :            : 
   10931                 :          0 :     m_aLinks[ nLinkId ].m_nDest = -1;
   10932                 :            : 
   10933                 :            :     using namespace ::com::sun::star;
   10934                 :            : 
   10935         [ #  # ]:          0 :     if (!m_xTrans.is())
   10936                 :            :     {
   10937         [ #  # ]:          0 :         uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
   10938 [ #  # ][ #  # ]:          0 :         m_xTrans = util::URLTransformer::create(xContext);;
   10939                 :            :     }
   10940                 :            : 
   10941                 :          0 :     util::URL aURL;
   10942                 :          0 :     aURL.Complete = rURL;
   10943                 :            : 
   10944 [ #  # ][ #  # ]:          0 :     m_xTrans->parseStrict( aURL );
   10945                 :            : 
   10946                 :          0 :     m_aLinks[ nLinkId ].m_aURL  = aURL.Complete;
   10947                 :            : 
   10948                 :          0 :     return 0;
   10949                 :            : }
   10950                 :            : 
   10951                 :          0 : void PDFWriterImpl::setLinkPropertyId( sal_Int32 nLinkId, sal_Int32 nPropertyId )
   10952                 :            : {
   10953                 :          0 :     m_aLinkPropertyMap[ nPropertyId ] = nLinkId;
   10954                 :          0 : }
   10955                 :            : 
   10956                 :          0 : sal_Int32 PDFWriterImpl::createOutlineItem( sal_Int32 nParent, const OUString& rText, sal_Int32 nDestID )
   10957                 :            : {
   10958                 :            :     // create new item
   10959                 :          0 :     sal_Int32 nNewItem = m_aOutline.size();
   10960         [ #  # ]:          0 :     m_aOutline.push_back( PDFOutlineEntry() );
   10961                 :            : 
   10962                 :            :     // set item attributes
   10963                 :          0 :     setOutlineItemParent( nNewItem, nParent );
   10964                 :          0 :     setOutlineItemText( nNewItem, rText );
   10965                 :          0 :     setOutlineItemDest( nNewItem, nDestID );
   10966                 :            : 
   10967                 :          0 :     return nNewItem;
   10968                 :            : }
   10969                 :            : 
   10970                 :          0 : sal_Int32 PDFWriterImpl::setOutlineItemParent( sal_Int32 nItem, sal_Int32 nNewParent )
   10971                 :            : {
   10972 [ #  # ][ #  # ]:          0 :     if( nItem < 1 || nItem >= (sal_Int32)m_aOutline.size() )
                 [ #  # ]
   10973                 :          0 :         return -1;
   10974                 :            : 
   10975                 :          0 :     int nRet = 0;
   10976                 :            : 
   10977 [ #  # ][ #  # ]:          0 :     if( nNewParent < 0 || nNewParent >= (sal_Int32)m_aOutline.size() || nNewParent == nItem )
         [ #  # ][ #  # ]
   10978                 :            :     {
   10979                 :          0 :         nNewParent = 0;
   10980                 :          0 :         nRet = -2;
   10981                 :            :     }
   10982                 :            :     // remove item from previous parent
   10983                 :          0 :     sal_Int32 nParentID = m_aOutline[ nItem ].m_nParentID;
   10984 [ #  # ][ #  # ]:          0 :     if( nParentID >= 0 && nParentID < (sal_Int32)m_aOutline.size() )
                 [ #  # ]
   10985                 :            :     {
   10986                 :          0 :         PDFOutlineEntry& rParent = m_aOutline[ nParentID ];
   10987                 :            : 
   10988   [ #  #  #  # ]:          0 :         for( std::vector<sal_Int32>::iterator it = rParent.m_aChildren.begin();
                 [ #  # ]
   10989                 :          0 :              it != rParent.m_aChildren.end(); ++it )
   10990                 :            :         {
   10991 [ #  # ][ #  # ]:          0 :             if( *it == nItem )
   10992                 :            :             {
   10993         [ #  # ]:          0 :                 rParent.m_aChildren.erase( it );
   10994                 :          0 :                 break;
   10995                 :            :             }
   10996                 :            :         }
   10997                 :            :     }
   10998                 :            : 
   10999                 :            :     // insert item to new parent's list of children
   11000                 :          0 :     m_aOutline[ nNewParent ].m_aChildren.push_back( nItem );
   11001                 :            : 
   11002                 :          0 :     return nRet;
   11003                 :            : }
   11004                 :            : 
   11005                 :          0 : sal_Int32 PDFWriterImpl::setOutlineItemText( sal_Int32 nItem, const OUString& rText )
   11006                 :            : {
   11007 [ #  # ][ #  # ]:          0 :     if( nItem < 1 || nItem >= (sal_Int32)m_aOutline.size() )
                 [ #  # ]
   11008                 :          0 :         return -1;
   11009                 :            : 
   11010 [ #  # ][ #  # ]:          0 :     m_aOutline[ nItem ].m_aTitle = psp::WhitespaceToSpace( rText );
                 [ #  # ]
   11011                 :          0 :     return 0;
   11012                 :            : }
   11013                 :            : 
   11014                 :          0 : sal_Int32 PDFWriterImpl::setOutlineItemDest( sal_Int32 nItem, sal_Int32 nDestID )
   11015                 :            : {
   11016 [ #  # ][ #  # ]:          0 :     if( nItem < 1 || nItem >= (sal_Int32)m_aOutline.size() ) // item does not exist
                 [ #  # ]
   11017                 :          0 :         return -1;
   11018 [ #  # ][ #  # ]:          0 :     if( nDestID < 0 || nDestID >= (sal_Int32)m_aDests.size() ) // dest does not exist
                 [ #  # ]
   11019                 :          0 :         return -2;
   11020                 :          0 :     m_aOutline[nItem].m_nDestID = nDestID;
   11021                 :          0 :     return 0;
   11022                 :            : }
   11023                 :            : 
   11024                 :          0 : const sal_Char* PDFWriterImpl::getStructureTag( PDFWriter::StructElement eType )
   11025                 :            : {
   11026 [ #  # ][ #  # ]:          0 :     static std::map< PDFWriter::StructElement, const char* > aTagStrings;
         [ #  # ][ #  # ]
   11027         [ #  # ]:          0 :     if( aTagStrings.empty() )
   11028                 :            :     {
   11029         [ #  # ]:          0 :         aTagStrings[ PDFWriter::NonStructElement] = "NonStruct";
   11030         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Document ]      = "Document";
   11031         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Part ]          = "Part";
   11032         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Article ]       = "Art";
   11033         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Section ]       = "Sect";
   11034         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Division ]      = "Div";
   11035         [ #  # ]:          0 :         aTagStrings[ PDFWriter::BlockQuote ]    = "BlockQuote";
   11036         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Caption ]       = "Caption";
   11037         [ #  # ]:          0 :         aTagStrings[ PDFWriter::TOC ]           = "TOC";
   11038         [ #  # ]:          0 :         aTagStrings[ PDFWriter::TOCI ]          = "TOCI";
   11039         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Index ]         = "Index";
   11040         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Paragraph ]     = "P";
   11041         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Heading ]       = "H";
   11042         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H1 ]            = "H1";
   11043         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H2 ]            = "H2";
   11044         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H3 ]            = "H3";
   11045         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H4 ]            = "H4";
   11046         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H5 ]            = "H5";
   11047         [ #  # ]:          0 :         aTagStrings[ PDFWriter::H6 ]            = "H6";
   11048         [ #  # ]:          0 :         aTagStrings[ PDFWriter::List ]          = "L";
   11049         [ #  # ]:          0 :         aTagStrings[ PDFWriter::ListItem ]      = "LI";
   11050         [ #  # ]:          0 :         aTagStrings[ PDFWriter::LILabel ]       = "Lbl";
   11051         [ #  # ]:          0 :         aTagStrings[ PDFWriter::LIBody ]        = "LBody";
   11052         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Table ]         = "Table";
   11053         [ #  # ]:          0 :         aTagStrings[ PDFWriter::TableRow ]      = "TR";
   11054         [ #  # ]:          0 :         aTagStrings[ PDFWriter::TableHeader ]   = "TH";
   11055         [ #  # ]:          0 :         aTagStrings[ PDFWriter::TableData ]     = "TD";
   11056         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Span ]          = "Span";
   11057         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Quote ]         = "Quote";
   11058         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Note ]          = "Note";
   11059         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Reference ]     = "Reference";
   11060         [ #  # ]:          0 :         aTagStrings[ PDFWriter::BibEntry ]      = "BibEntry";
   11061         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Code ]          = "Code";
   11062         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Link ]          = "Link";
   11063         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Figure ]        = "Figure";
   11064         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Formula ]       = "Formula";
   11065         [ #  # ]:          0 :         aTagStrings[ PDFWriter::Form ]          = "Form";
   11066                 :            :     }
   11067                 :            : 
   11068 [ #  # ][ #  # ]:          0 :     std::map< PDFWriter::StructElement, const char* >::const_iterator it = aTagStrings.find( eType );
   11069                 :            : 
   11070 [ #  # ][ #  # ]:          0 :     return it != aTagStrings.end() ? it->second : "Div";
         [ #  # ][ #  # ]
   11071                 :            : }
   11072                 :            : 
   11073                 :          0 : void PDFWriterImpl::beginStructureElementMCSeq()
   11074                 :            : {
   11075         [ #  # ]:          0 :     if( m_bEmitStructure &&
           [ #  #  #  # ]
                 [ #  # ]
   11076                 :            :         m_nCurrentStructElement > 0 && // StructTreeRoot
   11077                 :          0 :         ! m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq // already opened sequence
   11078                 :            :         )
   11079                 :            :     {
   11080                 :          0 :         PDFStructureElement& rEle = m_aStructure[ m_nCurrentStructElement ];
   11081                 :          0 :         OStringBuffer aLine( 128 );
   11082                 :          0 :         sal_Int32 nMCID = m_aPages[ m_nCurrentPage ].m_aMCIDParents.size();
   11083         [ #  # ]:          0 :         aLine.append( "/" );
   11084         [ #  # ]:          0 :         if( !rEle.m_aAlias.isEmpty() )
   11085         [ #  # ]:          0 :             aLine.append( rEle.m_aAlias );
   11086                 :            :         else
   11087 [ #  # ][ #  # ]:          0 :             aLine.append( getStructureTag( rEle.m_eType ) );
   11088         [ #  # ]:          0 :         aLine.append( "<</MCID " );
   11089         [ #  # ]:          0 :         aLine.append( nMCID );
   11090         [ #  # ]:          0 :         aLine.append( ">>BDC\n" );
   11091         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
   11092                 :            : 
   11093                 :            :         // update the element's content list
   11094                 :            : #if OSL_DEBUG_LEVEL > 1
   11095                 :            :         fprintf( stderr, "beginning marked content id %" SAL_PRIdINT32 " on page object %" SAL_PRIdINT32 ", structure first page = %" SAL_PRIdINT32 "\n",
   11096                 :            :                  nMCID,
   11097                 :            :                  m_aPages[ m_nCurrentPage ].m_nPageObject,
   11098                 :            :                  rEle.m_nFirstPageObject );
   11099                 :            : #endif
   11100         [ #  # ]:          0 :         rEle.m_aKids.push_back( PDFStructureElementKid( nMCID, m_aPages[m_nCurrentPage].m_nPageObject ) );
   11101                 :            :         // update the page's mcid parent list
   11102         [ #  # ]:          0 :         m_aPages[ m_nCurrentPage ].m_aMCIDParents.push_back( rEle.m_nObject );
   11103                 :            :         // mark element MC sequence as open
   11104                 :          0 :         rEle.m_bOpenMCSeq = true;
   11105                 :            :     }
   11106                 :            :     // handle artifacts
   11107 [ #  # ][ #  # ]:          0 :     else if( ! m_bEmitStructure && m_aContext.Tagged &&
           [ #  #  #  #  
           #  # ][ #  # ]
   11108                 :            :                m_nCurrentStructElement > 0 &&
   11109                 :          0 :                m_aStructure[ m_nCurrentStructElement ].m_eType == PDFWriter::NonStructElement &&
   11110                 :          0 :              ! m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq // already opened sequence
   11111                 :            :              )
   11112                 :            :     {
   11113                 :          0 :         OStringBuffer aLine( 128 );
   11114         [ #  # ]:          0 :         aLine.append( "/Artifact BMC\n" );
   11115         [ #  # ]:          0 :         writeBuffer( aLine.getStr(), aLine.getLength() );
   11116                 :            :         // mark element MC sequence as open
   11117                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq = true;
   11118                 :            :     }
   11119                 :          0 : }
   11120                 :            : 
   11121                 :          0 : void PDFWriterImpl::endStructureElementMCSeq()
   11122                 :            : {
   11123 [ #  # ][ #  #  :          0 :     if( m_nCurrentStructElement > 0 && // StructTreeRoot
             #  #  #  # ]
                 [ #  # ]
   11124                 :          0 :         ( m_bEmitStructure || m_aStructure[ m_nCurrentStructElement ].m_eType == PDFWriter::NonStructElement ) &&
   11125                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq // must have an opened MC sequence
   11126                 :            :         )
   11127                 :            :     {
   11128                 :          0 :         writeBuffer( "EMC\n", 4 );
   11129                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq = false;
   11130                 :            :     }
   11131                 :          0 : }
   11132                 :            : 
   11133                 :          0 : bool PDFWriterImpl::checkEmitStructure()
   11134                 :            : {
   11135                 :          0 :     bool bEmit = false;
   11136         [ #  # ]:          0 :     if( m_aContext.Tagged )
   11137                 :            :     {
   11138                 :          0 :         bEmit = true;
   11139                 :          0 :         sal_Int32 nEle = m_nCurrentStructElement;
   11140 [ #  # ][ #  # ]:          0 :         while( nEle > 0 && nEle < sal_Int32(m_aStructure.size()) )
                 [ #  # ]
   11141                 :            :         {
   11142         [ #  # ]:          0 :             if( m_aStructure[ nEle ].m_eType == PDFWriter::NonStructElement )
   11143                 :            :             {
   11144                 :          0 :                 bEmit = false;
   11145                 :          0 :                 break;
   11146                 :            :             }
   11147                 :          0 :             nEle = m_aStructure[ nEle ].m_nParentElement;
   11148                 :            :         }
   11149                 :            :     }
   11150                 :          0 :     return bEmit;
   11151                 :            : }
   11152                 :            : 
   11153                 :          0 : sal_Int32 PDFWriterImpl::beginStructureElement( PDFWriter::StructElement eType, const rtl::OUString& rAlias )
   11154                 :            : {
   11155         [ #  # ]:          0 :     if( m_nCurrentPage < 0 )
   11156                 :          0 :         return -1;
   11157                 :            : 
   11158         [ #  # ]:          0 :     if( ! m_aContext.Tagged )
   11159                 :          0 :         return -1;
   11160                 :            : 
   11161                 :            :     // close eventual current MC sequence
   11162         [ #  # ]:          0 :     endStructureElementMCSeq();
   11163                 :            : 
   11164 [ #  # ][ #  # ]:          0 :     if( m_nCurrentStructElement == 0 &&
                 [ #  # ]
   11165                 :            :         eType != PDFWriter::Document && eType != PDFWriter::NonStructElement )
   11166                 :            :     {
   11167                 :            :         // struct tree root hit, but not beginning document
   11168                 :            :         // this might happen with setCurrentStructureElement
   11169                 :            :         // silently insert structure into document again if one properly exists
   11170         [ #  # ]:          0 :         if( ! m_aStructure[ 0 ].m_aChildren.empty() )
   11171                 :            :         {
   11172                 :          0 :             PDFWriter::StructElement childType = PDFWriter::NonStructElement;
   11173                 :          0 :             sal_Int32 nNewCurElement = 0;
   11174                 :          0 :             const std::list< sal_Int32 >& rRootChildren = m_aStructure[0].m_aChildren;
   11175 [ #  # ][ #  # ]:          0 :             for( std::list< sal_Int32 >::const_iterator it = rRootChildren.begin();
         [ #  # ][ #  # ]
   11176 [ #  # ][ #  # ]:          0 :                  childType != PDFWriter::Document && it != rRootChildren.end(); ++it )
                 [ #  # ]
   11177                 :            :             {
   11178         [ #  # ]:          0 :                 nNewCurElement = *it;
   11179                 :          0 :                 childType = m_aStructure[ nNewCurElement ].m_eType;
   11180                 :            :             }
   11181         [ #  # ]:          0 :             if( childType == PDFWriter::Document )
   11182                 :            :             {
   11183                 :          0 :                 m_nCurrentStructElement = nNewCurElement;
   11184                 :            :                 DBG_ASSERT( 0, "Structure element inserted to StructTreeRoot that is not a document" );
   11185                 :            :             }
   11186                 :            :             else {
   11187                 :            :                 OSL_FAIL( "document structure in disorder !" );
   11188                 :            :             }
   11189                 :            :         }
   11190                 :            :         else {
   11191                 :            :             OSL_FAIL( "PDF document structure MUST be contained in a Document element" );
   11192                 :            :         }
   11193                 :            :     }
   11194                 :            : 
   11195                 :          0 :     sal_Int32 nNewId = sal_Int32(m_aStructure.size());
   11196 [ #  # ][ #  # ]:          0 :     m_aStructure.push_back( PDFStructureElement() );
   11197         [ #  # ]:          0 :     PDFStructureElement& rEle = m_aStructure.back();
   11198                 :          0 :     rEle.m_eType            = eType;
   11199                 :          0 :     rEle.m_nOwnElement      = nNewId;
   11200                 :          0 :     rEle.m_nParentElement   = m_nCurrentStructElement;
   11201                 :          0 :     rEle.m_nFirstPageObject = m_aPages[ m_nCurrentPage ].m_nPageObject;
   11202         [ #  # ]:          0 :     m_aStructure[ m_nCurrentStructElement ].m_aChildren.push_back( nNewId );
   11203                 :          0 :     m_nCurrentStructElement = nNewId;
   11204                 :            : 
   11205                 :            :     // handle alias names
   11206 [ #  # ][ #  # ]:          0 :     if( !rAlias.isEmpty() && eType != PDFWriter::NonStructElement )
                 [ #  # ]
   11207                 :            :     {
   11208                 :          0 :         OStringBuffer aNameBuf( rAlias.getLength() );
   11209         [ #  # ]:          0 :         appendName( rAlias, aNameBuf );
   11210                 :          0 :         OString aAliasName( aNameBuf.makeStringAndClear() );
   11211                 :          0 :         rEle.m_aAlias = aAliasName;
   11212 [ #  # ][ #  # ]:          0 :         m_aRoleMap[ aAliasName ] = getStructureTag( eType );
   11213                 :            :     }
   11214                 :            : 
   11215                 :            : #if OSL_DEBUG_LEVEL > 1
   11216                 :            :     OStringBuffer aLine( "beginStructureElement " );
   11217                 :            :     aLine.append( m_nCurrentStructElement );
   11218                 :            :     aLine.append( ": " );
   11219                 :            :     aLine.append( getStructureTag( eType ) );
   11220                 :            :     if( !rEle.m_aAlias.isEmpty() )
   11221                 :            :     {
   11222                 :            :         aLine.append( " aliased as \"" );
   11223                 :            :         aLine.append( rEle.m_aAlias );
   11224                 :            :         aLine.append( '\"' );
   11225                 :            :     }
   11226                 :            :     emitComment( aLine.getStr() );
   11227                 :            : #endif
   11228                 :            : 
   11229                 :            :     // check whether to emit structure henceforth
   11230         [ #  # ]:          0 :     m_bEmitStructure = checkEmitStructure();
   11231                 :            : 
   11232         [ #  # ]:          0 :     if( m_bEmitStructure ) // don't create nonexistant objects
   11233                 :            :     {
   11234         [ #  # ]:          0 :         rEle.m_nObject      = createObject();
   11235                 :            :         // update parent's kids list
   11236         [ #  # ]:          0 :         m_aStructure[ rEle.m_nParentElement ].m_aKids.push_back( rEle.m_nObject );
   11237                 :            :     }
   11238                 :          0 :     return nNewId;
   11239                 :            : }
   11240                 :            : 
   11241                 :          0 : void PDFWriterImpl::endStructureElement()
   11242                 :            : {
   11243         [ #  # ]:          0 :     if( m_nCurrentPage < 0 )
   11244                 :          0 :         return;
   11245                 :            : 
   11246         [ #  # ]:          0 :     if( ! m_aContext.Tagged )
   11247                 :          0 :         return;
   11248                 :            : 
   11249         [ #  # ]:          0 :     if( m_nCurrentStructElement == 0 )
   11250                 :            :     {
   11251                 :            :         // hit the struct tree root, that means there is an endStructureElement
   11252                 :            :         // without corresponding beginStructureElement
   11253                 :          0 :         return;
   11254                 :            :     }
   11255                 :            : 
   11256                 :            :     // end the marked content sequence
   11257                 :          0 :     endStructureElementMCSeq();
   11258                 :            : 
   11259                 :            : #if OSL_DEBUG_LEVEL > 1
   11260                 :            :     OStringBuffer aLine( "endStructureElement " );
   11261                 :            :     aLine.append( m_nCurrentStructElement );
   11262                 :            :     aLine.append( ": " );
   11263                 :            :     aLine.append( getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ) );
   11264                 :            :     if( !m_aStructure[ m_nCurrentStructElement ].m_aAlias.isEmpty() )
   11265                 :            :     {
   11266                 :            :         aLine.append( " aliased as \"" );
   11267                 :            :         aLine.append( m_aStructure[ m_nCurrentStructElement ].m_aAlias );
   11268                 :            :         aLine.append( '\"' );
   11269                 :            :     }
   11270                 :            : #endif
   11271                 :            : 
   11272                 :            :     // "end" the structure element, the parent becomes current element
   11273                 :          0 :     m_nCurrentStructElement = m_aStructure[ m_nCurrentStructElement ].m_nParentElement;
   11274                 :            : 
   11275                 :            :     // check whether to emit structure henceforth
   11276                 :          0 :     m_bEmitStructure = checkEmitStructure();
   11277                 :            : 
   11278                 :            : #if OSL_DEBUG_LEVEL > 1
   11279                 :            :     if( m_bEmitStructure )
   11280                 :            :         emitComment( aLine.getStr() );
   11281                 :            : #endif
   11282                 :            : }
   11283                 :            : 
   11284                 :            : //---> i94258
   11285                 :            : /*
   11286                 :            :  * This function adds an internal structure list container to overcome the 8191 elements array limitation
   11287                 :            :  * in kids element emission.
   11288                 :            :  * Recursive function
   11289                 :            :  *
   11290                 :            :  */
   11291                 :          0 : void PDFWriterImpl::addInternalStructureContainer( PDFStructureElement& rEle )
   11292                 :            : {
   11293 [ #  # ][ #  # ]:          0 :     if( rEle.m_eType == PDFWriter::NonStructElement &&
   11294                 :            :         rEle.m_nOwnElement != rEle.m_nParentElement )
   11295                 :          0 :         return;
   11296                 :            : 
   11297 [ #  # ][ #  # ]:          0 :     for( std::list< sal_Int32 >::const_iterator it = rEle.m_aChildren.begin(); it != rEle.m_aChildren.end(); ++it )
         [ #  # ][ #  # ]
                 [ #  # ]
   11298                 :            :     {
   11299 [ #  # ][ #  # ]:          0 :         if( *it > 0 && *it < sal_Int32(m_aStructure.size()) )
         [ #  # ][ #  # ]
                 [ #  # ]
   11300                 :            :         {
   11301         [ #  # ]:          0 :             PDFStructureElement& rChild = m_aStructure[ *it ];
   11302         [ #  # ]:          0 :             if( rChild.m_eType != PDFWriter::NonStructElement )
   11303                 :            :             {
   11304                 :            :                 //triggered when a child of the rEle element is found
   11305         [ #  # ]:          0 :                 if( rChild.m_nParentElement == rEle.m_nOwnElement )
   11306         [ #  # ]:          0 :                     addInternalStructureContainer( rChild );//examine the child
   11307                 :            :                 else
   11308                 :            :                 {
   11309                 :            :                     OSL_FAIL( "PDFWriterImpl::addInternalStructureContainer: invalid child structure element" );
   11310                 :            : #if OSL_DEBUG_LEVEL > 1
   11311                 :            :                     fprintf( stderr, "PDFWriterImpl::addInternalStructureContainer: invalid child structure elemnt with id %" SAL_PRIdINT32 "\n", *it );
   11312                 :            : #endif
   11313                 :            :                 }
   11314                 :            :             }
   11315                 :            :         }
   11316                 :            :         else
   11317                 :            :         {
   11318                 :            :             OSL_FAIL( "PDFWriterImpl::emitStructure: invalid child structure id" );
   11319                 :            : #if OSL_DEBUG_LEVEL > 1
   11320                 :            :             fprintf( stderr, "PDFWriterImpl::addInternalStructureContainer: invalid child structure id %" SAL_PRIdINT32 "\n", *it );
   11321                 :            : #endif
   11322                 :            :         }
   11323                 :            :     }
   11324                 :            : 
   11325         [ #  # ]:          0 :     if( rEle.m_nOwnElement != rEle.m_nParentElement )
   11326                 :            :     {
   11327         [ #  # ]:          0 :         if( !rEle.m_aKids.empty() )
   11328                 :            :         {
   11329         [ #  # ]:          0 :             if( rEle.m_aKids.size() > ncMaxPDFArraySize ) {
   11330                 :            :                 //then we need to add the containers for the kids elements
   11331                 :            :                 // a list to be used for the new kid element
   11332         [ #  # ]:          0 :                 std::list< PDFStructureElementKid > aNewKids;
   11333         [ #  # ]:          0 :                 std::list< sal_Int32 > aNewChildren;
   11334                 :            : 
   11335                 :            :                 // add Div in RoleMap, in case no one else did (TODO: is it needed? Is it dangerous?)
   11336                 :          0 :                 OStringBuffer aNameBuf( "Div" );
   11337                 :          0 :                 OString aAliasName( aNameBuf.makeStringAndClear() );
   11338 [ #  # ][ #  # ]:          0 :                 m_aRoleMap[ aAliasName ] = getStructureTag( PDFWriter::Division );
   11339                 :            : 
   11340         [ #  # ]:          0 :                 while( rEle.m_aKids.size() > ncMaxPDFArraySize )
   11341                 :            :                 {
   11342                 :          0 :                     sal_Int32 nCurrentStructElement = rEle.m_nOwnElement;
   11343                 :          0 :                     sal_Int32 nNewId = sal_Int32(m_aStructure.size());
   11344 [ #  # ][ #  # ]:          0 :                     m_aStructure.push_back( PDFStructureElement() );
   11345         [ #  # ]:          0 :                     PDFStructureElement& rEleNew = m_aStructure.back();
   11346                 :          0 :                     rEleNew.m_aAlias            = aAliasName;
   11347                 :          0 :                     rEleNew.m_eType             = PDFWriter::Division; // a new Div type container
   11348                 :          0 :                     rEleNew.m_nOwnElement       = nNewId;
   11349                 :          0 :                     rEleNew.m_nParentElement    = nCurrentStructElement;
   11350                 :            :                     //inherit the same page as the first child to be reparented
   11351         [ #  # ]:          0 :                     rEleNew.m_nFirstPageObject  = m_aStructure[ rEle.m_aChildren.front() ].m_nFirstPageObject;
   11352         [ #  # ]:          0 :                     rEleNew.m_nObject           = createObject();//assign a PDF object number
   11353                 :            :                     //add the object to the kid list of the parent
   11354         [ #  # ]:          0 :                     aNewKids.push_back( PDFStructureElementKid( rEleNew.m_nObject ) );
   11355         [ #  # ]:          0 :                     aNewChildren.push_back( nNewId );
   11356                 :            : 
   11357                 :          0 :                     std::list< sal_Int32 >::iterator aChildEndIt( rEle.m_aChildren.begin() );
   11358                 :          0 :                     std::list< PDFStructureElementKid >::iterator aKidEndIt( rEle.m_aKids.begin() );
   11359         [ #  # ]:          0 :                     advance( aChildEndIt, ncMaxPDFArraySize );
   11360         [ #  # ]:          0 :                     advance( aKidEndIt, ncMaxPDFArraySize );
   11361                 :            : 
   11362                 :            :                     rEleNew.m_aKids.splice( rEleNew.m_aKids.begin(),
   11363                 :            :                                             rEle.m_aKids,
   11364                 :            :                                             rEle.m_aKids.begin(),
   11365         [ #  # ]:          0 :                                             aKidEndIt );
   11366                 :            :                     rEleNew.m_aChildren.splice( rEleNew.m_aChildren.begin(),
   11367                 :            :                                                 rEle.m_aChildren,
   11368                 :            :                                                 rEle.m_aChildren.begin(),
   11369         [ #  # ]:          0 :                                                 aChildEndIt );
   11370                 :            :                     // set the kid's new parent
   11371 [ #  # ][ #  # ]:          0 :                     for( std::list< sal_Int32 >::const_iterator it = rEleNew.m_aChildren.begin();
         [ #  # ][ #  # ]
   11372         [ #  # ]:          0 :                          it != rEleNew.m_aChildren.end(); ++it )
   11373                 :            :                     {
   11374         [ #  # ]:          0 :                         m_aStructure[ *it ].m_nParentElement = nNewId;
   11375                 :            :                     }
   11376                 :            :                 }
   11377                 :            :                 //finally add the new kids resulting from the container added
   11378         [ #  # ]:          0 :                 rEle.m_aKids.insert( rEle.m_aKids.begin(), aNewKids.begin(), aNewKids.end() );
   11379         [ #  # ]:          0 :                 rEle.m_aChildren.insert( rEle.m_aChildren.begin(), aNewChildren.begin(), aNewChildren.end() );
   11380                 :            :             }
   11381                 :            :         }
   11382                 :            :     }
   11383                 :            : }
   11384                 :            : //<--- i94258
   11385                 :            : 
   11386                 :          0 : bool PDFWriterImpl::setCurrentStructureElement( sal_Int32 nEle )
   11387                 :            : {
   11388                 :          0 :     bool bSuccess = false;
   11389                 :            : 
   11390 [ #  # ][ #  # ]:          0 :     if( m_aContext.Tagged && nEle >= 0 && nEle < sal_Int32(m_aStructure.size()) )
         [ #  # ][ #  # ]
   11391                 :            :     {
   11392                 :            :         // end eventual previous marked content sequence
   11393                 :          0 :         endStructureElementMCSeq();
   11394                 :            : 
   11395                 :          0 :         m_nCurrentStructElement = nEle;
   11396                 :          0 :         m_bEmitStructure = checkEmitStructure();
   11397                 :            : #if OSL_DEBUG_LEVEL > 1
   11398                 :            :         OStringBuffer aLine( "setCurrentStructureElement " );
   11399                 :            :         aLine.append( m_nCurrentStructElement );
   11400                 :            :         aLine.append( ": " );
   11401                 :            :         aLine.append( getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ) );
   11402                 :            :         if( !m_aStructure[ m_nCurrentStructElement ].m_aAlias.isEmpty() )
   11403                 :            :         {
   11404                 :            :             aLine.append( " aliased as \"" );
   11405                 :            :             aLine.append( m_aStructure[ m_nCurrentStructElement ].m_aAlias );
   11406                 :            :             aLine.append( '\"' );
   11407                 :            :         }
   11408                 :            :         if( ! m_bEmitStructure )
   11409                 :            :             aLine.append( " (inside NonStruct)" );
   11410                 :            :         emitComment( aLine.getStr() );
   11411                 :            : #endif
   11412                 :          0 :         bSuccess = true;
   11413                 :            :     }
   11414                 :            : 
   11415                 :          0 :     return bSuccess;
   11416                 :            : }
   11417                 :            : 
   11418                 :          0 : bool PDFWriterImpl::setStructureAttribute( enum PDFWriter::StructAttribute eAttr, enum PDFWriter::StructAttributeValue eVal )
   11419                 :            : {
   11420         [ #  # ]:          0 :     if( !m_aContext.Tagged )
   11421                 :          0 :         return false;
   11422                 :            : 
   11423                 :          0 :     bool bInsert = false;
   11424 [ #  # ][ #  # ]:          0 :     if( m_nCurrentStructElement > 0 && m_bEmitStructure )
   11425                 :            :     {
   11426                 :          0 :         PDFWriter::StructElement eType = m_aStructure[ m_nCurrentStructElement ].m_eType;
   11427   [ #  #  #  #  :          0 :         switch( eAttr )
          #  #  #  #  #  
                      # ]
   11428                 :            :         {
   11429                 :            :             case PDFWriter::Placement:
   11430 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::Block        ||
         [ #  # ][ #  # ]
                 [ #  # ]
   11431                 :            :                     eVal == PDFWriter::Inline       ||
   11432                 :            :                     eVal == PDFWriter::Before       ||
   11433                 :            :                     eVal == PDFWriter::Start        ||
   11434                 :            :                     eVal == PDFWriter::End )
   11435                 :          0 :                     bInsert = true;
   11436                 :          0 :                 break;
   11437                 :            :             case PDFWriter::WritingMode:
   11438 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::LrTb         ||
                 [ #  # ]
   11439                 :            :                     eVal == PDFWriter::RlTb         ||
   11440                 :            :                     eVal == PDFWriter::TbRl )
   11441                 :            :                 {
   11442                 :          0 :                     bInsert = true;
   11443                 :            :                 }
   11444                 :          0 :                 break;
   11445                 :            :             case PDFWriter::TextAlign:
   11446 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::Start        ||
         [ #  # ][ #  # ]
   11447                 :            :                     eVal == PDFWriter::Center       ||
   11448                 :            :                     eVal == PDFWriter::End          ||
   11449                 :            :                     eVal == PDFWriter::Justify )
   11450                 :            :                 {
   11451 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
   11452                 :            :                         eType == PDFWriter::Heading     ||
   11453                 :            :                         eType == PDFWriter::H1          ||
   11454                 :            :                         eType == PDFWriter::H2          ||
   11455                 :            :                         eType == PDFWriter::H3          ||
   11456                 :            :                         eType == PDFWriter::H4          ||
   11457                 :            :                         eType == PDFWriter::H5          ||
   11458                 :            :                         eType == PDFWriter::H6          ||
   11459                 :            :                         eType == PDFWriter::List        ||
   11460                 :            :                         eType == PDFWriter::ListItem    ||
   11461                 :            :                         eType == PDFWriter::LILabel     ||
   11462                 :            :                         eType == PDFWriter::LIBody      ||
   11463                 :            :                         eType == PDFWriter::Table       ||
   11464                 :            :                         eType == PDFWriter::TableRow    ||
   11465                 :            :                         eType == PDFWriter::TableHeader ||
   11466                 :            :                         eType == PDFWriter::TableData )
   11467                 :            :                     {
   11468                 :          0 :                         bInsert = true;
   11469                 :            :                     }
   11470                 :            :                 }
   11471                 :          0 :                 break;
   11472                 :            :             case PDFWriter::Width:
   11473                 :            :             case PDFWriter::Height:
   11474         [ #  # ]:          0 :                 if( eVal == PDFWriter::Auto )
   11475                 :            :                 {
   11476 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::Figure      ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
   11477                 :            :                         eType == PDFWriter::Formula     ||
   11478                 :            :                         eType == PDFWriter::Form        ||
   11479                 :            :                         eType == PDFWriter::Table       ||
   11480                 :            :                         eType == PDFWriter::TableHeader ||
   11481                 :            :                         eType == PDFWriter::TableData )
   11482                 :            :                     {
   11483                 :          0 :                         bInsert = true;
   11484                 :            :                     }
   11485                 :            :                 }
   11486                 :          0 :                 break;
   11487                 :            :             case PDFWriter::BlockAlign:
   11488 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::Before       ||
         [ #  # ][ #  # ]
   11489                 :            :                     eVal == PDFWriter::Middle       ||
   11490                 :            :                     eVal == PDFWriter::After        ||
   11491                 :            :                     eVal == PDFWriter::Justify )
   11492                 :            :                 {
   11493 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::TableHeader ||
   11494                 :            :                         eType == PDFWriter::TableData )
   11495                 :            :                     {
   11496                 :          0 :                         bInsert = true;
   11497                 :            :                     }
   11498                 :            :                 }
   11499                 :          0 :                 break;
   11500                 :            :             case PDFWriter::InlineAlign:
   11501 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::Start        ||
                 [ #  # ]
   11502                 :            :                     eVal == PDFWriter::Center       ||
   11503                 :            :                     eVal == PDFWriter::End )
   11504                 :            :                 {
   11505 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::TableHeader ||
   11506                 :            :                         eType == PDFWriter::TableData )
   11507                 :            :                     {
   11508                 :          0 :                         bInsert = true;
   11509                 :            :                     }
   11510                 :            :                 }
   11511                 :          0 :                 break;
   11512                 :            :             case PDFWriter::LineHeight:
   11513 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::Normal       ||
   11514                 :            :                     eVal == PDFWriter::Auto )
   11515                 :            :                 {
   11516                 :            :                     // only for ILSE and BLSE
   11517 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
   11518                 :            :                         eType == PDFWriter::Heading     ||
   11519                 :            :                         eType == PDFWriter::H1          ||
   11520                 :            :                         eType == PDFWriter::H2          ||
   11521                 :            :                         eType == PDFWriter::H3          ||
   11522                 :            :                         eType == PDFWriter::H4          ||
   11523                 :            :                         eType == PDFWriter::H5          ||
   11524                 :            :                         eType == PDFWriter::H6          ||
   11525                 :            :                         eType == PDFWriter::List        ||
   11526                 :            :                         eType == PDFWriter::ListItem    ||
   11527                 :            :                         eType == PDFWriter::LILabel     ||
   11528                 :            :                         eType == PDFWriter::LIBody      ||
   11529                 :            :                         eType == PDFWriter::Table       ||
   11530                 :            :                         eType == PDFWriter::TableRow    ||
   11531                 :            :                         eType == PDFWriter::TableHeader ||
   11532                 :            :                         eType == PDFWriter::TableData   ||
   11533                 :            :                         eType == PDFWriter::Span        ||
   11534                 :            :                         eType == PDFWriter::Quote       ||
   11535                 :            :                         eType == PDFWriter::Note        ||
   11536                 :            :                         eType == PDFWriter::Reference   ||
   11537                 :            :                         eType == PDFWriter::BibEntry    ||
   11538                 :            :                         eType == PDFWriter::Code        ||
   11539                 :            :                         eType == PDFWriter::Link )
   11540                 :            :                     {
   11541                 :          0 :                         bInsert = true;
   11542                 :            :                     }
   11543                 :            :                 }
   11544                 :          0 :                 break;
   11545                 :            :             case PDFWriter::TextDecorationType:
   11546 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::NONE         ||
         [ #  # ][ #  # ]
   11547                 :            :                     eVal == PDFWriter::Underline    ||
   11548                 :            :                     eVal == PDFWriter::Overline     ||
   11549                 :            :                     eVal == PDFWriter::LineThrough )
   11550                 :            :                 {
   11551                 :            :                     // only for ILSE and BLSE
   11552 [ #  # ][ #  # ]:          0 :                     if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
   11553                 :            :                         eType == PDFWriter::Heading     ||
   11554                 :            :                         eType == PDFWriter::H1          ||
   11555                 :            :                         eType == PDFWriter::H2          ||
   11556                 :            :                         eType == PDFWriter::H3          ||
   11557                 :            :                         eType == PDFWriter::H4          ||
   11558                 :            :                         eType == PDFWriter::H5          ||
   11559                 :            :                         eType == PDFWriter::H6          ||
   11560                 :            :                         eType == PDFWriter::List        ||
   11561                 :            :                         eType == PDFWriter::ListItem    ||
   11562                 :            :                         eType == PDFWriter::LILabel     ||
   11563                 :            :                         eType == PDFWriter::LIBody      ||
   11564                 :            :                         eType == PDFWriter::Table       ||
   11565                 :            :                         eType == PDFWriter::TableRow    ||
   11566                 :            :                         eType == PDFWriter::TableHeader ||
   11567                 :            :                         eType == PDFWriter::TableData   ||
   11568                 :            :                         eType == PDFWriter::Span        ||
   11569                 :            :                         eType == PDFWriter::Quote       ||
   11570                 :            :                         eType == PDFWriter::Note        ||
   11571                 :            :                         eType == PDFWriter::Reference   ||
   11572                 :            :                         eType == PDFWriter::BibEntry    ||
   11573                 :            :                         eType == PDFWriter::Code        ||
   11574                 :            :                         eType == PDFWriter::Link )
   11575                 :            :                     {
   11576                 :          0 :                         bInsert = true;
   11577                 :            :                     }
   11578                 :            :                 }
   11579                 :          0 :                 break;
   11580                 :            :             case PDFWriter::ListNumbering:
   11581 [ #  # ][ #  # ]:          0 :                 if( eVal == PDFWriter::NONE         ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
   11582                 :            :                     eVal == PDFWriter::Disc         ||
   11583                 :            :                     eVal == PDFWriter::Circle       ||
   11584                 :            :                     eVal == PDFWriter::Square       ||
   11585                 :            :                     eVal == PDFWriter::Decimal      ||
   11586                 :            :                     eVal == PDFWriter::UpperRoman   ||
   11587                 :            :                     eVal == PDFWriter::LowerRoman   ||
   11588                 :            :                     eVal == PDFWriter::UpperAlpha   ||
   11589                 :            :                     eVal == PDFWriter::LowerAlpha )
   11590                 :            :                 {
   11591         [ #  # ]:          0 :                     if( eType == PDFWriter::List )
   11592                 :          0 :                         bInsert = true;
   11593                 :            :                 }
   11594                 :          0 :                 break;
   11595                 :          0 :             default: break;
   11596                 :            :         }
   11597                 :            :     }
   11598                 :            : 
   11599         [ #  # ]:          0 :     if( bInsert )
   11600                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_aAttributes[ eAttr ] = PDFStructureAttribute( eVal );
   11601                 :            : #if OSL_DEBUG_LEVEL > 1
   11602                 :            :     else if( m_nCurrentStructElement > 0 && m_bEmitStructure )
   11603                 :            :         fprintf( stderr, "rejecting setStructureAttribute( %s, %s ) on %s (%s) element\n",
   11604                 :            :                  getAttributeTag( eAttr ),
   11605                 :            :                  getAttributeValueTag( eVal ),
   11606                 :            :                  getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ),
   11607                 :            :                  m_aStructure[ m_nCurrentStructElement ].m_aAlias.getStr()
   11608                 :            :                  );
   11609                 :            : #endif
   11610                 :            : 
   11611                 :          0 :     return bInsert;
   11612                 :            : }
   11613                 :            : 
   11614                 :          0 : bool PDFWriterImpl::setStructureAttributeNumerical( enum PDFWriter::StructAttribute eAttr, sal_Int32 nValue )
   11615                 :            : {
   11616         [ #  # ]:          0 :     if( ! m_aContext.Tagged )
   11617                 :          0 :         return false;
   11618                 :            : 
   11619                 :          0 :     bool bInsert = false;
   11620 [ #  # ][ #  # ]:          0 :     if( m_nCurrentStructElement > 0 && m_bEmitStructure )
   11621                 :            :     {
   11622         [ #  # ]:          0 :         if( eAttr == PDFWriter::Language )
   11623                 :            :         {
   11624                 :          0 :             m_aStructure[ m_nCurrentStructElement ].m_aLocale = MsLangId::convertLanguageToLocale( (LanguageType)nValue );
   11625                 :          0 :             return true;
   11626                 :            :         }
   11627                 :            : 
   11628                 :          0 :         PDFWriter::StructElement eType = m_aStructure[ m_nCurrentStructElement ].m_eType;
   11629   [ #  #  #  #  :          0 :         switch( eAttr )
                #  #  # ]
   11630                 :            :         {
   11631                 :            :             case PDFWriter::SpaceBefore:
   11632                 :            :             case PDFWriter::SpaceAfter:
   11633                 :            :             case PDFWriter::StartIndent:
   11634                 :            :             case PDFWriter::EndIndent:
   11635                 :            :                 // just for BLSE
   11636 [ #  # ][ #  # ]:          0 :                 if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
   11637                 :            :                     eType == PDFWriter::Heading     ||
   11638                 :            :                     eType == PDFWriter::H1          ||
   11639                 :            :                     eType == PDFWriter::H2          ||
   11640                 :            :                     eType == PDFWriter::H3          ||
   11641                 :            :                     eType == PDFWriter::H4          ||
   11642                 :            :                     eType == PDFWriter::H5          ||
   11643                 :            :                     eType == PDFWriter::H6          ||
   11644                 :            :                     eType == PDFWriter::List        ||
   11645                 :            :                     eType == PDFWriter::ListItem    ||
   11646                 :            :                     eType == PDFWriter::LILabel     ||
   11647                 :            :                     eType == PDFWriter::LIBody      ||
   11648                 :            :                     eType == PDFWriter::Table       ||
   11649                 :            :                     eType == PDFWriter::TableRow    ||
   11650                 :            :                     eType == PDFWriter::TableHeader ||
   11651                 :            :                     eType == PDFWriter::TableData )
   11652                 :            :                 {
   11653                 :          0 :                     bInsert = true;
   11654                 :            :                 }
   11655                 :          0 :                 break;
   11656                 :            :             case PDFWriter::TextIndent:
   11657                 :            :                 // paragraph like BLSE and additional elements
   11658 [ #  # ][ #  # ]:          0 :                 if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
   11659                 :            :                     eType == PDFWriter::Heading     ||
   11660                 :            :                     eType == PDFWriter::H1          ||
   11661                 :            :                     eType == PDFWriter::H2          ||
   11662                 :            :                     eType == PDFWriter::H3          ||
   11663                 :            :                     eType == PDFWriter::H4          ||
   11664                 :            :                     eType == PDFWriter::H5          ||
   11665                 :            :                     eType == PDFWriter::H6          ||
   11666                 :            :                     eType == PDFWriter::LILabel     ||
   11667                 :            :                     eType == PDFWriter::LIBody      ||
   11668                 :            :                     eType == PDFWriter::TableHeader ||
   11669                 :            :                     eType == PDFWriter::TableData )
   11670                 :            :                 {
   11671                 :          0 :                     bInsert = true;
   11672                 :            :                 }
   11673                 :          0 :                 break;
   11674                 :            :             case PDFWriter::Width:
   11675                 :            :             case PDFWriter::Height:
   11676 [ #  # ][ #  # ]:          0 :                 if( eType == PDFWriter::Figure      ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
   11677                 :            :                     eType == PDFWriter::Formula     ||
   11678                 :            :                     eType == PDFWriter::Form        ||
   11679                 :            :                     eType == PDFWriter::Table       ||
   11680                 :            :                     eType == PDFWriter::TableHeader ||
   11681                 :            :                     eType == PDFWriter::TableData )
   11682                 :            :                 {
   11683                 :          0 :                     bInsert = true;
   11684                 :            :                 }
   11685                 :          0 :                 break;
   11686                 :            :             case PDFWriter::LineHeight:
   11687                 :            :             case PDFWriter::BaselineShift:
   11688                 :            :                 // only for ILSE and BLSE
   11689 [ #  # ][ #  # ]:          0 :                 if( eType == PDFWriter::Paragraph   ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
   11690                 :            :                     eType == PDFWriter::Heading     ||
   11691                 :            :                     eType == PDFWriter::H1          ||
   11692                 :            :                     eType == PDFWriter::H2          ||
   11693                 :            :                     eType == PDFWriter::H3          ||
   11694                 :            :                     eType == PDFWriter::H4          ||
   11695                 :            :                     eType == PDFWriter::H5          ||
   11696                 :            :                     eType == PDFWriter::H6          ||
   11697                 :            :                     eType == PDFWriter::List        ||
   11698                 :            :                     eType == PDFWriter::ListItem    ||
   11699                 :            :                     eType == PDFWriter::LILabel     ||
   11700                 :            :                     eType == PDFWriter::LIBody      ||
   11701                 :            :                     eType == PDFWriter::Table       ||
   11702                 :            :                     eType == PDFWriter::TableRow    ||
   11703                 :            :                     eType == PDFWriter::TableHeader ||
   11704                 :            :                     eType == PDFWriter::TableData   ||
   11705                 :            :                     eType == PDFWriter::Span        ||
   11706                 :            :                     eType == PDFWriter::Quote       ||
   11707                 :            :                     eType == PDFWriter::Note        ||
   11708                 :            :                     eType == PDFWriter::Reference   ||
   11709                 :            :                     eType == PDFWriter::BibEntry    ||
   11710                 :            :                     eType == PDFWriter::Code        ||
   11711                 :            :                     eType == PDFWriter::Link )
   11712                 :            :                 {
   11713                 :          0 :                         bInsert = true;
   11714                 :            :                 }
   11715                 :          0 :                 break;
   11716                 :            :             case PDFWriter::RowSpan:
   11717                 :            :             case PDFWriter::ColSpan:
   11718                 :            :                 // only for table cells
   11719 [ #  # ][ #  # ]:          0 :                 if( eType == PDFWriter::TableHeader ||
   11720                 :            :                     eType == PDFWriter::TableData )
   11721                 :            :                 {
   11722                 :          0 :                     bInsert = true;
   11723                 :            :                 }
   11724                 :          0 :                 break;
   11725                 :            :             case PDFWriter::LinkAnnotation:
   11726         [ #  # ]:          0 :                 if( eType == PDFWriter::Link )
   11727                 :          0 :                     bInsert = true;
   11728                 :          0 :                 break;
   11729                 :          0 :             default: break;
   11730                 :            :         }
   11731                 :            :     }
   11732                 :            : 
   11733         [ #  # ]:          0 :     if( bInsert )
   11734                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_aAttributes[ eAttr ] = PDFStructureAttribute( nValue );
   11735                 :            : #if OSL_DEBUG_LEVEL > 1
   11736                 :            :     else if( m_nCurrentStructElement > 0 && m_bEmitStructure )
   11737                 :            :         fprintf( stderr, "rejecting setStructureAttributeNumerical( %s, %d ) on %s (%s) element\n",
   11738                 :            :                  getAttributeTag( eAttr ),
   11739                 :            :                  (int)nValue,
   11740                 :            :                  getStructureTag( m_aStructure[ m_nCurrentStructElement ].m_eType ),
   11741                 :            :                  m_aStructure[ m_nCurrentStructElement ].m_aAlias.getStr() );
   11742                 :            : #endif
   11743                 :            : 
   11744                 :          0 :     return bInsert;
   11745                 :            : }
   11746                 :            : 
   11747                 :          0 : void PDFWriterImpl::setStructureBoundingBox( const Rectangle& rRect )
   11748                 :            : {
   11749                 :          0 :     sal_Int32 nPageNr = m_nCurrentPage;
   11750 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() || !m_aContext.Tagged )
         [ #  # ][ #  # ]
   11751                 :          0 :         return;
   11752                 :            : 
   11753                 :            : 
   11754 [ #  # ][ #  # ]:          0 :     if( m_nCurrentStructElement > 0 && m_bEmitStructure )
   11755                 :            :     {
   11756                 :          0 :         PDFWriter::StructElement eType = m_aStructure[ m_nCurrentStructElement ].m_eType;
   11757 [ #  # ][ #  # ]:          0 :         if( eType == PDFWriter::Figure      ||
         [ #  # ][ #  # ]
   11758                 :            :             eType == PDFWriter::Formula     ||
   11759                 :            :             eType == PDFWriter::Form        ||
   11760                 :            :             eType == PDFWriter::Table )
   11761                 :            :         {
   11762                 :          0 :             m_aStructure[ m_nCurrentStructElement ].m_aBBox = rRect;
   11763                 :            :             // convert to default user space now, since the mapmode may change
   11764                 :          0 :             m_aPages[nPageNr].convertRect( m_aStructure[ m_nCurrentStructElement ].m_aBBox );
   11765                 :            :         }
   11766                 :            :     }
   11767                 :            : }
   11768                 :            : 
   11769                 :          0 : void PDFWriterImpl::setActualText( const String& rText )
   11770                 :            : {
   11771 [ #  # ][ #  # ]:          0 :     if( m_aContext.Tagged && m_nCurrentStructElement > 0 && m_bEmitStructure )
                 [ #  # ]
   11772                 :            :     {
   11773                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_aActualText = rText;
   11774                 :            :     }
   11775                 :          0 : }
   11776                 :            : 
   11777                 :          0 : void PDFWriterImpl::setAlternateText( const String& rText )
   11778                 :            : {
   11779 [ #  # ][ #  # ]:          0 :     if( m_aContext.Tagged && m_nCurrentStructElement > 0 && m_bEmitStructure )
                 [ #  # ]
   11780                 :            :     {
   11781                 :          0 :         m_aStructure[ m_nCurrentStructElement ].m_aAltText = rText;
   11782                 :            :     }
   11783                 :          0 : }
   11784                 :            : 
   11785                 :          0 : void PDFWriterImpl::setAutoAdvanceTime( sal_uInt32 nSeconds, sal_Int32 nPageNr )
   11786                 :            : {
   11787         [ #  # ]:          0 :     if( nPageNr < 0 )
   11788                 :          0 :         nPageNr = m_nCurrentPage;
   11789                 :            : 
   11790 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   11791                 :          0 :         return;
   11792                 :            : 
   11793                 :          0 :     m_aPages[ nPageNr ].m_nDuration = nSeconds;
   11794                 :            : }
   11795                 :            : 
   11796                 :          0 : void PDFWriterImpl::setPageTransition( PDFWriter::PageTransition eType, sal_uInt32 nMilliSec, sal_Int32 nPageNr )
   11797                 :            : {
   11798         [ #  # ]:          0 :     if( nPageNr < 0 )
   11799                 :          0 :         nPageNr = m_nCurrentPage;
   11800                 :            : 
   11801 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   11802                 :          0 :         return;
   11803                 :            : 
   11804                 :          0 :     m_aPages[ nPageNr ].m_eTransition   = eType;
   11805                 :          0 :     m_aPages[ nPageNr ].m_nTransTime    = nMilliSec;
   11806                 :            : }
   11807                 :            : 
   11808                 :          0 : void PDFWriterImpl::ensureUniqueRadioOnValues()
   11809                 :            : {
   11810                 :            :     // loop over radio groups
   11811 [ #  # ][ #  # ]:          0 :     for( std::map<sal_Int32,sal_Int32>::const_iterator group = m_aRadioGroupWidgets.begin();
         [ #  # ][ #  # ]
   11812         [ #  # ]:          0 :          group != m_aRadioGroupWidgets.end(); ++group )
   11813                 :            :     {
   11814         [ #  # ]:          0 :         PDFWidget& rGroupWidget = m_aWidgets[ group->second ];
   11815                 :            :         // check whether all kids have a unique OnValue
   11816         [ #  # ]:          0 :         boost::unordered_map< OUString, sal_Int32, OUStringHash > aOnValues;
   11817                 :          0 :         int nChildren = rGroupWidget.m_aKidsIndex.size();
   11818                 :          0 :         bool bIsUnique = true;
   11819 [ #  # ][ #  # ]:          0 :         for( int nKid = 0; nKid < nChildren && bIsUnique; nKid++ )
                 [ #  # ]
   11820                 :            :         {
   11821         [ #  # ]:          0 :             int nKidIndex = rGroupWidget.m_aKidsIndex[nKid];
   11822                 :          0 :             const OUString& rVal = m_aWidgets[nKidIndex].m_aOnValue;
   11823                 :            :             #if OSL_DEBUG_LEVEL > 1
   11824                 :            :             fprintf( stderr, "OnValue: %s\n", OUStringToOString( rVal, RTL_TEXTENCODING_UTF8 ).getStr() );
   11825                 :            :             #endif
   11826 [ #  # ][ #  # ]:          0 :             if( aOnValues.find( rVal ) == aOnValues.end() )
                 [ #  # ]
   11827                 :            :             {
   11828         [ #  # ]:          0 :                 aOnValues[ rVal ] = 1;
   11829                 :            :             }
   11830                 :            :             else
   11831                 :            :             {
   11832                 :          0 :                 bIsUnique = false;
   11833                 :            :             }
   11834                 :            :         }
   11835         [ #  # ]:          0 :         if( ! bIsUnique )
   11836                 :            :         {
   11837                 :            :             #if OSL_DEBUG_LEVEL > 1
   11838                 :            :             fprintf( stderr, "enforcing unique OnValues\n" );
   11839                 :            :             #endif
   11840                 :            :             // make unique by using ascending OnValues
   11841         [ #  # ]:          0 :             for( int nKid = 0; nKid < nChildren; nKid++ )
   11842                 :            :             {
   11843         [ #  # ]:          0 :                 int nKidIndex = rGroupWidget.m_aKidsIndex[nKid];
   11844                 :          0 :                 PDFWidget& rKid = m_aWidgets[nKidIndex];
   11845                 :          0 :                 rKid.m_aOnValue = OUString::valueOf( sal_Int32(nKid+1) );
   11846         [ #  # ]:          0 :                 if( rKid.m_aValue != "Off" )
   11847                 :          0 :                     rKid.m_aValue = rKid.m_aOnValue;
   11848                 :            :             }
   11849                 :            :         }
   11850                 :            :         // finally move the "Yes" appearance to the OnValue appearance
   11851         [ #  # ]:          0 :         for( int nKid = 0; nKid < nChildren; nKid++ )
   11852                 :            :         {
   11853         [ #  # ]:          0 :             int nKidIndex = rGroupWidget.m_aKidsIndex[nKid];
   11854                 :          0 :             PDFWidget& rKid = m_aWidgets[nKidIndex];
   11855         [ #  # ]:          0 :             PDFAppearanceMap::iterator app_it = rKid.m_aAppearances.find( "N" );
   11856 [ #  # ][ #  # ]:          0 :             if( app_it != rKid.m_aAppearances.end() )
   11857                 :            :             {
   11858 [ #  # ][ #  # ]:          0 :                 PDFAppearanceStreams::iterator stream_it = app_it->second.find( "Yes" );
   11859 [ #  # ][ #  # ]:          0 :                 if( stream_it != app_it->second.end() )
                 [ #  # ]
   11860                 :            :                 {
   11861         [ #  # ]:          0 :                     SvMemoryStream* pStream = stream_it->second;
   11862 [ #  # ][ #  # ]:          0 :                     app_it->second.erase( stream_it );
   11863                 :          0 :                     OStringBuffer aBuf( rKid.m_aOnValue.getLength()*2 );
   11864         [ #  # ]:          0 :                     appendName( rKid.m_aOnValue, aBuf );
   11865 [ #  # ][ #  # ]:          0 :                     (app_it->second)[ aBuf.makeStringAndClear() ] = pStream;
   11866                 :            :                 }
   11867                 :            :                 #if OSL_DEBUG_LEVEL > 1
   11868                 :            :                 else
   11869                 :            :                     fprintf( stderr, "error: RadioButton without \"Yes\" stream\n" );
   11870                 :            :                 #endif
   11871                 :            :             }
   11872                 :            :             // update selected radio button
   11873         [ #  # ]:          0 :             if( rKid.m_aValue != "Off" )
   11874                 :            :             {
   11875                 :          0 :                 rGroupWidget.m_aValue = rKid.m_aValue;
   11876                 :            :             }
   11877                 :            :         }
   11878         [ #  # ]:          0 :     }
   11879                 :          0 : }
   11880                 :            : 
   11881                 :          0 : sal_Int32 PDFWriterImpl::findRadioGroupWidget( const PDFWriter::RadioButtonWidget& rBtn )
   11882                 :            : {
   11883                 :          0 :     sal_Int32 nRadioGroupWidget = -1;
   11884                 :            : 
   11885 [ #  # ][ #  # ]:          0 :     std::map< sal_Int32, sal_Int32 >::const_iterator it = m_aRadioGroupWidgets.find( rBtn.RadioGroup );
   11886                 :            : 
   11887 [ #  # ][ #  # ]:          0 :     if( it == m_aRadioGroupWidgets.end() )
                 [ #  # ]
   11888                 :            :     {
   11889         [ #  # ]:          0 :         m_aRadioGroupWidgets[ rBtn.RadioGroup ] = nRadioGroupWidget =
   11890                 :          0 :             sal_Int32(m_aWidgets.size());
   11891                 :            : 
   11892                 :            :         // new group, insert the radiobutton
   11893 [ #  # ][ #  # ]:          0 :         m_aWidgets.push_back( PDFWidget() );
                 [ #  # ]
   11894 [ #  # ][ #  # ]:          0 :         m_aWidgets.back().m_nObject     = createObject();
   11895         [ #  # ]:          0 :         m_aWidgets.back().m_nPage       = m_nCurrentPage;
   11896         [ #  # ]:          0 :         m_aWidgets.back().m_eType       = PDFWriter::RadioButton;
   11897         [ #  # ]:          0 :         m_aWidgets.back().m_nRadioGroup = rBtn.RadioGroup;
   11898         [ #  # ]:          0 :         m_aWidgets.back().m_nFlags |= 0x0000C000;   // NoToggleToOff and Radio bits
   11899                 :            : 
   11900         [ #  # ]:          0 :         createWidgetFieldName( sal_Int32(m_aWidgets.size()-1), rBtn );
   11901                 :            :     }
   11902                 :            :     else
   11903         [ #  # ]:          0 :         nRadioGroupWidget = it->second;
   11904                 :            : 
   11905                 :          0 :     return nRadioGroupWidget;
   11906                 :            : }
   11907                 :            : 
   11908                 :          0 : sal_Int32 PDFWriterImpl::createControl( const PDFWriter::AnyWidget& rControl, sal_Int32 nPageNr )
   11909                 :            : {
   11910         [ #  # ]:          0 :     if( nPageNr < 0 )
   11911                 :          0 :         nPageNr = m_nCurrentPage;
   11912                 :            : 
   11913 [ #  # ][ #  # ]:          0 :     if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() )
                 [ #  # ]
   11914                 :          0 :         return -1;
   11915                 :            : 
   11916                 :          0 :     bool sigHidden(true);
   11917                 :          0 :     sal_Int32 nNewWidget = m_aWidgets.size();
   11918 [ #  # ][ #  # ]:          0 :     m_aWidgets.push_back( PDFWidget() );
                 [ #  # ]
   11919                 :            : 
   11920 [ #  # ][ #  # ]:          0 :     m_aWidgets.back().m_nObject         = createObject();
   11921         [ #  # ]:          0 :     m_aWidgets.back().m_aRect           = rControl.Location;
   11922         [ #  # ]:          0 :     m_aWidgets.back().m_nPage           = nPageNr;
   11923         [ #  # ]:          0 :     m_aWidgets.back().m_eType           = rControl.getType();
   11924                 :            : 
   11925                 :          0 :     sal_Int32 nRadioGroupWidget = -1;
   11926                 :            :     // for unknown reasons the radio buttons of a radio group must not have a
   11927                 :            :     // field name, else the buttons are in fact check boxes -
   11928                 :            :     // that is multiple buttons of the radio group can be selected
   11929         [ #  # ]:          0 :     if( rControl.getType() == PDFWriter::RadioButton )
   11930         [ #  # ]:          0 :         nRadioGroupWidget = findRadioGroupWidget( static_cast<const PDFWriter::RadioButtonWidget&>(rControl) );
   11931                 :            :     else
   11932                 :            :     {
   11933         [ #  # ]:          0 :         createWidgetFieldName( nNewWidget, rControl );
   11934                 :            :     }
   11935                 :            : 
   11936                 :            :     // caution: m_aWidgets must not be changed after here or rNewWidget may be invalid
   11937                 :          0 :     PDFWidget& rNewWidget           = m_aWidgets[nNewWidget];
   11938                 :          0 :     rNewWidget.m_aDescription       = rControl.Description;
   11939                 :          0 :     rNewWidget.m_aText              = rControl.Text;
   11940                 :            :     rNewWidget.m_nTextStyle         = rControl.TextStyle &
   11941                 :            :         (  TEXT_DRAW_LEFT | TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT | TEXT_DRAW_TOP |
   11942                 :            :            TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM |
   11943                 :          0 :            TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK  );
   11944                 :          0 :     rNewWidget.m_nTabOrder          = rControl.TabOrder;
   11945                 :            : 
   11946                 :            :     // various properties are set via the flags (/Ff) property of the field dict
   11947         [ #  # ]:          0 :     if( rControl.ReadOnly )
   11948                 :          0 :         rNewWidget.m_nFlags |= 1;
   11949         [ #  # ]:          0 :     if( rControl.getType() == PDFWriter::PushButton )
   11950                 :            :     {
   11951                 :          0 :         const PDFWriter::PushButtonWidget& rBtn = static_cast<const PDFWriter::PushButtonWidget&>(rControl);
   11952         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   11953                 :            :             rNewWidget.m_nTextStyle =
   11954                 :            :                 TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER |
   11955                 :          0 :                 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK;
   11956                 :            : 
   11957                 :          0 :         rNewWidget.m_nFlags |= 0x00010000;
   11958         [ #  # ]:          0 :         if( !rBtn.URL.isEmpty() )
   11959         [ #  # ]:          0 :             rNewWidget.m_aListEntries.push_back( rBtn.URL );
   11960                 :          0 :         rNewWidget.m_bSubmit    = rBtn.Submit;
   11961                 :          0 :         rNewWidget.m_bSubmitGet = rBtn.SubmitGet;
   11962                 :          0 :         rNewWidget.m_nDest      = rBtn.Dest;
   11963         [ #  # ]:          0 :         createDefaultPushButtonAppearance( rNewWidget, rBtn );
   11964                 :            :     }
   11965         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::RadioButton )
   11966                 :            :     {
   11967                 :          0 :         const PDFWriter::RadioButtonWidget& rBtn = static_cast<const PDFWriter::RadioButtonWidget&>(rControl);
   11968         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   11969                 :            :             rNewWidget.m_nTextStyle =
   11970                 :          0 :                 TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK;
   11971                 :            :         /*  PDF sees a RadioButton group as one radio button with
   11972                 :            :          *  children which are in turn check boxes
   11973                 :            :          *
   11974                 :            :          *  so we need to create a radio button on demand for a new group
   11975                 :            :          *  and insert a checkbox for each RadioButtonWidget as its child
   11976                 :            :          */
   11977                 :          0 :         rNewWidget.m_eType          = PDFWriter::CheckBox;
   11978                 :          0 :         rNewWidget.m_nRadioGroup    = rBtn.RadioGroup;
   11979                 :            : 
   11980                 :            :         DBG_ASSERT( nRadioGroupWidget >= 0 && nRadioGroupWidget < (sal_Int32)m_aWidgets.size(), "no radio group parent" );
   11981                 :            : 
   11982                 :          0 :         PDFWidget& rRadioButton = m_aWidgets[nRadioGroupWidget];
   11983         [ #  # ]:          0 :         rRadioButton.m_aKids.push_back( rNewWidget.m_nObject );
   11984         [ #  # ]:          0 :         rRadioButton.m_aKidsIndex.push_back( nNewWidget );
   11985                 :          0 :         rNewWidget.m_nParent = rRadioButton.m_nObject;
   11986                 :            : 
   11987                 :          0 :         rNewWidget.m_aValue     = OUString( "Off"  );
   11988                 :          0 :         rNewWidget.m_aOnValue   = rBtn.OnValue;
   11989 [ #  # ][ #  # ]:          0 :         if( rRadioButton.m_aValue.isEmpty() && rBtn.Selected )
                 [ #  # ]
   11990                 :            :         {
   11991                 :          0 :             rNewWidget.m_aValue     = rNewWidget.m_aOnValue;
   11992                 :          0 :             rRadioButton.m_aValue   = rNewWidget.m_aOnValue;
   11993                 :            :         }
   11994         [ #  # ]:          0 :         createDefaultRadioButtonAppearance( rNewWidget, rBtn );
   11995                 :            : 
   11996                 :            :         // union rect of radio group
   11997                 :          0 :         Rectangle aRect = rNewWidget.m_aRect;
   11998         [ #  # ]:          0 :         m_aPages[ nPageNr ].convertRect( aRect );
   11999         [ #  # ]:          0 :         rRadioButton.m_aRect.Union( aRect );
   12000                 :            :     }
   12001         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::CheckBox )
   12002                 :            :     {
   12003                 :          0 :         const PDFWriter::CheckBoxWidget& rBox = static_cast<const PDFWriter::CheckBoxWidget&>(rControl);
   12004         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   12005                 :            :             rNewWidget.m_nTextStyle =
   12006                 :          0 :                 TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK;
   12007                 :            : 
   12008 [ #  # ][ #  # ]:          0 :         rNewWidget.m_aValue = rBox.Checked ? OUString("Yes") : OUString("Off" );
                 [ #  # ]
   12009                 :            :         // create default appearance before m_aRect gets transformed
   12010         [ #  # ]:          0 :         createDefaultCheckBoxAppearance( rNewWidget, rBox );
   12011                 :            :     }
   12012         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::ListBox )
   12013                 :            :     {
   12014         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   12015                 :          0 :             rNewWidget.m_nTextStyle = TEXT_DRAW_VCENTER;
   12016                 :            : 
   12017                 :          0 :         const PDFWriter::ListBoxWidget& rLstBox = static_cast<const PDFWriter::ListBoxWidget&>(rControl);
   12018         [ #  # ]:          0 :         rNewWidget.m_aListEntries     = rLstBox.Entries;
   12019         [ #  # ]:          0 :         rNewWidget.m_aSelectedEntries = rLstBox.SelectedEntries;
   12020                 :          0 :         rNewWidget.m_aValue           = rLstBox.Text;
   12021         [ #  # ]:          0 :         if( rLstBox.DropDown )
   12022                 :          0 :             rNewWidget.m_nFlags |= 0x00020000;
   12023         [ #  # ]:          0 :         if( rLstBox.Sort )
   12024                 :          0 :             rNewWidget.m_nFlags |= 0x00080000;
   12025 [ #  # ][ #  # ]:          0 :         if( rLstBox.MultiSelect && !rLstBox.DropDown && (int)m_aContext.Version > (int)PDFWriter::PDF_1_3 )
                 [ #  # ]
   12026                 :          0 :             rNewWidget.m_nFlags |= 0x00200000;
   12027                 :            : 
   12028         [ #  # ]:          0 :         createDefaultListBoxAppearance( rNewWidget, rLstBox );
   12029                 :            :     }
   12030         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::ComboBox )
   12031                 :            :     {
   12032         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   12033                 :          0 :             rNewWidget.m_nTextStyle = TEXT_DRAW_VCENTER;
   12034                 :            : 
   12035                 :          0 :         const PDFWriter::ComboBoxWidget& rBox = static_cast<const PDFWriter::ComboBoxWidget&>(rControl);
   12036                 :          0 :         rNewWidget.m_aValue         = rBox.Text;
   12037         [ #  # ]:          0 :         rNewWidget.m_aListEntries   = rBox.Entries;
   12038                 :          0 :         rNewWidget.m_nFlags |= 0x00060000; // combo and edit flag
   12039         [ #  # ]:          0 :         if( rBox.Sort )
   12040                 :          0 :             rNewWidget.m_nFlags |= 0x00080000;
   12041                 :            : 
   12042         [ #  # ]:          0 :         PDFWriter::ListBoxWidget aLBox;
   12043                 :          0 :         aLBox.Name              = rBox.Name;
   12044                 :          0 :         aLBox.Description       = rBox.Description;
   12045                 :          0 :         aLBox.Text              = rBox.Text;
   12046                 :          0 :         aLBox.TextStyle         = rBox.TextStyle;
   12047                 :          0 :         aLBox.ReadOnly          = rBox.ReadOnly;
   12048                 :          0 :         aLBox.Border            = rBox.Border;
   12049                 :          0 :         aLBox.BorderColor       = rBox.BorderColor;
   12050                 :          0 :         aLBox.Background        = rBox.Background;
   12051                 :          0 :         aLBox.BackgroundColor   = rBox.BackgroundColor;
   12052         [ #  # ]:          0 :         aLBox.TextFont          = rBox.TextFont;
   12053                 :          0 :         aLBox.TextColor         = rBox.TextColor;
   12054                 :          0 :         aLBox.DropDown          = true;
   12055                 :          0 :         aLBox.Sort              = rBox.Sort;
   12056                 :          0 :         aLBox.MultiSelect       = false;
   12057         [ #  # ]:          0 :         aLBox.Entries           = rBox.Entries;
   12058                 :            : 
   12059 [ #  # ][ #  # ]:          0 :         createDefaultListBoxAppearance( rNewWidget, aLBox );
   12060                 :            :     }
   12061         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::Edit )
   12062                 :            :     {
   12063         [ #  # ]:          0 :         if( rNewWidget.m_nTextStyle == 0 )
   12064                 :          0 :             rNewWidget.m_nTextStyle = TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER;
   12065                 :            : 
   12066                 :          0 :         const PDFWriter::EditWidget& rEdit = static_cast<const  PDFWriter::EditWidget&>(rControl);
   12067         [ #  # ]:          0 :         if( rEdit.MultiLine )
   12068                 :            :         {
   12069                 :          0 :             rNewWidget.m_nFlags |= 0x00001000;
   12070                 :          0 :             rNewWidget.m_nTextStyle |= TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK;
   12071                 :            :         }
   12072         [ #  # ]:          0 :         if( rEdit.Password )
   12073                 :          0 :             rNewWidget.m_nFlags |= 0x00002000;
   12074 [ #  # ][ #  # ]:          0 :         if( rEdit.FileSelect && m_aContext.Version > PDFWriter::PDF_1_3 )
   12075                 :          0 :             rNewWidget.m_nFlags |= 0x00100000;
   12076                 :          0 :         rNewWidget.m_nMaxLen = rEdit.MaxLen;
   12077                 :          0 :         rNewWidget.m_aValue = rEdit.Text;
   12078                 :            : 
   12079         [ #  # ]:          0 :         createDefaultEditAppearance( rNewWidget, rEdit );
   12080                 :            :     }
   12081                 :            : #if !defined(ANDROID) && !defined(IOS)
   12082         [ #  # ]:          0 :     else if( rControl.getType() == PDFWriter::Signature)
   12083                 :            :     {
   12084                 :          0 :         const PDFWriter::SignatureWidget& rSig = static_cast<const PDFWriter::SignatureWidget&>(rControl);
   12085                 :          0 :         sigHidden = rSig.SigHidden;
   12086                 :            : 
   12087         [ #  # ]:          0 :         if ( sigHidden )
   12088         [ #  # ]:          0 :             rNewWidget.m_aRect = Rectangle(0, 0, 0, 0);
   12089                 :            : 
   12090         [ #  # ]:          0 :         m_nSignatureObject = createObject();
   12091                 :          0 :         rNewWidget.m_aValue = OUString::valueOf( m_nSignatureObject );
   12092                 :          0 :         rNewWidget.m_aValue += OUString(" 0 R");
   12093                 :            :         //createDefaultSignatureAppearance( rNewWidget, rSig );
   12094                 :            :         // let's add a fake appearance
   12095 [ #  # ][ #  # ]:          0 :         rNewWidget.m_aAppearances[ "N" ][ "Standard" ] = new SvMemoryStream();
         [ #  # ][ #  # ]
   12096                 :            :     }
   12097                 :            : #endif
   12098                 :            : 
   12099                 :            :     // if control is a hidden signature, do not convert coordinates since we
   12100                 :            :     // need /Rect [ 0 0 0 0 ]
   12101 [ #  # ][ #  # ]:          0 :     if ( ! ( ( rControl.getType() == PDFWriter::Signature ) && ( sigHidden ) ) )
                 [ #  # ]
   12102                 :            :     {
   12103                 :            :         // convert to default user space now, since the mapmode may change
   12104                 :            :         // note: create default appearances before m_aRect gets transformed
   12105         [ #  # ]:          0 :         m_aPages[ nPageNr ].convertRect( rNewWidget.m_aRect );
   12106                 :            :     }
   12107                 :            : 
   12108                 :            :     // insert widget to page's annotation list
   12109         [ #  # ]:          0 :     m_aPages[ nPageNr ].m_aAnnotations.push_back( rNewWidget.m_nObject );
   12110                 :            : 
   12111                 :            :     // mark page as having widgets
   12112                 :          0 :     m_aPages[ nPageNr ].m_bHasWidgets = true;
   12113                 :            : 
   12114                 :          0 :     return nNewWidget;
   12115                 :            : }
   12116                 :            : 
   12117                 :          0 : void PDFWriterImpl::addStream( const String& rMimeType, PDFOutputStream* pStream, bool bCompress )
   12118                 :            : {
   12119         [ #  # ]:          0 :     if( pStream )
   12120                 :            :     {
   12121         [ #  # ]:          0 :         m_aAdditionalStreams.push_back( PDFAddStream() );
   12122                 :          0 :         PDFAddStream& rStream = m_aAdditionalStreams.back();
   12123                 :          0 :         rStream.m_aMimeType = rMimeType.Len()
   12124                 :            :                               ? OUString( rMimeType )
   12125 [ #  # ][ #  # ]:          0 :                               : OUString( "application/octet-stream"  );
         [ #  # ][ #  # ]
   12126                 :          0 :         rStream.m_pStream = pStream;
   12127                 :          0 :         rStream.m_bCompress = bCompress;
   12128                 :            :     }
   12129                 :          0 : }
   12130                 :            : 
   12131                 :            : 
   12132                 :            : 
   12133                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10