LCOV - code coverage report
Current view: top level - sw/source/core/text - EnhancedPDFExportHelper.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 915 0.0 %
Date: 2014-04-14 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/embed/XEmbeddedObject.hpp>
      21             : #include <com/sun/star/i18n/ScriptType.hpp>
      22             : #include <EnhancedPDFExportHelper.hxx>
      23             : #include <hintids.hxx>
      24             : 
      25             : #include <vcl/outdev.hxx>
      26             : #include <tools/multisel.hxx>
      27             : #include <editeng/adjustitem.hxx>
      28             : #include <editeng/lrspitem.hxx>
      29             : #include <editeng/langitem.hxx>
      30             : #include <editeng/scripttypeitem.hxx>
      31             : #include <tools/urlobj.hxx>
      32             : #include <svl/zforlist.hxx>
      33             : #include <swatrset.hxx>
      34             : #include <frmatr.hxx>
      35             : #include <paratr.hxx>
      36             : #include <ndtxt.hxx>
      37             : #include <ndole.hxx>
      38             : #include <section.hxx>
      39             : #include <tox.hxx>
      40             : #include <fmtfld.hxx>
      41             : #include <txtinet.hxx>
      42             : #include <fmtinfmt.hxx>
      43             : #include <fchrfmt.hxx>
      44             : #include <charfmt.hxx>
      45             : #include <fmtanchr.hxx>
      46             : #include <fmturl.hxx>
      47             : #include <editsh.hxx>
      48             : #include <viscrs.hxx>
      49             : #include <txtfld.hxx>
      50             : #include <reffld.hxx>
      51             : #include <doc.hxx>
      52             : #include <docary.hxx>
      53             : #include <crsskip.hxx>
      54             : #include <mdiexp.hxx>
      55             : #include <docufld.hxx>
      56             : #include <ftnidx.hxx>
      57             : #include <txtftn.hxx>
      58             : #include <rootfrm.hxx>
      59             : #include <pagefrm.hxx>
      60             : #include <txtfrm.hxx>
      61             : #include <tabfrm.hxx>
      62             : #include <rowfrm.hxx>
      63             : #include <cellfrm.hxx>
      64             : #include <sectfrm.hxx>
      65             : #include <flyfrm.hxx>
      66             : #include <notxtfrm.hxx>
      67             : #include <porfld.hxx>
      68             : #include <SwStyleNameMapper.hxx>
      69             : #include <itrpaint.hxx>
      70             : #include "i18nlangtag/languagetag.hxx"
      71             : #include <IMark.hxx>
      72             : #include <SwNodeNum.hxx>
      73             : #include <switerator.hxx>
      74             : #include <stack>
      75             : 
      76             : #include <tools/globname.hxx>
      77             : 
      78             : using namespace ::com::sun::star;
      79             : 
      80             : // Some static data structures
      81             : 
      82           0 : TableColumnsMap SwEnhancedPDFExportHelper::aTableColumnsMap;
      83           0 : LinkIdMap SwEnhancedPDFExportHelper::aLinkIdMap;
      84           0 : NumListIdMap SwEnhancedPDFExportHelper::aNumListIdMap;
      85           0 : NumListBodyIdMap SwEnhancedPDFExportHelper::aNumListBodyIdMap;
      86           0 : FrmTagIdMap SwEnhancedPDFExportHelper::aFrmTagIdMap;
      87             : 
      88             : LanguageType SwEnhancedPDFExportHelper::eLanguageDefault = 0;
      89             : 
      90             : #if OSL_DEBUG_LEVEL > 1
      91             : 
      92             : static std::vector< sal_uInt16 > aStructStack;
      93             : 
      94             : void lcl_DBGCheckStack()
      95             : {
      96             :     /* NonStructElement = 0     Document = 1        Part = 2
      97             :      * Article = 3              Section = 4         Division = 5
      98             :      * BlockQuote = 6           Caption = 7         TOC = 8
      99             :      * TOCI = 9                 Index = 10          Paragraph = 11
     100             :      * Heading = 12             H1-6 = 13 - 18      List = 19
     101             :      * ListItem = 20            LILabel = 21        LIBody = 22
     102             :      * Table = 23               TableRow = 24       TableHeader = 25
     103             :      * TableData = 26           Span = 27           Quote = 28
     104             :      * Note = 29                Reference = 30      BibEntry = 31
     105             :      * Code = 32                Link = 33           Figure = 34
     106             :      * Formula = 35             Form = 36           Continued frame = 99
     107             :      */
     108             : 
     109             :     sal_uInt16 nElement;
     110             :     std::vector< sal_uInt16 >::iterator aIter;
     111             :     for ( aIter = aStructStack.begin(); aIter != aStructStack.end(); ++aIter )
     112             :     {
     113             :         nElement = *aIter;
     114             :     }
     115             :     (void)nElement;
     116             : }
     117             : 
     118             : #endif
     119             : 
     120             : namespace
     121             : {
     122             : // ODF Style Names:
     123             : const char aTableHeadingName[]  = "Table Heading";
     124             : const char aQuotations[]        = "Quotations";
     125             : const char aCaption[]           = "Caption";
     126             : const char aHeading[]           = "Heading";
     127             : const char aQuotation[]         = "Quotation";
     128             : const char aSourceText[]        = "Source Text";
     129             : 
     130             : // PDF Tag Names:
     131             : const char aDocumentString[] = "Document";
     132             : const char aDivString[] = "Div";
     133             : const char aSectString[] = "Sect";
     134             : const char aHString[] = "H";
     135             : const char aH1String[] = "H1";
     136             : const char aH2String[] = "H2";
     137             : const char aH3String[] = "H3";
     138             : const char aH4String[] = "H4";
     139             : const char aH5String[] = "H5";
     140             : const char aH6String[] = "H6";
     141             : const char aListString[] = "L";
     142             : const char aListItemString[] = "LI";
     143             : const char aListBodyString[] = "LBody";
     144             : const char aBlockQuoteString[] = "BlockQuote";
     145             : const char aCaptionString[] = "Caption";
     146             : const char aIndexString[] = "Index";
     147             : const char aTOCString[] = "TOC";
     148             : const char aTOCIString[] = "TOCI";
     149             : const char aTableString[] = "Table";
     150             : const char aTRString[] = "TR";
     151             : const char aTDString[] = "TD";
     152             : const char aTHString[] = "TH";
     153             : const char aBibEntryString[] = "BibEntry";
     154             : const char aQuoteString[] = "Quote";
     155             : const char aSpanString[] = "Span";
     156             : const char aCodeString[] = "Code";
     157             : const char aFigureString[] = "Figure";
     158             : const char aFormulaString[] = "Formula";
     159             : const char aLinkString[] = "Link";
     160             : const char aNoteString[] = "Note";
     161             : 
     162             : // returns true if first paragraph in cell frame has 'table heading' style
     163           0 : bool lcl_IsHeadlineCell( const SwCellFrm& rCellFrm )
     164             : {
     165           0 :     bool bRet = false;
     166             : 
     167           0 :     const SwCntntFrm *pCnt = rCellFrm.ContainsCntnt();
     168           0 :     if ( pCnt && pCnt->IsTxtFrm() )
     169             :     {
     170           0 :         const SwTxtNode* pTxtNode = static_cast<const SwTxtFrm*>(pCnt)->GetTxtNode();
     171           0 :         const SwFmt* pTxtFmt = pTxtNode->GetFmtColl();
     172             : 
     173           0 :         OUString sStyleName;
     174           0 :         SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
     175           0 :         bRet = sStyleName.equalsAscii(aTableHeadingName);
     176             :     }
     177             : 
     178           0 :     return bRet;
     179             : }
     180             : 
     181             : // List all frames for which the NonStructElement tag is set:
     182           0 : bool lcl_IsInNonStructEnv( const SwFrm& rFrm )
     183             : {
     184           0 :     bool bRet = false;
     185             : 
     186           0 :     if ( 0 != rFrm.FindFooterOrHeader() &&
     187           0 :            !rFrm.IsHeaderFrm() && !rFrm.IsFooterFrm() )
     188             :     {
     189           0 :         bRet = true;
     190             :     }
     191           0 :     else if ( rFrm.IsInTab() && !rFrm.IsTabFrm() )
     192             :     {
     193           0 :         const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
     194           0 :         if ( rFrm.GetUpper() != pTabFrm &&
     195           0 :              pTabFrm->IsFollow() && pTabFrm->IsInHeadline( rFrm ) )
     196           0 :              bRet = true;
     197             :     }
     198             : 
     199           0 :     return bRet;
     200             : }
     201             : 
     202             : // Generate key from frame for reopening tags:
     203           0 : void* lcl_GetKeyFromFrame( const SwFrm& rFrm )
     204             : {
     205           0 :     void* pKey = 0;
     206             : 
     207           0 :     if ( rFrm.IsPageFrm() )
     208           0 :         pKey = (void*)static_cast<const SwPageFrm&>(rFrm).GetFmt()->getIDocumentSettingAccess();
     209           0 :     else if ( rFrm.IsTxtFrm() )
     210           0 :         pKey = (void*)static_cast<const SwTxtFrm&>(rFrm).GetTxtNode();
     211           0 :     else if ( rFrm.IsSctFrm() )
     212           0 :         pKey = (void*)static_cast<const SwSectionFrm&>(rFrm).GetSection();
     213           0 :     else if ( rFrm.IsTabFrm() )
     214           0 :         pKey = (void*)static_cast<const SwTabFrm&>(rFrm).GetTable();
     215           0 :     else if ( rFrm.IsRowFrm() )
     216           0 :         pKey = (void*)static_cast<const SwRowFrm&>(rFrm).GetTabLine();
     217           0 :     else if ( rFrm.IsCellFrm() )
     218             :     {
     219           0 :         const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
     220           0 :         const SwTable* pTable = pTabFrm->GetTable();
     221           0 :         pKey = (void*) & static_cast<const SwCellFrm&>(rFrm).GetTabBox()->FindStartOfRowSpan( *pTable );
     222             :     }
     223             : 
     224           0 :     return pKey;
     225             : }
     226             : 
     227           0 : bool lcl_HasPreviousParaSameNumRule( const SwTxtNode& rNode )
     228             : {
     229           0 :     bool bRet = false;
     230           0 :     SwNodeIndex aIdx( rNode );
     231           0 :     const SwDoc* pDoc = rNode.GetDoc();
     232           0 :     const SwNodes& rNodes = pDoc->GetNodes();
     233           0 :     const SwNode* pNode = &rNode;
     234           0 :     const SwNumRule* pNumRule = rNode.GetNumRule();
     235             : 
     236           0 :     while (! (pNode == rNodes.DocumentSectionStartNode((SwNode*)&rNode) ) )
     237             :     {
     238           0 :         --aIdx;
     239             : 
     240           0 :         if (aIdx.GetNode().IsTxtNode())
     241             :         {
     242           0 :             const SwTxtNode* pPrevTxtNd = aIdx.GetNode().GetTxtNode();
     243           0 :             const SwNumRule * pPrevNumRule = pPrevTxtNd->GetNumRule();
     244             : 
     245             :             // We find the previous text node. Now check, if the previous text node
     246             :             // has the same numrule like rNode:
     247           0 :             if ( (pPrevNumRule == pNumRule) &&
     248           0 :                  (!pPrevTxtNd->IsOutline() == !rNode.IsOutline()))
     249           0 :                 bRet = true;
     250             : 
     251           0 :             break;
     252             :         }
     253             : 
     254           0 :         pNode = &aIdx.GetNode();
     255             :     }
     256           0 :     return bRet;
     257             : }
     258             : 
     259             : } // end namespace
     260             : 
     261             : /*
     262             :  * SwTaggedPDFHelper::SwTaggedPDFHelper()
     263             :  */
     264           0 : SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info* pNumInfo,
     265             :                                       const Frm_Info* pFrmInfo,
     266             :                                       const Por_Info* pPorInfo,
     267             :                                       OutputDevice& rOut )
     268             :   : nEndStructureElement( 0 ),
     269             :     nRestoreCurrentTag( -1 ),
     270             :     mpNumInfo( pNumInfo ),
     271             :     mpFrmInfo( pFrmInfo ),
     272           0 :     mpPorInfo( pPorInfo )
     273             : {
     274             :     mpPDFExtOutDevData =
     275           0 :         PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
     276             : 
     277           0 :     if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
     278             :     {
     279             : #if OSL_DEBUG_LEVEL > 1
     280             :         sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
     281             :         lcl_DBGCheckStack();
     282             : #endif
     283           0 :         if ( mpNumInfo )
     284           0 :             BeginNumberedListStructureElements();
     285           0 :         else if ( mpFrmInfo )
     286           0 :             BeginBlockStructureElements();
     287           0 :         else if ( mpPorInfo )
     288           0 :             BeginInlineStructureElements();
     289             :         else
     290           0 :             BeginTag( vcl::PDFWriter::NonStructElement, OUString() );
     291             : 
     292             : #if OSL_DEBUG_LEVEL > 1
     293             :         nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
     294             :         lcl_DBGCheckStack();
     295             :         (void)nCurrentStruct;
     296             : #endif
     297             :     }
     298           0 : }
     299             : 
     300             : /*
     301             :  * SwTaggedPDFHelper::~SwTaggedPDFHelper()
     302             :  */
     303           0 : SwTaggedPDFHelper::~SwTaggedPDFHelper()
     304             : {
     305           0 :     if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
     306             :     {
     307             : #if OSL_DEBUG_LEVEL > 1
     308             :         sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
     309             :         lcl_DBGCheckStack();
     310             : #endif
     311           0 :         EndStructureElements();
     312             : 
     313             : #if OSL_DEBUG_LEVEL > 1
     314             :         nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
     315             :         lcl_DBGCheckStack();
     316             :         (void)nCurrentStruct;
     317             : #endif
     318             : 
     319             :     }
     320           0 : }
     321             : 
     322             : /*
     323             :  * SwTaggedPDFHelper::CheckReopenTag()
     324             :  */
     325           0 : bool SwTaggedPDFHelper::CheckReopenTag()
     326             : {
     327           0 :     bool bRet = false;
     328           0 :     sal_Int32 nReopenTag = -1;
     329           0 :     bool bContinue = false; // in some cases we just have to reopen a tag without early returning
     330             : 
     331           0 :     if ( mpFrmInfo )
     332             :     {
     333           0 :         const SwFrm& rFrm = mpFrmInfo->mrFrm;
     334           0 :         const SwFrm* pKeyFrm = 0;
     335           0 :         void* pKey = 0;
     336             : 
     337             :         // Reopen an existing structure element if
     338             :         // - rFrm is not the first page frame (reopen Document tag)
     339             :         // - rFrm is a follow frame (reopen Master tag)
     340             :         // - rFrm is a fly frame anchored at content (reopen Anchor paragraph tag)
     341             :         // - rFrm is a fly frame anchord at page (reopen Document tag)
     342             :         // - rFrm is a follow flow row (reopen TableRow tag)
     343             :         // - rFrm is a cell frame in a follow flow row (reopen TableData tag)
     344           0 :         if ( ( rFrm.IsPageFrm() && static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
     345           0 :              ( rFrm.IsFlowFrm() && SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() ) ||
     346           0 :              ( rFrm.IsRowFrm() && rFrm.IsInFollowFlowRow() ) ||
     347           0 :              ( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetPrevCellLeaf( MAKEPAGE_NONE ) ) )
     348             :         {
     349           0 :             pKeyFrm = &rFrm;
     350             :         }
     351           0 :         else if ( rFrm.IsFlyFrm() )
     352             :         {
     353             :             const SwFmtAnchor& rAnchor =
     354           0 :                 static_cast<const SwFlyFrm*>(&rFrm)->GetFmt()->GetAnchor();
     355           0 :             if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
     356           0 :                 (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
     357           0 :                 (FLY_AT_PAGE == rAnchor.GetAnchorId()))
     358             :             {
     359           0 :                 pKeyFrm = static_cast<const SwFlyFrm&>(rFrm).GetAnchorFrm();
     360           0 :                 bContinue = true;
     361             :             }
     362             :         }
     363             : 
     364           0 :         if ( pKeyFrm )
     365             :         {
     366           0 :             pKey = lcl_GetKeyFromFrame( *pKeyFrm );
     367             : 
     368           0 :             if ( pKey )
     369             :             {
     370           0 :                 FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
     371           0 :                 const FrmTagIdMap::const_iterator aIter =  rFrmTagIdMap.find( pKey );
     372           0 :                 if ( aIter != rFrmTagIdMap.end() )
     373           0 :                     nReopenTag = (*aIter).second;
     374             :             }
     375             :         }
     376             :     }
     377             : 
     378           0 :     if ( -1 != nReopenTag )
     379             :     {
     380           0 :         nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
     381           0 :         const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
     382             :         OSL_ENSURE( bSuccess, "Failed to reopen tag" );
     383             : 
     384             : #if OSL_DEBUG_LEVEL > 1
     385             :         aStructStack.push_back( 99 );
     386             : #endif
     387             : 
     388           0 :         bRet = bSuccess;
     389             :     }
     390             : 
     391           0 :     return bRet && !bContinue;
     392             : }
     393             : 
     394             : /*
     395             :  * SwTaggedPDFHelper::CheckRestoreTag()
     396             :  */
     397           0 : bool SwTaggedPDFHelper::CheckRestoreTag() const
     398             : {
     399           0 :     bool bRet = false;
     400           0 :     if ( nRestoreCurrentTag != -1 )
     401             :     {
     402           0 :         const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nRestoreCurrentTag );
     403             :         (void)bSuccess;
     404             :         OSL_ENSURE( bSuccess, "Failed to restore reopened tag" );
     405             : 
     406             : #if OSL_DEBUG_LEVEL > 1
     407             :         aStructStack.pop_back();
     408             : #endif
     409             : 
     410           0 :         bRet = true;
     411             :     }
     412             : 
     413           0 :     return bRet;
     414             : }
     415             : 
     416             : /*
     417             :  * SwTaggedPDFHelper::BeginTag()
     418             :  */
     419           0 : void SwTaggedPDFHelper::BeginTag( vcl::PDFWriter::StructElement eType, const OUString& rString )
     420             : {
     421             :     // write new tag
     422           0 :     const sal_Int32 nId = mpPDFExtOutDevData->BeginStructureElement( eType, rString );
     423           0 :     ++nEndStructureElement;
     424             : 
     425             : #if OSL_DEBUG_LEVEL > 1
     426             :     aStructStack.push_back( static_cast<sal_uInt16>(eType) );
     427             : #endif
     428             : 
     429             :     // Store the id of the current structure element if
     430             :     // - it is a list structure element
     431             :     // - it is a list body element with children
     432             :     // - rFrm is the first page frame
     433             :     // - rFrm is a master frame
     434             :     // - rFrm has objects anchored to it
     435             :     // - rFrm is a row frame or cell frame in a split table row
     436             : 
     437           0 :     if ( mpNumInfo )
     438             :     {
     439           0 :         const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(mpNumInfo->mrFrm);
     440           0 :         const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
     441           0 :         const SwNodeNum* pNodeNum = pTxtNd->GetNum();
     442             : 
     443           0 :         if ( vcl::PDFWriter::List == eType )
     444             :         {
     445           0 :             NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
     446           0 :             rNumListIdMap[ pNodeNum ] = nId;
     447             :         }
     448           0 :         else if ( vcl::PDFWriter::LIBody == eType )
     449             :         {
     450           0 :             NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
     451           0 :             rNumListBodyIdMap[ pNodeNum ] = nId;
     452             :         }
     453             :     }
     454           0 :     else if ( mpFrmInfo )
     455             :     {
     456           0 :         const SwFrm& rFrm = mpFrmInfo->mrFrm;
     457             : 
     458           0 :         if ( ( rFrm.IsPageFrm() && !static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
     459           0 :              ( rFrm.IsFlowFrm() && !SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() && SwFlowFrm::CastFlowFrm(&rFrm)->HasFollow() ) ||
     460           0 :              ( rFrm.IsTxtFrm() && rFrm.GetDrawObjs() ) ||
     461           0 :              ( rFrm.IsRowFrm() && rFrm.IsInSplitTableRow() ) ||
     462           0 :              ( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetNextCellLeaf( MAKEPAGE_NONE ) ) )
     463             :         {
     464           0 :             const void* pKey = lcl_GetKeyFromFrame( rFrm );
     465             : 
     466           0 :             if ( pKey )
     467             :             {
     468           0 :                 FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
     469           0 :                 rFrmTagIdMap[ pKey ] = nId;
     470             :             }
     471             :         }
     472             :     }
     473             : 
     474           0 :     SetAttributes( eType );
     475           0 : }
     476             : 
     477             : /*
     478             :  * SwTaggedPDFHelper::EndTag()
     479             :  */
     480           0 : void SwTaggedPDFHelper::EndTag()
     481             : {
     482           0 :     mpPDFExtOutDevData->EndStructureElement();
     483             : 
     484             : #if OSL_DEBUG_LEVEL > 1
     485             :     aStructStack.pop_back();
     486             : #endif
     487           0 : }
     488             : 
     489             : /*
     490             :  * SwTaggedPDFHelper::SetAttributes()
     491             :  *
     492             :  * Sets the attributes according to the structure type.
     493             :  */
     494           0 : void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
     495             : {
     496             :     vcl::PDFWriter::StructAttributeValue eVal;
     497             :     sal_Int32 nVal;
     498             : 
     499             :     /*
     500             :      * ATTRIBUTES FOR BLSE
     501             :      */
     502           0 :     if ( mpFrmInfo )
     503             :     {
     504           0 :         const SwFrm* pFrm = &mpFrmInfo->mrFrm;
     505           0 :         SWRECTFN( pFrm )
     506             : 
     507           0 :         bool bPlacement = false;
     508           0 :         bool bWritingMode = false;
     509           0 :         bool bSpaceBefore = false;
     510           0 :         bool bSpaceAfter = false;
     511           0 :         bool bStartIndent = false;
     512           0 :         bool bEndIndent = false;
     513           0 :         bool bTextIndent = false;
     514           0 :         bool bTextAlign = false;
     515           0 :         bool bAlternateText = false;
     516           0 :         bool bWidth = false;
     517           0 :         bool bHeight = false;
     518           0 :         bool bBox = false;
     519           0 :         bool bRowSpan = false;
     520             : 
     521             :         // Check which attributes to set:
     522             : 
     523           0 :         switch ( eType )
     524             :         {
     525             :             case vcl::PDFWriter::Document :
     526           0 :                 bWritingMode = true;
     527           0 :                 break;
     528             : 
     529             :             case vcl::PDFWriter::Table :
     530             :                 bPlacement =
     531             :                 bWritingMode =
     532             :                 bSpaceBefore =
     533             :                 bSpaceAfter =
     534             :                 bStartIndent =
     535             :                 bEndIndent =
     536             :                 bWidth =
     537             :                 bHeight =
     538           0 :                 bBox = true;
     539           0 :                 break;
     540             : 
     541             :             case vcl::PDFWriter::TableRow :
     542             :                 bPlacement =
     543           0 :                 bWritingMode = true;
     544           0 :                 break;
     545             : 
     546             :             case vcl::PDFWriter::TableHeader :
     547             :             case vcl::PDFWriter::TableData :
     548             :                 bPlacement =
     549             :                 bWritingMode =
     550             :                 bWidth =
     551             :                 bHeight =
     552           0 :                 bRowSpan = true;
     553           0 :                 break;
     554             : 
     555             :             case vcl::PDFWriter::H1 :
     556             :             case vcl::PDFWriter::H2 :
     557             :             case vcl::PDFWriter::H3 :
     558             :             case vcl::PDFWriter::H4 :
     559             :             case vcl::PDFWriter::H5 :
     560             :             case vcl::PDFWriter::H6 :
     561             :             case vcl::PDFWriter::Paragraph :
     562             :             case vcl::PDFWriter::Heading :
     563             :             case vcl::PDFWriter::Caption :
     564             :             case vcl::PDFWriter::BlockQuote :
     565             : 
     566             :                 bPlacement =
     567             :                 bWritingMode =
     568             :                 bSpaceBefore =
     569             :                 bSpaceAfter =
     570             :                 bStartIndent =
     571             :                 bEndIndent =
     572             :                 bTextIndent =
     573           0 :                 bTextAlign = true;
     574           0 :                 break;
     575             : 
     576             :             case vcl::PDFWriter::Formula :
     577             :             case vcl::PDFWriter::Figure :
     578             :                 bPlacement =
     579             :                 bAlternateText =
     580             :                 bWidth =
     581             :                 bHeight =
     582           0 :                 bBox = true;
     583           0 :                 break;
     584             :             default :
     585           0 :                 break;
     586             :         }
     587             : 
     588             :         // Set the attributes:
     589             : 
     590           0 :         if ( bPlacement )
     591             :         {
     592           0 :             eVal = vcl::PDFWriter::TableHeader == eType ||
     593             :                    vcl::PDFWriter::TableData   == eType ?
     594             :                    vcl::PDFWriter::Inline :
     595           0 :                    vcl::PDFWriter::Block;
     596             : 
     597           0 :             mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::Placement, eVal );
     598             :         }
     599             : 
     600           0 :         if ( bWritingMode )
     601             :         {
     602           0 :             eVal =  pFrm->IsVertical() ?
     603             :                     vcl::PDFWriter::TbRl :
     604           0 :                     pFrm->IsRightToLeft() ?
     605             :                     vcl::PDFWriter::RlTb :
     606           0 :                     vcl::PDFWriter::LrTb;
     607             : 
     608           0 :             if ( vcl::PDFWriter::LrTb != eVal )
     609           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::WritingMode, eVal );
     610             :         }
     611             : 
     612           0 :         if ( bSpaceBefore )
     613             :         {
     614           0 :             nVal = (pFrm->*fnRect->fnGetTopMargin)();
     615           0 :             if ( 0 != nVal )
     616           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceBefore, nVal );
     617             :         }
     618             : 
     619           0 :         if ( bSpaceAfter )
     620             :         {
     621           0 :             nVal = (pFrm->*fnRect->fnGetBottomMargin)();
     622           0 :             if ( 0 != nVal )
     623           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceAfter, nVal );
     624             :         }
     625             : 
     626           0 :         if ( bStartIndent )
     627             :         {
     628           0 :             nVal = (pFrm->*fnRect->fnGetLeftMargin)();
     629           0 :             if ( 0 != nVal )
     630           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::StartIndent, nVal );
     631             :         }
     632             : 
     633           0 :         if ( bEndIndent )
     634             :         {
     635           0 :             nVal = (pFrm->*fnRect->fnGetRightMargin)();
     636           0 :             if ( 0 != nVal )
     637           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::EndIndent, nVal );
     638             :         }
     639             : 
     640           0 :         if ( bTextIndent )
     641             :         {
     642             :             OSL_ENSURE( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" );
     643             :             const SvxLRSpaceItem &rSpace =
     644           0 :                 static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
     645           0 :             nVal =  rSpace.GetTxtFirstLineOfst();
     646           0 :             if ( 0 != nVal )
     647           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::TextIndent, nVal );
     648             :         }
     649             : 
     650           0 :         if ( bTextAlign )
     651             :         {
     652             :             OSL_ENSURE( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" );
     653           0 :             const SwAttrSet& aSet = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet();
     654           0 :             const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
     655           0 :             if ( SVX_ADJUST_BLOCK == nAdjust || SVX_ADJUST_CENTER == nAdjust ||
     656           0 :                  (  (pFrm->IsRightToLeft() && SVX_ADJUST_LEFT == nAdjust) ||
     657           0 :                    (!pFrm->IsRightToLeft() && SVX_ADJUST_RIGHT == nAdjust) ) )
     658             :             {
     659             :                 eVal = SVX_ADJUST_BLOCK == nAdjust ?
     660             :                        vcl::PDFWriter::Justify :
     661             :                        SVX_ADJUST_CENTER == nAdjust ?
     662             :                        vcl::PDFWriter::Center :
     663           0 :                        vcl::PDFWriter::End;
     664             : 
     665           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextAlign, eVal );
     666             :             }
     667             :         }
     668             : 
     669           0 :         if ( bAlternateText )
     670             :         {
     671             :             OSL_ENSURE( pFrm->IsFlyFrm(), "Frame type <-> tag attribute mismatch" );
     672           0 :             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
     673           0 :             if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
     674             :             {
     675           0 :                 const SwNoTxtFrm* pNoTxtFrm   = static_cast<const SwNoTxtFrm*>(pFly->Lower());
     676           0 :                 const SwNoTxtNode* pNoTxtNode = static_cast<const SwNoTxtNode*>(pNoTxtFrm->GetNode());
     677             : 
     678           0 :                 const OUString aAlternateTxt( pNoTxtNode->GetTitle() );
     679           0 :                 mpPDFExtOutDevData->SetAlternateText( aAlternateTxt );
     680             :             }
     681             :         }
     682             : 
     683           0 :         if ( bWidth )
     684             :         {
     685           0 :             nVal = (pFrm->Frm().*fnRect->fnGetWidth)();
     686           0 :             mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Width, nVal );
     687             :         }
     688             : 
     689           0 :         if ( bHeight )
     690             :         {
     691           0 :             nVal = (pFrm->Frm().*fnRect->fnGetHeight)();
     692           0 :             mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Height, nVal );
     693             :         }
     694             : 
     695           0 :         if ( bBox )
     696             :         {
     697             :             // BBox only for non-split tables:
     698           0 :             if ( vcl::PDFWriter::Table != eType ||
     699           0 :                  ( pFrm->IsTabFrm() &&
     700           0 :                    !static_cast<const SwTabFrm*>(pFrm)->IsFollow() &&
     701           0 :                    !static_cast<const SwTabFrm*>(pFrm)->HasFollow() ) )
     702           0 :                 mpPDFExtOutDevData->SetStructureBoundingBox( pFrm->Frm().SVRect() );
     703             :         }
     704             : 
     705           0 :         if ( bRowSpan )
     706             :         {
     707           0 :             const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(pFrm);
     708           0 :             if ( pThisCell )
     709             :             {
     710           0 :                 nVal =  pThisCell->GetTabBox()->getRowSpan();
     711           0 :                 if ( nVal > 1 )
     712           0 :                     mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::RowSpan, nVal );
     713             : 
     714             :                 // calculate colspan:
     715           0 :                 const SwTabFrm* pTabFrm = pThisCell->FindTabFrm();
     716           0 :                 const SwTable* pTable = pTabFrm->GetTable();
     717             : 
     718           0 :                 SWRECTFNX( pTabFrm )
     719             : 
     720           0 :                 const TableColumnsMapEntry& rCols = SwEnhancedPDFExportHelper::GetTableColumnsMap()[ pTable ];
     721             : 
     722           0 :                 const long nLeft  = (pThisCell->Frm().*fnRectX->fnGetLeft)();
     723           0 :                 const long nRight = (pThisCell->Frm().*fnRectX->fnGetRight)();
     724           0 :                 const TableColumnsMapEntry::const_iterator aLeftIter =  rCols.find( nLeft );
     725           0 :                 const TableColumnsMapEntry::const_iterator aRightIter = rCols.find( nRight );
     726             : 
     727             :                 OSL_ENSURE( aLeftIter != rCols.end() && aRightIter != rCols.end(), "Colspan trouble" );
     728           0 :                 if ( aLeftIter != rCols.end() && aRightIter != rCols.end() )
     729             :                 {
     730           0 :                     nVal = std::distance( aLeftIter, aRightIter );
     731           0 :                     if ( nVal > 1 )
     732           0 :                         mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::ColSpan, nVal );
     733             :                 }
     734             :             }
     735             :         }
     736             :     }
     737             : 
     738             :     /*
     739             :      * ATTRIBUTES FOR ILSE
     740             :      */
     741           0 :     else if ( mpPorInfo )
     742             :     {
     743           0 :         const SwLinePortion* pPor = &mpPorInfo->mrPor;
     744           0 :         const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
     745             : 
     746           0 :         bool bActualText = false;
     747           0 :         bool bBaselineShift = false;
     748           0 :         bool bTextDecorationType = false;
     749           0 :         bool bLinkAttribute = false;
     750           0 :         bool bLanguage = false;
     751             : 
     752             :         // Check which attributes to set:
     753             : 
     754           0 :         switch ( eType )
     755             :         {
     756             :             case vcl::PDFWriter::Span :
     757             :             case vcl::PDFWriter::Quote :
     758             :             case vcl::PDFWriter::Code :
     759           0 :                 if( POR_HYPHSTR == pPor->GetWhichPor() || POR_SOFTHYPHSTR == pPor->GetWhichPor() ||
     760           0 :                     POR_HYPH == pPor->GetWhichPor() || POR_SOFTHYPH == pPor->GetWhichPor() )
     761           0 :                     bActualText = true;
     762             :                 else
     763             :                 {
     764             :                     bBaselineShift =
     765             :                     bTextDecorationType =
     766           0 :                     bLanguage = true;
     767             :                 }
     768           0 :                 break;
     769             : 
     770             :             case vcl::PDFWriter::Link :
     771             :                 bTextDecorationType =
     772             :                 bBaselineShift =
     773             :                 bLinkAttribute =
     774           0 :                 bLanguage = true;
     775           0 :                 break;
     776             : 
     777             :             default:
     778           0 :                 break;
     779             :         }
     780             : 
     781           0 :         if ( bActualText )
     782             :         {
     783           0 :             OUString aActualTxt;
     784           0 :             if (pPor->GetWhichPor() == POR_SOFTHYPH || pPor->GetWhichPor() == POR_HYPH)
     785           0 :                 aActualTxt = OUString(0xad); // soft hyphen
     786             :             else
     787           0 :                 aActualTxt = rInf.GetTxt().copy(rInf.GetIdx(), pPor->GetLen());
     788           0 :             mpPDFExtOutDevData->SetActualText( aActualTxt );
     789             :         }
     790             : 
     791           0 :         if ( bBaselineShift )
     792             :         {
     793             :             // TODO: Calculate correct values!
     794           0 :             nVal = rInf.GetFont()->GetEscapement();
     795           0 :             if ( nVal > 0 ) nVal = 33;
     796           0 :             else if ( nVal < 0 ) nVal = -33;
     797             : 
     798           0 :             if ( 0 != nVal )
     799             :             {
     800           0 :                 nVal = nVal * pPor->Height() / 100;
     801           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::BaselineShift, nVal );
     802             :             }
     803             :         }
     804             : 
     805           0 :         if ( bTextDecorationType )
     806             :         {
     807           0 :             if ( UNDERLINE_NONE    != rInf.GetFont()->GetUnderline() )
     808           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Underline );
     809           0 :             if ( UNDERLINE_NONE    != rInf.GetFont()->GetOverline() )
     810           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
     811           0 :             if ( STRIKEOUT_NONE    != rInf.GetFont()->GetStrikeout() )
     812           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::LineThrough );
     813           0 :             if ( EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() )
     814           0 :                 mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
     815             :         }
     816             : 
     817           0 :         if ( bLanguage )
     818             :         {
     819             : 
     820           0 :             const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
     821           0 :             const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
     822             : 
     823           0 :             if ( nDefaultLang != nCurrentLanguage )
     824           0 :                 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Language, nCurrentLanguage );
     825             :         }
     826             : 
     827           0 :         if ( bLinkAttribute )
     828             :         {
     829           0 :             const LinkIdMap& rLinkIdMap = SwEnhancedPDFExportHelper::GetLinkIdMap();
     830           0 :             SwRect aPorRect;
     831           0 :             rInf.CalcRect( *pPor, &aPorRect );
     832           0 :             const Point aPorCenter = aPorRect.Center();
     833           0 :             LinkIdMap::const_iterator aIter;
     834           0 :             for ( aIter = rLinkIdMap.begin(); aIter != rLinkIdMap.end(); ++aIter )
     835             :             {
     836           0 :                 const SwRect& rLinkRect = (*aIter).first;
     837           0 :                 if ( rLinkRect.IsInside( aPorCenter ) )
     838             :                 {
     839           0 :                     sal_Int32 nLinkId = (*aIter).second;
     840           0 :                     mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::LinkAnnotation, nLinkId );
     841           0 :                     break;
     842             :                 }
     843             :             }
     844             :         }
     845             :     }
     846           0 : }
     847             : 
     848             : /*
     849             :  * SwTaggedPDFHelper::BeginNumberedListStructureElements()
     850             :  */
     851           0 : void SwTaggedPDFHelper::BeginNumberedListStructureElements()
     852             : {
     853             :     OSL_ENSURE( mpNumInfo, "List without mpNumInfo?" );
     854           0 :     if ( !mpNumInfo )
     855           0 :         return;
     856             : 
     857           0 :     const SwFrm& rFrm = mpNumInfo->mrFrm;
     858             :     OSL_ENSURE( rFrm.IsTxtFrm(), "numbered only for text frames" );
     859           0 :     const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(rFrm);
     860             : 
     861             :     // Lowers of NonStructureElements should not be considered:
     862             : 
     863           0 :     if ( lcl_IsInNonStructEnv( rTxtFrm ) || rTxtFrm.IsFollow() )
     864           0 :         return;
     865             : 
     866           0 :     const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
     867           0 :     const SwNumRule* pNumRule = pTxtNd->GetNumRule();
     868           0 :     const SwNodeNum* pNodeNum = pTxtNd->GetNum();
     869             : 
     870           0 :     const bool bNumbered = !pTxtNd->IsOutline() && pNodeNum && pNodeNum->GetParent() && pNumRule;
     871             : 
     872             :     // Check, if we have to reopen a list or a list body:
     873             :     // First condition:
     874             :     // Paragraph is numbered/bulleted
     875           0 :     if ( !bNumbered )
     876           0 :         return;
     877             : 
     878           0 :     const SwNumberTreeNode* pParent = pNodeNum->GetParent();
     879           0 :     const bool bSameNumbering = lcl_HasPreviousParaSameNumRule(*pTxtNd);
     880             : 
     881             :     // Second condition: current numbering is not 'interrupted'
     882           0 :     if ( bSameNumbering )
     883             :     {
     884           0 :         sal_Int32 nReopenTag = -1;
     885             : 
     886             :         // Two cases:
     887             :         // 1. We have to reopen an existing list body tag:
     888             :         // - If the current node is either the first child of its parent
     889             :         //   and its level > 1 or
     890             :         // - Numbering should restart at the current node and its level > 1
     891             :         // - The current item has no label
     892           0 :         const bool bNewSubListStart = pParent->GetParent() && (pParent->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() );
     893           0 :         const bool bNoLabel = !pTxtNd->IsCountedInList() && !pTxtNd->IsListRestart();
     894           0 :         if ( bNewSubListStart || bNoLabel )
     895             :         {
     896             :             // Fine, we try to reopen the appropriate list body
     897           0 :             NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
     898             : 
     899           0 :             if ( bNewSubListStart )
     900             :             {
     901             :                 // The list body tag associated with the parent has to be reopened
     902             :                 // to start a new list inside the list body
     903           0 :                 NumListBodyIdMap::const_iterator aIter;
     904             : 
     905           0 :                 do
     906           0 :                     aIter = rNumListBodyIdMap.find( pParent );
     907           0 :                 while ( aIter == rNumListBodyIdMap.end() && 0 != ( pParent = pParent->GetParent() ) );
     908             : 
     909           0 :                 if ( aIter != rNumListBodyIdMap.end() )
     910           0 :                     nReopenTag = (*aIter).second;
     911             :             }
     912             :             else // if(bNoLabel)
     913             :             {
     914             :                 // The list body tag of a 'counted' predecessor has to be reopened
     915           0 :                 const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
     916           0 :                 while ( pPrevious )
     917             :                 {
     918           0 :                     if ( pPrevious->IsCounted())
     919             :                     {
     920             :                         // get id of list body tag
     921           0 :                         const NumListBodyIdMap::const_iterator aIter =  rNumListBodyIdMap.find( pPrevious );
     922           0 :                         if ( aIter != rNumListBodyIdMap.end() )
     923             :                         {
     924           0 :                             nReopenTag = (*aIter).second;
     925           0 :                             break;
     926             :                         }
     927             :                     }
     928           0 :                     pPrevious = pPrevious->GetPred(true);
     929             :                 }
     930           0 :             }
     931             :         }
     932             :         // 2. We have to reopen an existing list tag:
     933           0 :         else if ( !pParent->IsFirst( pNodeNum ) && !pTxtNd->IsListRestart() )
     934             :         {
     935             :             // any other than the first node in a list level has to reopen the current
     936             :             // list. The current list is associated in a map with the first child of the list:
     937           0 :             NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
     938             : 
     939             :             // Search backwards and check if any of the previous nodes has a list associated with it:
     940           0 :             const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
     941           0 :             while ( pPrevious )
     942             :             {
     943             :                 // get id of list tag
     944           0 :                 const NumListIdMap::const_iterator aIter =  rNumListIdMap.find( pPrevious );
     945           0 :                 if ( aIter != rNumListIdMap.end() )
     946             :                 {
     947           0 :                     nReopenTag = (*aIter).second;
     948           0 :                     break;
     949             :                 }
     950             : 
     951           0 :                 pPrevious = pPrevious->GetPred(true);
     952             :             }
     953             :         }
     954             : 
     955           0 :         if ( -1 != nReopenTag )
     956             :         {
     957           0 :             nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
     958           0 :             mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
     959             : 
     960             : #if OSL_DEBUG_LEVEL > 1
     961             :             aStructStack.push_back( 99 );
     962             : #endif
     963             :         }
     964             :     }
     965             :     else
     966             :     {
     967             :         // clear list maps in case a list has been interrupted
     968           0 :         NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
     969           0 :         rNumListIdMap.clear();
     970           0 :         NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
     971           0 :         rNumListBodyIdMap.clear();
     972             :     }
     973             : 
     974             :     // New tags:
     975           0 :     const bool bNewListTag = (pNodeNum->GetParent()->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() || !bSameNumbering);
     976           0 :     const bool bNewItemTag = bNewListTag || pTxtNd->IsCountedInList(); // If the text node is not counted, we do not start a new list item:
     977             : 
     978           0 :     if ( bNewListTag )
     979           0 :         BeginTag( vcl::PDFWriter::List, OUString(aListString) );
     980             : 
     981           0 :     if ( bNewItemTag )
     982             :     {
     983           0 :         BeginTag( vcl::PDFWriter::ListItem, OUString(aListItemString) );
     984           0 :         BeginTag( vcl::PDFWriter::LIBody, OUString(aListBodyString) );
     985             :     }
     986             : }
     987             : 
     988             : /*
     989             :  * SwTaggedPDFHelper::BeginBlockStructureElements()
     990             :  */
     991           0 : void SwTaggedPDFHelper::BeginBlockStructureElements()
     992             : {
     993           0 :     const SwFrm* pFrm = &mpFrmInfo->mrFrm;
     994             : 
     995             :     // Lowers of NonStructureElements should not be considered:
     996             : 
     997           0 :     if ( lcl_IsInNonStructEnv( *pFrm ) )
     998           0 :         return;
     999             : 
    1000             :     // Check if we have to reopen an existing structure element.
    1001             :     // This has to be done e.g., if pFrm is a follow frame.
    1002           0 :     if ( CheckReopenTag() )
    1003           0 :         return;
    1004             : 
    1005           0 :     sal_uInt16 nPDFType = USHRT_MAX;
    1006           0 :     OUString aPDFType;
    1007             : 
    1008           0 :     switch ( pFrm->GetType() )
    1009             :     {
    1010             :         /*
    1011             :          * GROUPING ELEMENTS
    1012             :          */
    1013             : 
    1014             :         case FRM_PAGE :
    1015             : 
    1016             :             // Document: Document
    1017             : 
    1018           0 :             nPDFType = vcl::PDFWriter::Document;
    1019           0 :             aPDFType = OUString(aDocumentString);
    1020           0 :             break;
    1021             : 
    1022             :         case FRM_HEADER :
    1023             :         case FRM_FOOTER :
    1024             : 
    1025             :             // Header, Footer: NonStructElement
    1026             : 
    1027           0 :             nPDFType = vcl::PDFWriter::NonStructElement;
    1028           0 :             break;
    1029             : 
    1030             :         case FRM_FTNCONT :
    1031             : 
    1032             :             // Footnote container: Division
    1033             : 
    1034           0 :             nPDFType = vcl::PDFWriter::Division;
    1035           0 :             aPDFType = OUString(aDivString);
    1036           0 :             break;
    1037             : 
    1038             :         case FRM_FTN :
    1039             : 
    1040             :             // Footnote frame: Note
    1041             : 
    1042             :             // Note: vcl::PDFWriter::Note is actually a ILSE. Nevertheless
    1043             :             // we treat it like a grouping element!
    1044           0 :             nPDFType = vcl::PDFWriter::Note;
    1045           0 :             aPDFType = OUString(aNoteString);
    1046           0 :             break;
    1047             : 
    1048             :         case FRM_SECTION :
    1049             : 
    1050             :             // Section: TOX, Index, or Sect
    1051             : 
    1052             :             {
    1053             :                 const SwSection* pSection =
    1054           0 :                         static_cast<const SwSectionFrm*>(pFrm)->GetSection();
    1055           0 :                 if ( TOX_CONTENT_SECTION == pSection->GetType() )
    1056             :                 {
    1057           0 :                     const SwTOXBase* pTOXBase = pSection->GetTOXBase();
    1058           0 :                     if ( pTOXBase )
    1059             :                     {
    1060           0 :                         if ( TOX_INDEX == pTOXBase->GetType() )
    1061             :                         {
    1062           0 :                             nPDFType = vcl::PDFWriter::Index;
    1063           0 :                             aPDFType = OUString(aIndexString);
    1064             :                         }
    1065             :                         else
    1066             :                         {
    1067           0 :                             nPDFType = vcl::PDFWriter::TOC;
    1068           0 :                             aPDFType = OUString(aTOCString);
    1069             :                         }
    1070             :                     }
    1071             :                 }
    1072           0 :                 else if ( CONTENT_SECTION == pSection->GetType() )
    1073             :                 {
    1074           0 :                     nPDFType = vcl::PDFWriter::Section;
    1075           0 :                     aPDFType = OUString(aSectString);
    1076             :                 }
    1077             :             }
    1078           0 :             break;
    1079             : 
    1080             :         /*
    1081             :          * BLOCK-LEVEL STRUCTURE ELEMENTS
    1082             :          */
    1083             : 
    1084             :         case FRM_TXT :
    1085             :             {
    1086             :                 const SwTxtNode* pTxtNd =
    1087           0 :                     static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
    1088             : 
    1089           0 :                 const SwFmt* pTxtFmt = pTxtNd->GetFmtColl();
    1090           0 :                 const SwFmt* pParentTxtFmt = pTxtFmt ? pTxtFmt->DerivedFrom() : NULL;
    1091             : 
    1092           0 :                 OUString sStyleName;
    1093           0 :                 OUString sParentStyleName;
    1094             : 
    1095           0 :                 if ( pTxtFmt)
    1096           0 :                     SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
    1097           0 :                 if ( pParentTxtFmt)
    1098           0 :                     SwStyleNameMapper::FillProgName( pParentTxtFmt->GetName(), sParentStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
    1099             : 
    1100             :                 // This is the default. If the paragraph could not be mapped to
    1101             :                 // any of the standard pdf tags, we write a user defined tag
    1102             :                 // <stylename> with role = P
    1103           0 :                 nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Paragraph);
    1104           0 :                 aPDFType = sStyleName;
    1105             : 
    1106             :                 // Quotations: BlockQuote
    1107             : 
    1108           0 :                 if (sStyleName.equalsAscii(aQuotations))
    1109             :                 {
    1110           0 :                     nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::BlockQuote);
    1111           0 :                     aPDFType = OUString(aBlockQuoteString);
    1112             :                 }
    1113             : 
    1114             :                 // Caption: Caption
    1115             : 
    1116           0 :                 else if (sStyleName.equalsAscii(aCaption))
    1117             :                 {
    1118           0 :                     nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Caption);
    1119           0 :                     aPDFType = OUString(aCaptionString);
    1120             :                 }
    1121             : 
    1122             :                 // Caption: Caption
    1123             : 
    1124           0 :                 else if (sParentStyleName.equalsAscii(aCaption))
    1125             :                 {
    1126           0 :                     nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Caption);
    1127           0 :                     aPDFType = sStyleName + aCaptionString;
    1128             :                 }
    1129             : 
    1130             :                 // Heading: H
    1131             : 
    1132           0 :                 else if (sStyleName.equalsAscii(aHeading))
    1133             :                 {
    1134           0 :                     nPDFType = static_cast<sal_uInt16>(vcl::PDFWriter::Heading);
    1135           0 :                     aPDFType = OUString(aHString);
    1136             :                 }
    1137             : 
    1138             :                 // Heading: H1 - H6
    1139             : 
    1140           0 :                 if ( pTxtNd->IsOutline() )
    1141             :                 {
    1142           0 :                     int nRealLevel = pTxtNd->GetAttrOutlineLevel()-1;
    1143           0 :                    nRealLevel = nRealLevel > 5 ? 5 : nRealLevel;
    1144             : 
    1145           0 :                     nPDFType =  static_cast<sal_uInt16>(vcl::PDFWriter::H1 + nRealLevel);
    1146           0 :                     switch(nRealLevel)
    1147             :                     {
    1148             :                         case 0 :
    1149           0 :                             aPDFType = OUString(aH1String);
    1150           0 :                             break;
    1151             :                         case 1 :
    1152           0 :                             aPDFType = OUString(aH2String);
    1153           0 :                             break;
    1154             :                         case 2 :
    1155           0 :                             aPDFType = OUString(aH3String);
    1156           0 :                             break;
    1157             :                         case 3 :
    1158           0 :                             aPDFType = OUString(aH4String);
    1159           0 :                             break;
    1160             :                         case 4 :
    1161           0 :                             aPDFType = OUString(aH5String);
    1162           0 :                             break;
    1163             :                         default:
    1164           0 :                             aPDFType = OUString(aH6String);
    1165           0 :                             break;
    1166             :                     }
    1167             :                 }
    1168             : 
    1169             :                 // Section: TOCI
    1170             : 
    1171           0 :                 else if ( pFrm->IsInSct() )
    1172             :                 {
    1173           0 :                     const SwSectionFrm* pSctFrm = pFrm->FindSctFrm();
    1174             :                     const SwSection* pSection =
    1175           0 :                             static_cast<const SwSectionFrm*>(pSctFrm)->GetSection();
    1176             : 
    1177           0 :                     if ( TOX_CONTENT_SECTION == pSection->GetType() )
    1178             :                     {
    1179           0 :                         const SwTOXBase* pTOXBase = pSection->GetTOXBase();
    1180           0 :                         if ( pTOXBase && TOX_INDEX != pTOXBase->GetType() )
    1181             :                         {
    1182             :                             // Special case: Open additional TOCI tag:
    1183           0 :                             BeginTag( vcl::PDFWriter::TOCI, OUString(aTOCIString) );
    1184             :                         }
    1185             :                     }
    1186           0 :                 }
    1187             :             }
    1188           0 :             break;
    1189             : 
    1190             :         case FRM_TAB :
    1191             : 
    1192             :             // TabFrm: Table
    1193             : 
    1194           0 :             nPDFType = vcl::PDFWriter::Table;
    1195           0 :             aPDFType = OUString(aTableString);
    1196             : 
    1197             :             {
    1198             :                 // set up table column data:
    1199           0 :                 const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>(pFrm);
    1200           0 :                 const SwTable* pTable = pTabFrm->GetTable();
    1201             : 
    1202           0 :                 TableColumnsMap& rTableColumnsMap = SwEnhancedPDFExportHelper::GetTableColumnsMap();
    1203           0 :                 const TableColumnsMap::const_iterator aIter = rTableColumnsMap.find( pTable );
    1204             : 
    1205           0 :                 if ( aIter == rTableColumnsMap.end() )
    1206             :                 {
    1207           0 :                     SWRECTFN( pTabFrm )
    1208           0 :                     TableColumnsMapEntry& rCols = rTableColumnsMap[ pTable ];
    1209             : 
    1210           0 :                     const SwTabFrm* pMasterFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
    1211             : 
    1212           0 :                     while ( pMasterFrm )
    1213             :                     {
    1214           0 :                         const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pMasterFrm->GetLower());
    1215             : 
    1216           0 :                         while ( pRowFrm )
    1217             :                         {
    1218           0 :                             const SwFrm* pCellFrm = pRowFrm->GetLower();
    1219             : 
    1220           0 :                             const long nLeft  = (pCellFrm->Frm().*fnRect->fnGetLeft)();
    1221           0 :                             rCols.insert( nLeft );
    1222             : 
    1223           0 :                             while ( pCellFrm )
    1224             :                             {
    1225           0 :                                 const long nRight = (pCellFrm->Frm().*fnRect->fnGetRight)();
    1226           0 :                                 rCols.insert( nRight );
    1227           0 :                                 pCellFrm = pCellFrm->GetNext();
    1228             :                             }
    1229           0 :                             pRowFrm = static_cast<const SwRowFrm*>(pRowFrm->GetNext());
    1230             :                         }
    1231           0 :                         pMasterFrm = static_cast<const SwTabFrm*>(pMasterFrm->GetFollow());
    1232             :                     }
    1233             :                 }
    1234             :             }
    1235             : 
    1236           0 :             break;
    1237             : 
    1238             :         /*
    1239             :          * TABLE ELEMENTS
    1240             :          */
    1241             : 
    1242             :         case FRM_ROW :
    1243             : 
    1244             :             // RowFrm: TR
    1245             : 
    1246           0 :             if ( !static_cast<const SwRowFrm*>(pFrm)->IsRepeatedHeadline() )
    1247             :             {
    1248           0 :                 nPDFType = vcl::PDFWriter::TableRow;
    1249           0 :                 aPDFType = OUString(aTRString);
    1250             :             }
    1251             :             else
    1252             :             {
    1253           0 :                 nPDFType = vcl::PDFWriter::NonStructElement;
    1254             :             }
    1255           0 :             break;
    1256             : 
    1257             :         case FRM_CELL :
    1258             : 
    1259             :             // CellFrm: TH, TD
    1260             : 
    1261             :             {
    1262           0 :                 const SwTabFrm* pTable = static_cast<const SwCellFrm*>(pFrm)->FindTabFrm();
    1263           0 :                 if ( pTable->IsInHeadline( *pFrm ) || lcl_IsHeadlineCell( *static_cast<const SwCellFrm*>(pFrm) ) )
    1264             :                 {
    1265           0 :                     nPDFType = vcl::PDFWriter::TableHeader;
    1266           0 :                     aPDFType = OUString(aTHString);
    1267             :                 }
    1268             :                 else
    1269             :                 {
    1270           0 :                     nPDFType = vcl::PDFWriter::TableData;
    1271           0 :                     aPDFType = OUString(aTDString);
    1272             :                 }
    1273             :             }
    1274           0 :             break;
    1275             : 
    1276             :         /*
    1277             :          * ILLUSTRATION
    1278             :          */
    1279             : 
    1280             :         case FRM_FLY :
    1281             : 
    1282             :             // FlyFrm: Figure, Formula, Control
    1283             :             // fly in content or fly at page
    1284             :             {
    1285           0 :                 bool bFormula = false;
    1286           0 :                 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
    1287           0 :                 if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
    1288             :                 {
    1289           0 :                     const SwNoTxtFrm* pNoTxtFrm = static_cast<const SwNoTxtFrm*>(pFly->Lower());
    1290           0 :                     SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTxtFrm->GetNode()->GetOLENode());
    1291           0 :                     if ( pOLENd )
    1292             :                     {
    1293           0 :                         SwOLEObj& aOLEObj = pOLENd->GetOLEObj();
    1294           0 :                         uno::Reference< embed::XEmbeddedObject > aRef = aOLEObj.GetOleRef();
    1295           0 :                         if ( aRef.is() )
    1296             :                         {
    1297           0 :                             bFormula = 0 != SotExchange::IsMath( SvGlobalName( aRef->getClassID() ) );
    1298           0 :                         }
    1299             :                     }
    1300           0 :                     if ( bFormula )
    1301             :                     {
    1302           0 :                         nPDFType = vcl::PDFWriter::Formula;
    1303           0 :                         aPDFType = OUString(aFormulaString);
    1304             :                     }
    1305             :                     else
    1306             :                     {
    1307           0 :                         nPDFType = vcl::PDFWriter::Figure;
    1308           0 :                         aPDFType = OUString(aFigureString);
    1309             :                     }
    1310             :                 }
    1311             :                 else
    1312             :                 {
    1313           0 :                     nPDFType = vcl::PDFWriter::Division;
    1314           0 :                     aPDFType = OUString(aDivString);
    1315             :                 }
    1316             :             }
    1317           0 :             break;
    1318             :     }
    1319             : 
    1320           0 :     if ( USHRT_MAX != nPDFType )
    1321             :     {
    1322           0 :         BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
    1323           0 :     }
    1324             : }
    1325             : 
    1326             : /*
    1327             :  * SwTaggedPDFHelper::EndStructureElements()
    1328             :  */
    1329           0 : void SwTaggedPDFHelper::EndStructureElements()
    1330             : {
    1331           0 :     while ( nEndStructureElement > 0 )
    1332             :     {
    1333           0 :         EndTag();
    1334           0 :         --nEndStructureElement;
    1335             :     }
    1336             : 
    1337           0 :     CheckRestoreTag();
    1338           0 : }
    1339             : 
    1340             : /*
    1341             :  * SwTaggedPDFHelper::BeginInlineStructureElements()
    1342             :  */
    1343           0 : void SwTaggedPDFHelper::BeginInlineStructureElements()
    1344             : {
    1345           0 :     const SwLinePortion* pPor = &mpPorInfo->mrPor;
    1346           0 :     const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
    1347           0 :     const SwTxtFrm* pFrm = rInf.GetTxtFrm();
    1348             : 
    1349             :     // Lowers of NonStructureElements should not be considered:
    1350             : 
    1351           0 :     if ( lcl_IsInNonStructEnv( *pFrm ) )
    1352           0 :         return;
    1353             : 
    1354           0 :     sal_uInt16 nPDFType = USHRT_MAX;
    1355           0 :     OUString aPDFType;
    1356             : 
    1357           0 :     switch ( pPor->GetWhichPor() )
    1358             :     {
    1359             :         case POR_HYPH :
    1360             :         case POR_SOFTHYPH :
    1361             :         // Check for alternative spelling:
    1362             :         case POR_HYPHSTR :
    1363             :         case POR_SOFTHYPHSTR :
    1364           0 :             nPDFType = vcl::PDFWriter::Span;
    1365           0 :             aPDFType = OUString(aSpanString);
    1366           0 :             break;
    1367             : 
    1368             :         case POR_LAY :
    1369             :         case POR_TXT :
    1370             :         case POR_PARA :
    1371             :             {
    1372           0 :                 SwTxtNode* pNd = (SwTxtNode*)pFrm->GetTxtNode();
    1373             :                 SwTxtAttr const*const pInetFmtAttr =
    1374           0 :                     pNd->GetTxtAttrAt(rInf.GetIdx(), RES_TXTATR_INETFMT);
    1375             : 
    1376           0 :                 OUString sStyleName;
    1377           0 :                 if ( !pInetFmtAttr )
    1378             :                 {
    1379             :                     ::std::vector<SwTxtAttr *> const charAttrs(
    1380           0 :                         pNd->GetTxtAttrsAt(rInf.GetIdx(), RES_TXTATR_CHARFMT));
    1381             :                     // TODO: handle more than 1 char style?
    1382           0 :                     const SwCharFmt* pCharFmt = (charAttrs.size())
    1383           0 :                         ? (*charAttrs.begin())->GetCharFmt().GetCharFmt() : 0;
    1384           0 :                     if ( pCharFmt )
    1385           0 :                         SwStyleNameMapper::FillProgName( pCharFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
    1386             :                 }
    1387             : 
    1388             :                 // Check for Link:
    1389           0 :                 if( pInetFmtAttr )
    1390             :                 {
    1391           0 :                     nPDFType = vcl::PDFWriter::Link;
    1392           0 :                     aPDFType = OUString(aLinkString);
    1393             :                 }
    1394             :                 // Check for Quote/Code character style:
    1395           0 :                 else if (sStyleName.equalsAscii(aQuotation))
    1396             :                 {
    1397           0 :                     nPDFType = vcl::PDFWriter::Quote;
    1398           0 :                     aPDFType = OUString(aQuoteString);
    1399             :                 }
    1400           0 :                 else if (sStyleName.equalsAscii(aSourceText))
    1401             :                 {
    1402           0 :                     nPDFType = vcl::PDFWriter::Code;
    1403           0 :                     aPDFType = OUString(aCodeString);
    1404             :                 }
    1405             :                 else
    1406             :                 {
    1407           0 :                     const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
    1408           0 :                     const sal_uInt16 nFont = rInf.GetFont()->GetActual();
    1409           0 :                     const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
    1410             : 
    1411           0 :                     if ( UNDERLINE_NONE    != rInf.GetFont()->GetUnderline() ||
    1412           0 :                          UNDERLINE_NONE    != rInf.GetFont()->GetOverline()  ||
    1413           0 :                          STRIKEOUT_NONE    != rInf.GetFont()->GetStrikeout() ||
    1414           0 :                          EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() ||
    1415           0 :                          0                 != rInf.GetFont()->GetEscapement() ||
    1416           0 :                          SW_LATIN          != nFont ||
    1417           0 :                          nCurrentLanguage  != nDefaultLang ||
    1418           0 :                          !sStyleName.isEmpty())
    1419             :                     {
    1420           0 :                         nPDFType = vcl::PDFWriter::Span;
    1421           0 :                         if (!sStyleName.isEmpty())
    1422           0 :                             aPDFType = sStyleName;
    1423             :                         else
    1424           0 :                             aPDFType = OUString(aSpanString);
    1425             :                     }
    1426           0 :                 }
    1427             :             }
    1428           0 :             break;
    1429             : 
    1430             :         case POR_FTN :
    1431           0 :             nPDFType = vcl::PDFWriter::Link;
    1432           0 :             aPDFType = OUString(aLinkString);
    1433           0 :             break;
    1434             : 
    1435             :         case POR_FLD :
    1436             :             {
    1437             :                 // check field type:
    1438           0 :                 const sal_Int32 nIdx = static_cast<const SwFldPortion*>(pPor)->IsFollow() ?
    1439           0 :                                         rInf.GetIdx() - 1 :
    1440           0 :                                         rInf.GetIdx();
    1441           0 :                 const SwTxtAttr* pHint = mpPorInfo->mrTxtPainter.GetAttr( nIdx );
    1442           0 :                 const SwField* pFld = 0;
    1443           0 :                 if ( pHint && RES_TXTATR_FIELD == pHint->Which() )
    1444             :                 {
    1445           0 :                     pFld = (SwField*)pHint->GetFmtFld().GetField();
    1446           0 :                     if ( RES_GETREFFLD == pFld->Which() )
    1447             :                     {
    1448           0 :                         nPDFType = vcl::PDFWriter::Link;
    1449           0 :                         aPDFType = OUString(aLinkString);
    1450             :                     }
    1451           0 :                     else if ( RES_AUTHORITY == pFld->Which() )
    1452             :                     {
    1453           0 :                         nPDFType = vcl::PDFWriter::BibEntry;
    1454           0 :                         aPDFType = OUString(aBibEntryString);
    1455             :                     }
    1456             :                 }
    1457             :             }
    1458           0 :             break;
    1459             : 
    1460             :         case POR_TAB :
    1461             :         case POR_TABRIGHT :
    1462             :         case POR_TABCENTER :
    1463             :         case POR_TABDECIMAL :
    1464           0 :             nPDFType = vcl::PDFWriter::NonStructElement;
    1465           0 :             break;
    1466             :     }
    1467             : 
    1468           0 :     if ( USHRT_MAX != nPDFType )
    1469             :     {
    1470           0 :         BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
    1471           0 :     }
    1472             : }
    1473             : 
    1474             : /*
    1475             :  * static SwTaggedPDFHelper::IsExportTaggedPDF
    1476             :  */
    1477           0 :  bool SwTaggedPDFHelper::IsExportTaggedPDF( const OutputDevice& rOut )
    1478             :  {
    1479           0 :     vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
    1480           0 :     return pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF();
    1481             :  }
    1482             : 
    1483             : /*
    1484             :  * SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper()
    1485             :  */
    1486           0 : SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper( SwEditShell& rSh,
    1487             :                                                       OutputDevice& rOut,
    1488             :                                                       const OUString& rPageRange,
    1489             :                                                       bool bSkipEmptyPages,
    1490             :                                                       bool bEditEngineOnly )
    1491             :     : mrSh( rSh ),
    1492             :       mrOut( rOut ),
    1493             :       mpRangeEnum( 0 ),
    1494             :       mbSkipEmptyPages( bSkipEmptyPages ),
    1495           0 :       mbEditEngineOnly( bEditEngineOnly )
    1496             : {
    1497           0 :     if ( !rPageRange.isEmpty() )
    1498           0 :         mpRangeEnum = new StringRangeEnumerator( rPageRange, 0, mrSh.GetPageCount()-1 );
    1499             : 
    1500           0 :     if ( mbSkipEmptyPages )
    1501             :     {
    1502           0 :         maPageNumberMap.resize( mrSh.GetPageCount() );
    1503             :         const SwPageFrm* pCurrPage =
    1504           0 :             static_cast<const SwPageFrm*>( mrSh.GetLayout()->Lower() );
    1505           0 :         sal_Int32 nPageNumber = 0;
    1506           0 :         for ( size_t i = 0, n = maPageNumberMap.size(); i < n && pCurrPage; ++i )
    1507             :         {
    1508           0 :             if ( pCurrPage->IsEmptyPage() )
    1509           0 :                 maPageNumberMap[i] = -1;
    1510             :             else
    1511           0 :                 maPageNumberMap[i] = nPageNumber++;
    1512             : 
    1513           0 :             pCurrPage = static_cast<const SwPageFrm*>( pCurrPage->GetNext() );
    1514             :         }
    1515             :     }
    1516             : 
    1517           0 :     aTableColumnsMap.clear();
    1518           0 :     aLinkIdMap.clear();
    1519           0 :     aNumListIdMap.clear();
    1520           0 :     aNumListBodyIdMap.clear();
    1521           0 :     aFrmTagIdMap.clear();
    1522             : 
    1523             : #if OSL_DEBUG_LEVEL > 1
    1524             :     aStructStack.clear();
    1525             : #endif
    1526             : 
    1527           0 :     const sal_uInt8 nScript = (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
    1528           0 :     sal_uInt16 nLangRes = RES_CHRATR_LANGUAGE;
    1529             : 
    1530           0 :     if ( i18n::ScriptType::ASIAN == nScript )
    1531           0 :         nLangRes = RES_CHRATR_CJK_LANGUAGE;
    1532           0 :     else if ( i18n::ScriptType::COMPLEX == nScript )
    1533           0 :         nLangRes = RES_CHRATR_CTL_LANGUAGE;
    1534             : 
    1535           0 :     eLanguageDefault = static_cast<const SvxLanguageItem*>(&mrSh.GetDoc()->GetDefault( nLangRes ))->GetLanguage();
    1536             : 
    1537           0 :     EnhancedPDFExport();
    1538           0 : }
    1539             : 
    1540           0 : SwEnhancedPDFExportHelper::~SwEnhancedPDFExportHelper()
    1541             : {
    1542           0 :     delete mpRangeEnum;
    1543           0 : }
    1544             : 
    1545             : /*
    1546             :  * SwEnhancedPDFExportHelper::EnhancedPDFExport()
    1547             :  */
    1548           0 : void SwEnhancedPDFExportHelper::EnhancedPDFExport()
    1549             : {
    1550             :     vcl::PDFExtOutDevData* pPDFExtOutDevData =
    1551           0 :         PTR_CAST( vcl::PDFExtOutDevData, mrOut.GetExtOutDevData() );
    1552             : 
    1553           0 :     if ( !pPDFExtOutDevData )
    1554           0 :         return;
    1555             : 
    1556             :     // set the document locale
    1557             : 
    1558           0 :     com::sun::star::lang::Locale aDocLocale( LanguageTag( SwEnhancedPDFExportHelper::GetDefaultLanguage() ).getLocale() );
    1559           0 :     pPDFExtOutDevData->SetDocumentLocale( aDocLocale );
    1560             : 
    1561             :     // Prepare the output device:
    1562             : 
    1563           0 :     mrOut.Push( PUSH_MAPMODE );
    1564           0 :     MapMode aMapMode( mrOut.GetMapMode() );
    1565           0 :     aMapMode.SetMapUnit( MAP_TWIP );
    1566           0 :     mrOut.SetMapMode( aMapMode );
    1567             : 
    1568             :     // Create new cursor and lock the view:
    1569             : 
    1570           0 :     SwDoc* pDoc = mrSh.GetDoc();
    1571           0 :     mrSh.SwCrsrShell::Push();
    1572           0 :     mrSh.SwCrsrShell::ClearMark();
    1573           0 :     const bool bOldLockView = mrSh.IsViewLocked();
    1574           0 :     mrSh.LockView( true );
    1575             : 
    1576           0 :     if ( !mbEditEngineOnly )
    1577             :     {
    1578             : 
    1579             :         // POSTITS
    1580             : 
    1581           0 :         if ( pPDFExtOutDevData->GetIsExportNotes() )
    1582             :         {
    1583           0 :             SwFieldType* pType = mrSh.GetFldType( RES_POSTITFLD, OUString() );
    1584           0 :             SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
    1585           0 :             for( SwFmtFld* pFirst = aIter.First(); pFirst; )
    1586             :             {
    1587           0 :                 if( pFirst->GetTxtFld() && pFirst->IsFldInDoc() )
    1588             :                 {
    1589           0 :                     const SwTxtNode* pTNd = (SwTxtNode*)pFirst->GetTxtFld()->GetpTxtNode();
    1590             :                     OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
    1591             : 
    1592             :                     // 1. Check if the whole paragraph is hidden
    1593             :                     // 2. Move to the field
    1594             :                     // 3. Check for hidden text attribute
    1595           0 :                     if ( !pTNd->IsHidden() &&
    1596           0 :                           mrSh.GotoFld( *pFirst ) &&
    1597           0 :                          !mrSh.SelectHiddenRange() )
    1598             :                     {
    1599             :                         // Link Rectangle
    1600           0 :                         const SwRect& rNoteRect = mrSh.GetCharRect();
    1601             : 
    1602             :                         // Link PageNums
    1603           0 :                         std::vector<sal_Int32> aNotePageNums = CalcOutputPageNums( rNoteRect );
    1604           0 :                         for ( size_t nNumIdx = 0; nNumIdx < aNotePageNums.size(); ++nNumIdx )
    1605             :                         {
    1606             :                             // Link Note
    1607           0 :                             vcl::PDFNote aNote;
    1608             : 
    1609             :                             // Use the NumberFormatter to get the date string:
    1610           0 :                             const SwPostItField* pField = (SwPostItField*)pFirst->GetField();
    1611           0 :                             SvNumberFormatter* pNumFormatter = pDoc->GetNumberFormatter();
    1612           0 :                             const Date aDateDiff( pField->GetDate() -
    1613           0 :                                                  *pNumFormatter->GetNullDate() );
    1614             :                             const sal_uLong nFormat =
    1615           0 :                                 pNumFormatter->GetStandardFormat( NUMBERFORMAT_DATE, pField->GetLanguage() );
    1616           0 :                             OUString sDate;
    1617             :                             Color* pColor;
    1618           0 :                             pNumFormatter->GetOutputString( aDateDiff.GetDate(), nFormat, sDate, &pColor );
    1619             : 
    1620             :                             // The title should consist of the author and the date:
    1621           0 :                             aNote.Title = pField->GetPar1() + ", " + sDate;
    1622             :                             // Guess what the contents contains...
    1623           0 :                             aNote.Contents = pField->GetTxt();
    1624             : 
    1625             :                             // Link Export
    1626           0 :                             pPDFExtOutDevData->CreateNote( rNoteRect.SVRect(), aNote, aNotePageNums[nNumIdx] );
    1627           0 :                         }
    1628             :                     }
    1629             :                 }
    1630           0 :                 pFirst = aIter.Next();
    1631           0 :                 mrSh.SwCrsrShell::ClearMark();
    1632           0 :             }
    1633             :         }
    1634             : 
    1635             :         // HYPERLINKS
    1636             : 
    1637           0 :         SwGetINetAttrs aArr;
    1638           0 :         const sal_uInt16 nHyperLinkCount = mrSh.GetINetAttrs( aArr );
    1639           0 :         for( sal_uInt16 n = 0; n < nHyperLinkCount; ++n )
    1640             :         {
    1641           0 :             SwGetINetAttr* p = &aArr[ n ];
    1642             :             OSL_ENSURE( 0 != p, "Enhanced pdf export - SwGetINetAttr is missing" );
    1643             : 
    1644           0 :             const SwTxtNode* pTNd = p->rINetAttr.GetpTxtNode();
    1645             :             OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
    1646             : 
    1647             :             // 1. Check if the whole paragraph is hidden
    1648             :             // 2. Move to the hyperlink
    1649             :             // 3. Check for hidden text attribute
    1650           0 :             if ( !pTNd->IsHidden() &&
    1651           0 :                   mrSh.GotoINetAttr( p->rINetAttr ) &&
    1652           0 :                  !mrSh.SelectHiddenRange() )
    1653             :             {
    1654             :                 // Select the hyperlink:
    1655           0 :                 mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
    1656           0 :                 if ( mrSh.SwCrsrShell::SelectTxtAttr( RES_TXTATR_INETFMT, true ) )
    1657             :                 {
    1658             :                     // First, we create the destination, because there may be more
    1659             :                     // than one link to this destination:
    1660             :                     OUString aURL( INetURLObject::decode(
    1661           0 :                         p->rINetAttr.GetINetFmt().GetValue(),
    1662             :                         '%',
    1663             :                         INetURLObject::DECODE_UNAMBIGUOUS,
    1664           0 :                         RTL_TEXTENCODING_UTF8 ) );
    1665             : 
    1666             :                     // We have to distinguish between intern and real URLs
    1667           0 :                     const bool bIntern = '#' == aURL[0];
    1668             : 
    1669             :                     // _GetCrsr() is a SwShellCrsr, which is derived from
    1670             :                     // SwSelPaintRects, therefore the rectangles of the current
    1671             :                     // selection can be easily obtained:
    1672             :                     // Note: We make a copy of the rectangles, because they may
    1673             :                     // be deleted again in JumpToSwMark.
    1674           0 :                     SwRects aTmp;
    1675           0 :                     aTmp.insert( aTmp.begin(), mrSh.SwCrsrShell::_GetCrsr()->begin(), mrSh.SwCrsrShell::_GetCrsr()->end() );
    1676             :                     OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" );
    1677             : 
    1678             :                     // Create the destination for internal links:
    1679           0 :                     sal_Int32 nDestId = -1;
    1680           0 :                     if ( bIntern )
    1681             :                     {
    1682           0 :                         aURL = aURL.copy( 1 );
    1683           0 :                         mrSh.SwCrsrShell::ClearMark();
    1684           0 :                         JumpToSwMark( &mrSh, aURL );
    1685             : 
    1686             :                         // Destination Rectangle
    1687           0 :                         const SwRect& rDestRect = mrSh.GetCharRect();
    1688             : 
    1689             :                         // Destination PageNum
    1690           0 :                         const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    1691             : 
    1692             :                         // Destination Export
    1693           0 :                         if ( -1 != nDestPageNum )
    1694           0 :                             nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    1695             :                     }
    1696             : 
    1697           0 :                     if ( !bIntern || -1 != nDestId )
    1698             :                     {
    1699             :                         // #i44368# Links in Header/Footer
    1700           0 :                         const SwPosition aPos( *pTNd );
    1701           0 :                         const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
    1702             : 
    1703             :                         // Create links for all selected rectangles:
    1704           0 :                         const sal_uInt16 nNumOfRects = aTmp.size();
    1705           0 :                         for ( sal_uInt16 i = 0; i < nNumOfRects; ++i )
    1706             :                         {
    1707             :                             // Link Rectangle
    1708           0 :                             const SwRect& rLinkRect( aTmp[ i ] );
    1709             : 
    1710             :                             // Link PageNums
    1711           0 :                             std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( rLinkRect );
    1712             : 
    1713           0 :                             for ( size_t nNumIdx = 0; nNumIdx < aLinkPageNums.size(); ++nNumIdx )
    1714             :                             {
    1715             :                                 // Link Export
    1716             :                                 const sal_Int32 nLinkId =
    1717           0 :                                     pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), aLinkPageNums[nNumIdx] );
    1718             : 
    1719             :                                 // Store link info for tagged pdf output:
    1720           0 :                                 const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
    1721           0 :                                 aLinkIdMap.push_back( aLinkEntry );
    1722             : 
    1723             :                                 // Connect Link and Destination:
    1724           0 :                                 if ( bIntern )
    1725           0 :                                     pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
    1726             :                                 else
    1727           0 :                                     pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
    1728             : 
    1729             :                                 // #i44368# Links in Header/Footer
    1730           0 :                                 if ( bHeaderFooter )
    1731           0 :                                     MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aURL, bIntern );
    1732             :                             }
    1733           0 :                         }
    1734           0 :                     }
    1735             :                 }
    1736             :             }
    1737           0 :             mrSh.SwCrsrShell::ClearMark();
    1738             :         }
    1739             : 
    1740             :         // HYPERLINKS (Graphics, Frames, OLEs )
    1741             : 
    1742           0 :         const SwFrmFmts* pTbl = pDoc->GetSpzFrmFmts();
    1743           0 :         const sal_uInt16 nSpzFrmFmtsCount = pTbl->size();
    1744           0 :         for( sal_uInt16 n = 0; n < nSpzFrmFmtsCount; ++n )
    1745             :         {
    1746           0 :             const SwFrmFmt* pFrmFmt = (*pTbl)[n];
    1747             :             const SfxPoolItem* pItem;
    1748           0 :             if ( RES_DRAWFRMFMT != pFrmFmt->Which() &&
    1749           0 :                  SFX_ITEM_SET == pFrmFmt->GetAttrSet().GetItemState( RES_URL, true, &pItem ) )
    1750             :             {
    1751           0 :                 OUString aURL( static_cast<const SwFmtURL*>(pItem)->GetURL() );
    1752           0 :                 const bool bIntern = '#' == aURL[0];
    1753             : 
    1754             :                 // Create the destination for internal links:
    1755           0 :                 sal_Int32 nDestId = -1;
    1756           0 :                 if ( bIntern )
    1757             :                 {
    1758           0 :                     aURL = aURL.copy( 1 );
    1759           0 :                     mrSh.SwCrsrShell::ClearMark();
    1760           0 :                     JumpToSwMark( &mrSh, aURL );
    1761             : 
    1762             :                     // Destination Rectangle
    1763           0 :                     const SwRect& rDestRect = mrSh.GetCharRect();
    1764             : 
    1765             :                     // Destination PageNum
    1766           0 :                     const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    1767             : 
    1768             :                     // Destination Export
    1769           0 :                     if ( -1 != nDestPageNum )
    1770           0 :                         nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    1771             :                 }
    1772             : 
    1773           0 :                 if ( !bIntern || -1 != nDestId )
    1774             :                 {
    1775           0 :                     Point aNullPt;
    1776           0 :                     const SwRect aLinkRect = pFrmFmt->FindLayoutRect( false, &aNullPt );
    1777             : 
    1778             :                     // Link PageNums
    1779           0 :                     std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( aLinkRect );
    1780             : 
    1781             :                     // Link Export
    1782           0 :                     for ( size_t nNumIdx = 0; nNumIdx < aLinkPageNums.size(); ++nNumIdx )
    1783             :                     {
    1784             :                         const sal_Int32 nLinkId =
    1785           0 :                             pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), aLinkPageNums[nNumIdx] );
    1786             : 
    1787             :                         // Connect Link and Destination:
    1788           0 :                         if ( bIntern )
    1789           0 :                             pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
    1790             :                         else
    1791           0 :                             pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
    1792             : 
    1793             :                         // #i44368# Links in Header/Footer
    1794           0 :                         const SwFmtAnchor &rAnch = pFrmFmt->GetAnchor();
    1795           0 :                         if (FLY_AT_PAGE != rAnch.GetAnchorId())
    1796             :                         {
    1797           0 :                             const SwPosition* pPosition = rAnch.GetCntntAnchor();
    1798           0 :                             if ( pPosition && pDoc->IsInHeaderFooter( pPosition->nNode ) )
    1799             :                             {
    1800           0 :                                 const SwTxtNode* pTNd = pPosition->nNode.GetNode().GetTxtNode();
    1801           0 :                                 if ( pTNd )
    1802           0 :                                     MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern );
    1803             :                             }
    1804             :                         }
    1805           0 :                     }
    1806           0 :                 }
    1807             :             }
    1808           0 :             mrSh.SwCrsrShell::ClearMark();
    1809             :         }
    1810             : 
    1811             :         // REFERENCES
    1812             : 
    1813           0 :         SwFieldType* pType = mrSh.GetFldType( RES_GETREFFLD, OUString() );
    1814           0 :         SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
    1815           0 :         for( SwFmtFld* pFirst = aIter.First(); pFirst; )
    1816             :         {
    1817           0 :             if( pFirst->GetTxtFld() && pFirst->IsFldInDoc() )
    1818             :             {
    1819           0 :                 const SwTxtNode* pTNd = (SwTxtNode*)pFirst->GetTxtFld()->GetpTxtNode();
    1820             :                OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
    1821             : 
    1822             :                 // 1. Check if the whole paragraph is hidden
    1823             :                 // 2. Move to the field
    1824             :                 // 3. Check for hidden text attribute
    1825           0 :                 if ( !pTNd->IsHidden() &&
    1826           0 :                       mrSh.GotoFld( *pFirst ) &&
    1827           0 :                      !mrSh.SelectHiddenRange() )
    1828             :                 {
    1829             :                     // Select the field:
    1830           0 :                     mrSh.SwCrsrShell::SetMark();
    1831           0 :                     mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
    1832             : 
    1833             :                     // Link Rectangles
    1834           0 :                     SwRects aTmp;
    1835           0 :                     aTmp.insert( aTmp.begin(), mrSh.SwCrsrShell::_GetCrsr()->begin(), mrSh.SwCrsrShell::_GetCrsr()->end() );
    1836             :                     OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" );
    1837             : 
    1838           0 :                     mrSh.SwCrsrShell::ClearMark();
    1839             : 
    1840             :                     // Destination Rectangle
    1841             :                     const SwGetRefField* pField =
    1842           0 :                         (SwGetRefField*)pFirst->GetField();
    1843           0 :                     const OUString& rRefName = pField->GetSetRefName();
    1844           0 :                     mrSh.GotoRefMark( rRefName, pField->GetSubType(), pField->GetSeqNo() );
    1845           0 :                     const SwRect& rDestRect = mrSh.GetCharRect();
    1846             : 
    1847             :                     // Destination PageNum
    1848           0 :                     const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    1849             : 
    1850           0 :                     if ( -1 != nDestPageNum )
    1851             :                     {
    1852             :                         // Destination Export
    1853           0 :                         const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    1854             : 
    1855             :                         // #i44368# Links in Header/Footer
    1856           0 :                         const SwPosition aPos( *pTNd );
    1857           0 :                         const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
    1858             : 
    1859             :                         // Create links for all selected rectangles:
    1860           0 :                         const sal_uInt16 nNumOfRects = aTmp.size();
    1861           0 :                         for ( sal_uInt16 i = 0; i < nNumOfRects; ++i )
    1862             :                         {
    1863             :                             // Link rectangle
    1864           0 :                             const SwRect& rLinkRect( aTmp[ i ] );
    1865             : 
    1866             :                             // Link PageNums
    1867           0 :                             std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( rLinkRect );
    1868             : 
    1869           0 :                             for ( size_t nNumIdx = 0; nNumIdx < aLinkPageNums.size(); ++nNumIdx )
    1870             :                             {
    1871             :                                 // Link Export
    1872             :                                 const sal_Int32 nLinkId =
    1873           0 :                                     pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), aLinkPageNums[nNumIdx] );
    1874             : 
    1875             :                                 // Store link info for tagged pdf output:
    1876           0 :                                 const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
    1877           0 :                                 aLinkIdMap.push_back( aLinkEntry );
    1878             : 
    1879             :                                 // Connect Link and Destination:
    1880           0 :                                 pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
    1881             : 
    1882             :                                 // #i44368# Links in Header/Footer
    1883           0 :                                 if ( bHeaderFooter )
    1884             :                                 {
    1885           0 :                                     const OUString aDummy;
    1886           0 :                                     MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aDummy, true );
    1887             :                                 }
    1888             :                             }
    1889           0 :                         }
    1890           0 :                     }
    1891             :                 }
    1892             :             }
    1893           0 :             pFirst = aIter.Next();
    1894           0 :             mrSh.SwCrsrShell::ClearMark();
    1895             :         }
    1896             : 
    1897             :         // FOOTNOTES
    1898             : 
    1899           0 :         const sal_uInt16 nFtnCount = pDoc->GetFtnIdxs().size();
    1900           0 :         for ( sal_uInt16 nIdx = 0; nIdx < nFtnCount; ++nIdx )
    1901             :         {
    1902             :             // Set cursor to text node that contains the footnote:
    1903           0 :             const SwTxtFtn* pTxtFtn = pDoc->GetFtnIdxs()[ nIdx ];
    1904           0 :             SwTxtNode& rTNd = const_cast<SwTxtNode&>(pTxtFtn->GetTxtNode());
    1905             : 
    1906           0 :             mrSh._GetCrsr()->GetPoint()->nNode = rTNd;
    1907           0 :             mrSh._GetCrsr()->GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
    1908             : 
    1909             :             // 1. Check if the whole paragraph is hidden
    1910             :             // 2. Check for hidden text attribute
    1911           0 :             if ( static_cast<const SwTxtNode&>(rTNd).IsHidden() ||
    1912           0 :                  mrSh.SelectHiddenRange() )
    1913           0 :                 continue;
    1914             : 
    1915           0 :             SwCrsrSaveState aSaveState( *mrSh._GetCrsr() );
    1916             : 
    1917             :             // Select the footnote:
    1918           0 :             mrSh.SwCrsrShell::SetMark();
    1919           0 :             mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
    1920             : 
    1921             :             // Link Rectangle
    1922           0 :             SwRects aTmp;
    1923           0 :             aTmp.insert( aTmp.begin(), mrSh.SwCrsrShell::_GetCrsr()->begin(), mrSh.SwCrsrShell::_GetCrsr()->end() );
    1924             :             OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles are missing" );
    1925           0 :             const SwRect aLinkRect( aTmp[ 0 ] );
    1926             : 
    1927           0 :             mrSh._GetCrsr()->RestoreSavePos();
    1928           0 :             mrSh.SwCrsrShell::ClearMark();
    1929             : 
    1930             :             // Goto footnote text:
    1931           0 :             if ( mrSh.GotoFtnTxt() )
    1932             :             {
    1933             :                 // Link PageNums
    1934           0 :                 std::vector<sal_Int32> aLinkPageNums = CalcOutputPageNums( aLinkRect );
    1935             : 
    1936             :                 // Destination Rectangle
    1937           0 :                 const SwRect& rDestRect = mrSh.GetCharRect();
    1938             : 
    1939             :                 // Destination PageNum
    1940           0 :                 const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    1941             : 
    1942           0 :                 for ( size_t nNumIdx = 0; nNumIdx < aLinkPageNums.size(); ++nNumIdx )
    1943             :                 {
    1944             :                     // Link Export
    1945             :                     const sal_Int32 nLinkId =
    1946           0 :                         pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), aLinkPageNums[nNumIdx] );
    1947             : 
    1948             :                     // Store link info for tagged pdf output:
    1949           0 :                     const IdMapEntry aLinkEntry( aLinkRect, nLinkId );
    1950           0 :                     aLinkIdMap.push_back( aLinkEntry );
    1951             : 
    1952           0 :                     if ( -1 != nDestPageNum )
    1953             :                     {
    1954             :                         // Destination Export
    1955           0 :                         const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    1956             : 
    1957             :                         // Connect Link and Destination:
    1958           0 :                         pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
    1959             :                     }
    1960           0 :                 }
    1961             :             }
    1962           0 :         }
    1963             : 
    1964             :         // OUTLINE
    1965             : 
    1966           0 :         if( pPDFExtOutDevData->GetIsExportBookmarks() )
    1967             :         {
    1968             :             typedef std::pair< sal_Int8, sal_Int32 > StackEntry;
    1969           0 :             std::stack< StackEntry > aOutlineStack;
    1970           0 :             aOutlineStack.push( StackEntry( -1, -1 ) ); // push default value
    1971             : 
    1972             :             const sal_uInt16 nOutlineCount =
    1973           0 :                 static_cast<sal_uInt16>(mrSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount());
    1974           0 :             for ( sal_uInt16 i = 0; i < nOutlineCount; ++i )
    1975             :             {
    1976             :                 // Check if outline is hidden
    1977           0 :                 const SwTxtNode* pTNd = mrSh.GetNodes().GetOutLineNds()[ i ]->GetTxtNode();
    1978             :                 OSL_ENSURE( 0 != pTNd, "Enhanced pdf export - text node is missing" );
    1979             : 
    1980           0 :                 if ( pTNd->IsHidden() ||
    1981             :                      // #i40292# Skip empty outlines:
    1982           0 :                      pTNd->GetTxt().isEmpty())
    1983           0 :                     continue;
    1984             : 
    1985             :                 // Get parent id from stack:
    1986           0 :                 const sal_Int8 nLevel = (sal_Int8)mrSh.getIDocumentOutlineNodesAccess()->getOutlineLevel( i );
    1987           0 :                 sal_Int8 nLevelOnTopOfStack = aOutlineStack.top().first;
    1988           0 :                 while ( nLevelOnTopOfStack >= nLevel &&
    1989             :                         nLevelOnTopOfStack != -1 )
    1990             :                 {
    1991           0 :                     aOutlineStack.pop();
    1992           0 :                     nLevelOnTopOfStack = aOutlineStack.top().first;
    1993             :                 }
    1994           0 :                 const sal_Int32 nParent = aOutlineStack.top().second;
    1995             : 
    1996             :                 // Destination rectangle
    1997           0 :                 mrSh.GotoOutline(i);
    1998           0 :                 const SwRect& rDestRect = mrSh.GetCharRect();
    1999             : 
    2000             :                 // Destination PageNum
    2001           0 :                 const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    2002             : 
    2003           0 :                 if ( -1 != nDestPageNum )
    2004             :                 {
    2005             :                     // Destination Export
    2006             :                     const sal_Int32 nDestId =
    2007           0 :                         pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    2008             : 
    2009             :                     // Outline entry text
    2010           0 :                     const OUString& rEntry = mrSh.getIDocumentOutlineNodesAccess()->getOutlineText( i, true, false, false );
    2011             : 
    2012             :                     // Create a new outline item:
    2013             :                     const sal_Int32 nOutlineId =
    2014           0 :                         pPDFExtOutDevData->CreateOutlineItem( nParent, rEntry, nDestId );
    2015             : 
    2016             :                     // Push current level and nOutlineId on stack:
    2017           0 :                     aOutlineStack.push( StackEntry( nLevel, nOutlineId ) );
    2018             :                 }
    2019           0 :             }
    2020             :         }
    2021             : 
    2022           0 :         if( pPDFExtOutDevData->GetIsExportNamedDestinations() )
    2023             :         {
    2024             :             // #i56629# the iteration to convert the OOo bookmark (#bookmark)
    2025             :             // into PDF named destination, see section 8.2.1 in PDF 1.4 spec
    2026             :             // We need:
    2027             :             // 1. a name for the destination, formed from the standard OOo bookmark name
    2028             :             // 2. the destination, obtained from where the bookmark destination lies
    2029           0 :             IDocumentMarkAccess* const pMarkAccess = mrSh.GetDoc()->getIDocumentMarkAccess();
    2030           0 :             for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
    2031           0 :                 ppMark != pMarkAccess->getBookmarksEnd();
    2032             :                 ++ppMark)
    2033             :             {
    2034             :                 //get the name
    2035           0 :                 const ::sw::mark::IMark* pBkmk = ppMark->get();
    2036           0 :                 mrSh.SwCrsrShell::ClearMark();
    2037           0 :                 OUString sBkName = pBkmk->GetName();
    2038             : 
    2039             :                 //jump to it
    2040           0 :                 JumpToSwMark( &mrSh, sBkName );
    2041             : 
    2042             :                 // Destination Rectangle
    2043           0 :                 const SwRect& rDestRect = mrSh.GetCharRect();
    2044             : 
    2045             :                 // Destination PageNum
    2046           0 :                 const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    2047             : 
    2048             :                 // Destination Export
    2049           0 :                 if ( -1 != nDestPageNum )
    2050           0 :                     pPDFExtOutDevData->CreateNamedDest( sBkName, rDestRect.SVRect(), nDestPageNum );
    2051           0 :             }
    2052           0 :             mrSh.SwCrsrShell::ClearMark();
    2053             :             //<--- i56629
    2054           0 :         }
    2055             :     }
    2056             :     else
    2057             :     {
    2058             : 
    2059             :         // LINKS FROM EDITENGINE
    2060             : 
    2061           0 :         std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
    2062           0 :         std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIBeg = rBookmarks.begin();
    2063           0 :         const std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIEnd = rBookmarks.end();
    2064           0 :         while ( aIBeg != aIEnd )
    2065             :         {
    2066           0 :             OUString aBookmarkName( aIBeg->aBookmark );
    2067           0 :             const bool bIntern = '#' == aBookmarkName[0];
    2068           0 :             if ( bIntern )
    2069             :             {
    2070           0 :                 aBookmarkName = aBookmarkName.copy( 1 );
    2071           0 :                 JumpToSwMark( &mrSh, aBookmarkName );
    2072             : 
    2073             :                 // Destination Rectangle
    2074           0 :                 const SwRect& rDestRect = mrSh.GetCharRect();
    2075             : 
    2076             :                 // Destination PageNum
    2077           0 :                 const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
    2078             : 
    2079           0 :                 if ( -1 != nDestPageNum )
    2080             :                 {
    2081           0 :                     if ( aIBeg->nLinkId != -1 )
    2082             :                     {
    2083             :                         // Destination Export
    2084           0 :                         const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
    2085             : 
    2086             :                         // Connect Link and Destination:
    2087           0 :                         pPDFExtOutDevData->SetLinkDest( aIBeg->nLinkId, nDestId );
    2088             :                     }
    2089             :                     else
    2090             :                     {
    2091           0 :                         pPDFExtOutDevData->DescribeRegisteredDest( aIBeg->nDestId, rDestRect.SVRect(), nDestPageNum );
    2092             :                     }
    2093             :                 }
    2094             :             }
    2095             :             else
    2096           0 :                 pPDFExtOutDevData->SetLinkURL( aIBeg->nLinkId, aBookmarkName );
    2097             : 
    2098           0 :             ++aIBeg;
    2099           0 :         }
    2100           0 :         rBookmarks.clear();
    2101             :     }
    2102             : 
    2103             :     // Restore view, cursor, and outdev:
    2104           0 :     mrSh.LockView( bOldLockView );
    2105           0 :     mrSh.SwCrsrShell::Pop( false );
    2106           0 :     mrOut.Pop();
    2107             : }
    2108             : 
    2109             : /*
    2110             :  * SwEnhancedPDFExportHelper::CalcOutputPageNum()
    2111             :  *
    2112             :  * Returns the page number in the output pdf on which the given rect is located.
    2113             :  * If this page is duplicated, method will return first occurrence of it.
    2114             :  */
    2115           0 : sal_Int32 SwEnhancedPDFExportHelper::CalcOutputPageNum( const SwRect& rRect ) const
    2116             : {
    2117           0 :     std::vector< sal_Int32 > aPageNums = CalcOutputPageNums( rRect );
    2118           0 :     if ( !aPageNums.empty() )
    2119           0 :         return aPageNums[0];
    2120           0 :     return -1;
    2121             : }
    2122             : 
    2123             : /*
    2124             :  * SwEnhancedPDFExportHelper::CalcOutputPageNums()
    2125             :  *
    2126             :  * Returns a vector of the page numbers in the output pdf on which the given
    2127             :  * rect is located. There can be many such pages since StringRangeEnumerator
    2128             :  * allows duplication of its entries.
    2129             :  */
    2130           0 : std::vector< sal_Int32 > SwEnhancedPDFExportHelper::CalcOutputPageNums(
    2131             :     const SwRect& rRect ) const
    2132             : {
    2133           0 :     std::vector< sal_Int32 > aPageNums;
    2134             : 
    2135             :     // Document page number.
    2136           0 :     sal_Int32 nPageNumOfRect = mrSh.GetPageNumAndSetOffsetForPDF( mrOut, rRect );
    2137           0 :     if ( nPageNumOfRect < 0 )
    2138           0 :         return aPageNums;
    2139             : 
    2140             :     // What will be the page numbers of page nPageNumOfRect in the output pdf?
    2141           0 :     if ( mpRangeEnum )
    2142             :     {
    2143           0 :         if ( mbSkipEmptyPages )
    2144             :             // Map the page number to the range without empty pages.
    2145           0 :             nPageNumOfRect = maPageNumberMap[ nPageNumOfRect ];
    2146             : 
    2147           0 :         if ( mpRangeEnum->hasValue( nPageNumOfRect ) )
    2148             :         {
    2149           0 :             sal_Int32 nOutputPageNum = 0;
    2150           0 :             StringRangeEnumerator::Iterator aIter = mpRangeEnum->begin();
    2151           0 :             StringRangeEnumerator::Iterator aEnd  = mpRangeEnum->end();
    2152           0 :             for ( ; aIter != aEnd; ++aIter )
    2153             :             {
    2154           0 :                 if ( *aIter == nPageNumOfRect )
    2155           0 :                     aPageNums.push_back( nOutputPageNum );
    2156           0 :                 ++nOutputPageNum;
    2157             :             }
    2158             :         }
    2159             :     }
    2160             :     else
    2161             :     {
    2162           0 :         if ( mbSkipEmptyPages )
    2163             :         {
    2164           0 :             sal_Int32 nOutputPageNum = 0;
    2165           0 :             for ( size_t i = 0; i < maPageNumberMap.size(); ++i )
    2166             :             {
    2167           0 :                 if ( maPageNumberMap[i] >= 0 ) // is not empty?
    2168             :                 {
    2169           0 :                     if ( i == static_cast<size_t>( nPageNumOfRect ) )
    2170             :                     {
    2171           0 :                         aPageNums.push_back( nOutputPageNum );
    2172           0 :                         break;
    2173             :                     }
    2174           0 :                     ++nOutputPageNum;
    2175             :                 }
    2176             :             }
    2177             :         }
    2178             :         else
    2179           0 :             aPageNums.push_back( nPageNumOfRect );
    2180             :     }
    2181             : 
    2182           0 :     return aPageNums;
    2183             : }
    2184             : 
    2185           0 : void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rPDFExtOutDevData,
    2186             :                                                        const SwTxtNode& rTNd,
    2187             :                                                        const SwRect& rLinkRect,
    2188             :                                                        sal_Int32 nDestId,
    2189             :                                                        const OUString& rURL,
    2190             :                                                        bool bIntern ) const
    2191             : {
    2192             :     // We assume, that the primary link has just been exported. Therefore
    2193             :     // the offset of the link rectangle calculates as follows:
    2194           0 :     const Point aOffset = rLinkRect.Pos() + mrOut.GetMapMode().GetOrigin();
    2195             : 
    2196           0 :     SwIterator<SwTxtFrm,SwTxtNode> aIter( rTNd );
    2197           0 :     for ( SwTxtFrm* pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
    2198             :         {
    2199             :             // Add offset to current page:
    2200           0 :             const SwPageFrm* pPageFrm = pTmpFrm->FindPageFrm();
    2201           0 :             SwRect aHFLinkRect( rLinkRect );
    2202           0 :             aHFLinkRect.Pos() = pPageFrm->Frm().Pos() + aOffset;
    2203             : 
    2204             :             // #i97135# the gcc_x64 optimizer gets aHFLinkRect != rLinkRect wrong
    2205             :             // fool it by comparing the position only (the width and height are the
    2206             :             // same anyway)
    2207           0 :             if ( aHFLinkRect.Pos() != rLinkRect.Pos() )
    2208             :             {
    2209             :                 // Link PageNums
    2210           0 :                 std::vector<sal_Int32> aHFLinkPageNums = CalcOutputPageNums( aHFLinkRect );
    2211             : 
    2212           0 :                 for ( size_t nNumIdx = 0; nNumIdx < aHFLinkPageNums.size(); ++nNumIdx )
    2213             :                 {
    2214             :                     // Link Export
    2215             :                     const sal_Int32 nHFLinkId =
    2216           0 :                         rPDFExtOutDevData.CreateLink( aHFLinkRect.SVRect(), aHFLinkPageNums[nNumIdx] );
    2217             : 
    2218             :                     // Connect Link and Destination:
    2219           0 :                     if ( bIntern )
    2220           0 :                         rPDFExtOutDevData.SetLinkDest( nHFLinkId, nDestId );
    2221             :                     else
    2222           0 :                         rPDFExtOutDevData.SetLinkURL( nHFLinkId, rURL );
    2223           0 :                 }
    2224             :             }
    2225           0 :         }
    2226           0 : }
    2227             : 
    2228             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10