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

Generated by: LCOV version 1.10