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

Generated by: LCOV version 1.11