2008-12-19 10:32:51 +0100 od r265718 : #i70748# method <SwWW8Writer::StartTOX(..)> - correction for custom to outline style assigned paragraph styles 2008-12-19 09:24:41 +0100 od r265715 : #i70748# method <HandleModifyAtTxtNode(..)> - retrieve former applied list style before potential reset of empty list style due to set outline level 2008-12-17 15:33:57 +0100 hde r265608 : #i97013# 2008-12-17 14:43:42 +0100 od r265603 : #i70748# adjust fix i44177 - adjustment of to outline style assigned paragraph styles only for OOo-Templates. 2008-12-17 12:59:42 +0100 od r265598 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - special handling of OOo 2.x document regarding outline numbering of headings. 2008-12-17 12:45:53 +0100 od r265597 : #i70748# method <HandleModifyAtTxtNode(..)> - correct determination of new and former applied list style 2008-12-17 10:18:41 +0100 od r265581 : #i97312# method <XMLTextNumRuleInfo::Set(..)> - check, if numbering rules instance contains any numbering rule. 2008-12-16 14:34:22 +0100 hde r265542 : #i97013 2008-12-16 14:20:24 +0100 od r265541 : #i70748# adjust documentation of "Which"-ID numbers 2008-12-16 14:19:49 +0100 od r265539 : #i70748# Adjust Attribute-Function-Mapping table due to new attribute 2008-12-16 14:06:24 +0100 od r265538 : #i70748# - Correct handling of to outline style assigned paragraph styles on reset of all paragraph style attributes - WW8 import: Consider refactoring of paragraph style's outline level attribute - NO_NUMBERING define no longer exsits. 2008-12-16 10:37:19 +0100 od r265530 : #i70478# Correction on moving outline paragraph up respectively down in its outline level: - Check also outline paragraph, which are not an outline via a to outline style assigned paragraph style, if action is applicable. 2008-12-16 09:10:13 +0100 hde r265523 : #i97277 2008-12-16 09:09:30 +0100 hde r265522 : #i97277 2008-12-16 09:07:40 +0100 hde r265521 : Added control and purged obsolete id's 2008-12-10 13:09:36 +0100 od r265174 : #i70748# correction of previous fix due to warning-free code 2008-12-10 13:03:30 +0100 od r265172 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - Due to performance issues avoid retrieving outline level value from paragraph's paragraph style for each paragraph. Instead retrieve current outline level value from paragraph, which is the inherited value from its paragraph style, and only when it is needed. 2008-12-09 16:50:36 +0100 ufi r265117 : help 2008-12-09 16:49:50 +0100 ufi r265116 : help 2008-12-09 15:45:05 +0100 od r265107 : #i70748# method <XMLTextImportHelper::SetStyleAndAttrs(..)> - some minor rework and check access to paragraph styles 2008-12-09 15:42:04 +0100 od r265106 : #i70748# adjust name of local variable to avoid hiding of class variable 2008-12-09 15:40:51 +0100 od r265105 : #i70748# correct initialization order 2008-12-09 15:35:07 +0100 od r265101 : #i70748# remove duplicate entry in certain property map 2008-12-09 15:33:39 +0100 od r265100 : #i70748# add end of file token 2008-12-07 15:11:54 +0100 zhaojianwei r264952 : conflicts left not to be resolved when cws rebase 2008-12-04 14:52:21 +0100 zhaojianwei r264846 : CWS-TOOLING: rebase CWS outlinelevel to trunk@264325 (milestone: DEV300:m36) 2008-11-28 03:42:09 +0100 zhaojianwei r264525 : #i70748#: migrate CWS outlinelevel to SVN 2008-11-28 03:41:39 +0100 zhaojianwei r264524 : #i70748#: migrate CWS outlinelevel to SVN 2008-11-28 03:41:11 +0100 zhaojianwei r264523 : #i70748#: migrate CWS outlinelevel to SVN
2214 lines
79 KiB
C++
2214 lines
79 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: EnhancedPDFExportHelper.cxx,v $
|
|
* $Revision: 1.26.138.1 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_sw.hxx"
|
|
#include <com/sun/star/embed/XEmbeddedObject.hpp>
|
|
#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
|
|
#include <com/sun/star/i18n/ScriptType.hdl>
|
|
#endif
|
|
#include <EnhancedPDFExportHelper.hxx>
|
|
#include <hintids.hxx>
|
|
|
|
#ifndef _OUTDEV_HXX
|
|
#include <vcl/outdev.hxx>
|
|
#endif
|
|
#include <tools/multisel.hxx>
|
|
#include <svx/adjitem.hxx>
|
|
#include <svx/lrspitem.hxx>
|
|
#include <svx/langitem.hxx>
|
|
#include <svx/scripttypeitem.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <svtools/zforlist.hxx>
|
|
#include <swatrset.hxx>
|
|
#include <frmatr.hxx>
|
|
#include <paratr.hxx>
|
|
#include <ndtxt.hxx>
|
|
#include <ndole.hxx>
|
|
#include <section.hxx>
|
|
#include <tox.hxx>
|
|
#include <fmtfld.hxx>
|
|
#include <txtinet.hxx>
|
|
#include <fmtinfmt.hxx>
|
|
#include <fchrfmt.hxx>
|
|
#include <charfmt.hxx>
|
|
#include <fmtanchr.hxx>
|
|
#include <fmturl.hxx>
|
|
#include <editsh.hxx>
|
|
#include <viscrs.hxx>
|
|
#include <txtfld.hxx>
|
|
#include <reffld.hxx>
|
|
#include <doc.hxx>
|
|
#include <docary.hxx>
|
|
#include <crsskip.hxx>
|
|
#include <mdiexp.hxx>
|
|
#include <docufld.hxx>
|
|
#include <ftnidx.hxx>
|
|
#include <txtftn.hxx>
|
|
#include <fmtftn.hxx>
|
|
#include <rootfrm.hxx>
|
|
#include <pagefrm.hxx>
|
|
#include <txtfrm.hxx>
|
|
#include <tabfrm.hxx>
|
|
#include <rowfrm.hxx>
|
|
#include <cellfrm.hxx>
|
|
#include <sectfrm.hxx>
|
|
#include <flyfrm.hxx>
|
|
#include <notxtfrm.hxx>
|
|
#include <porfld.hxx>
|
|
#include <SwStyleNameMapper.hxx>
|
|
#include <itrpaint.hxx>
|
|
#include "i18npool/mslangid.hxx"
|
|
#include <bookmrk.hxx>
|
|
#include <SwNodeNum.hxx>
|
|
|
|
#include <stack>
|
|
|
|
#include <tools/globname.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
//
|
|
// Some static data structures
|
|
//
|
|
TableColumnsMap SwEnhancedPDFExportHelper::aTableColumnsMap;
|
|
LinkIdMap SwEnhancedPDFExportHelper::aLinkIdMap;
|
|
NumListIdMap SwEnhancedPDFExportHelper::aNumListIdMap;
|
|
NumListBodyIdMap SwEnhancedPDFExportHelper::aNumListBodyIdMap;
|
|
FrmTagIdMap SwEnhancedPDFExportHelper::aFrmTagIdMap;
|
|
|
|
LanguageType SwEnhancedPDFExportHelper::eLanguageDefault = 0;
|
|
|
|
#ifndef PRODUCT
|
|
|
|
static std::vector< USHORT > aStructStack;
|
|
|
|
void lcl_DBGCheckStack()
|
|
{
|
|
/* NonStructElement = 0 Document = 1 Part = 2
|
|
* Article = 3 Section = 4 Division = 5
|
|
* BlockQuote = 6 Caption = 7 TOC = 8
|
|
* TOCI = 9 Index = 10 Paragraph = 11
|
|
* Heading = 12 H1-6 = 13 - 18 List = 19
|
|
* ListItem = 20 LILabel = 21 LIBody = 22
|
|
* Table = 23 TableRow = 24 TableHeader = 25
|
|
* TableData = 26 Span = 27 Quote = 28
|
|
* Note = 29 Reference = 30 BibEntry = 31
|
|
* Code = 32 Link = 33 Figure = 34
|
|
* Formula = 35 Form = 36 Continued frame = 99
|
|
*/
|
|
|
|
USHORT nElement;
|
|
std::vector< USHORT >::iterator aIter;
|
|
for ( aIter = aStructStack.begin(); aIter != aStructStack.end(); ++aIter )
|
|
{
|
|
nElement = *aIter;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
// ODF Style Names:
|
|
const String aTableHeadingName = String::CreateFromAscii("Table Heading");
|
|
const String aQuotations = String::CreateFromAscii("Quotations");
|
|
const String aCaption = String::CreateFromAscii("Caption");
|
|
const String aHeading = String::CreateFromAscii("Heading");
|
|
const String aQuotation = String::CreateFromAscii("Quotation");
|
|
const String aSourceText = String::CreateFromAscii("Source Text");
|
|
|
|
// PDF Tag Names:
|
|
const String aDocumentString = String::CreateFromAscii("Document");
|
|
const String aDivString = String::CreateFromAscii("Div");
|
|
const String aSectString = String::CreateFromAscii("Sect");
|
|
const String aHString = String::CreateFromAscii("H");
|
|
const String aH1String = String::CreateFromAscii("H1");
|
|
const String aH2String = String::CreateFromAscii("H2");
|
|
const String aH3String = String::CreateFromAscii("H3");
|
|
const String aH4String = String::CreateFromAscii("H4");
|
|
const String aH5String = String::CreateFromAscii("H5");
|
|
const String aH6String = String::CreateFromAscii("H6");
|
|
const String aListString = String::CreateFromAscii("L");
|
|
const String aListItemString = String::CreateFromAscii("LI");
|
|
const String aListBodyString = String::CreateFromAscii("LBody");
|
|
const String aBlockQuoteString = String::CreateFromAscii("BlockQuote");
|
|
const String aCaptionString = String::CreateFromAscii("Caption");
|
|
const String aIndexString = String::CreateFromAscii("Index");
|
|
const String aTOCString = String::CreateFromAscii("TOC");
|
|
const String aTOCIString = String::CreateFromAscii("TOCI");
|
|
const String aTableString = String::CreateFromAscii("Table");
|
|
const String aTRString = String::CreateFromAscii("TR");
|
|
const String aTDString = String::CreateFromAscii("TD");
|
|
const String aTHString = String::CreateFromAscii("TH");
|
|
const String aBibEntryString = String::CreateFromAscii("BibEntry");
|
|
const String aQuoteString = String::CreateFromAscii("Quote");
|
|
const String aSpanString = String::CreateFromAscii("Span");
|
|
const String aCodeString = String::CreateFromAscii("Code");
|
|
const String aFigureString = String::CreateFromAscii("Figure");
|
|
const String aFormulaString = String::CreateFromAscii("Formula");
|
|
const String aLinkString = String::CreateFromAscii("Link");
|
|
const String aNoteString = String::CreateFromAscii("Note");
|
|
const String aEmptyString = String::CreateFromAscii("");
|
|
|
|
// returns true if first paragraph in cell frame has 'table heading' style
|
|
bool lcl_IsHeadlineCell( const SwCellFrm& rCellFrm )
|
|
{
|
|
bool bRet = false;
|
|
|
|
const SwCntntFrm *pCnt = rCellFrm.ContainsCntnt();
|
|
if ( pCnt && pCnt->IsTxtFrm() )
|
|
{
|
|
const SwTxtNode* pTxtNode = static_cast<const SwTxtFrm*>(pCnt)->GetTxtNode();
|
|
const SwFmt* pTxtFmt = pTxtNode->GetFmtColl();
|
|
|
|
String sStyleName;
|
|
SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
|
|
bRet = sStyleName == aTableHeadingName;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// List all frames for which the NonStructElement tag is set:
|
|
bool lcl_IsInNonStructEnv( const SwFrm& rFrm )
|
|
{
|
|
bool bRet = false;
|
|
|
|
if ( 0 != rFrm.FindFooterOrHeader() &&
|
|
!rFrm.IsHeaderFrm() && !rFrm.IsFooterFrm() )
|
|
{
|
|
bRet = true;
|
|
}
|
|
else if ( rFrm.IsInTab() && !rFrm.IsTabFrm() )
|
|
{
|
|
const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
|
|
if ( rFrm.GetUpper() != pTabFrm &&
|
|
pTabFrm->IsFollow() && pTabFrm->IsInHeadline( rFrm ) )
|
|
bRet = true;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// Generate key from frame for reopening tags:
|
|
void* lcl_GetKeyFromFrame( const SwFrm& rFrm )
|
|
{
|
|
void* pKey = 0;
|
|
|
|
if ( rFrm.IsPageFrm() )
|
|
pKey = (void*)static_cast<const SwPageFrm&>(rFrm).GetFmt()->getIDocumentSettingAccess();
|
|
else if ( rFrm.IsTxtFrm() )
|
|
pKey = (void*)static_cast<const SwTxtFrm&>(rFrm).GetTxtNode();
|
|
else if ( rFrm.IsSctFrm() )
|
|
pKey = (void*)static_cast<const SwSectionFrm&>(rFrm).GetSection();
|
|
else if ( rFrm.IsTabFrm() )
|
|
pKey = (void*)static_cast<const SwTabFrm&>(rFrm).GetTable();
|
|
else if ( rFrm.IsRowFrm() )
|
|
pKey = (void*)static_cast<const SwRowFrm&>(rFrm).GetTabLine();
|
|
else if ( rFrm.IsCellFrm() )
|
|
{
|
|
const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
|
|
const SwTable* pTable = pTabFrm->GetTable();
|
|
pKey = (void*) & static_cast<const SwCellFrm&>(rFrm).GetTabBox()->FindStartOfRowSpan( *pTable );
|
|
}
|
|
|
|
return pKey;
|
|
}
|
|
|
|
bool lcl_HasPreviousParaSameNumRule( const SwTxtNode& rNode )
|
|
{
|
|
bool bRet = false;
|
|
SwNodeIndex aIdx( rNode );
|
|
const SwDoc* pDoc = rNode.GetDoc();
|
|
const SwNodes& rNodes = pDoc->GetNodes();
|
|
const SwNode* pNode = &rNode;
|
|
const SwNumRule* pNumRule = rNode.GetNumRule();
|
|
|
|
while (! (pNode == rNodes.DocumentSectionStartNode((SwNode*)&rNode) ) )
|
|
{
|
|
--aIdx;
|
|
|
|
if (aIdx.GetNode().IsTxtNode())
|
|
{
|
|
const SwTxtNode* pPrevTxtNd = aIdx.GetNode().GetTxtNode();
|
|
const SwNumRule * pPrevNumRule = pPrevTxtNd->GetNumRule();
|
|
|
|
// We find the previous text node. Now check, if the previous text node
|
|
// has the same numrule like rNode:
|
|
if ( (pPrevNumRule == pNumRule) &&
|
|
(!pPrevTxtNd->IsOutline() == !rNode.IsOutline()))
|
|
bRet = true;
|
|
|
|
break;
|
|
}
|
|
|
|
pNode = &aIdx.GetNode();
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
} // end namespace
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::SwTaggedPDFHelper()
|
|
*/
|
|
SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info* pNumInfo,
|
|
const Frm_Info* pFrmInfo,
|
|
const Por_Info* pPorInfo,
|
|
OutputDevice& rOut )
|
|
: nEndStructureElement( 0 ),
|
|
nRestoreCurrentTag( -1 ),
|
|
mpNumInfo( pNumInfo ),
|
|
mpFrmInfo( pFrmInfo ),
|
|
mpPorInfo( pPorInfo )
|
|
{
|
|
mpPDFExtOutDevData =
|
|
PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
|
|
|
|
if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
|
|
{
|
|
#ifndef PRODUCT
|
|
sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
lcl_DBGCheckStack();
|
|
#endif
|
|
if ( mpNumInfo )
|
|
BeginNumberedListStructureElements();
|
|
else if ( mpFrmInfo )
|
|
BeginBlockStructureElements();
|
|
else if ( mpPorInfo )
|
|
BeginInlineStructureElements();
|
|
else
|
|
BeginTag( vcl::PDFWriter::NonStructElement, aEmptyString );
|
|
|
|
#ifndef PRODUCT
|
|
nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
lcl_DBGCheckStack();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::~SwTaggedPDFHelper()
|
|
*/
|
|
SwTaggedPDFHelper::~SwTaggedPDFHelper()
|
|
{
|
|
if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
|
|
{
|
|
#ifndef PRODUCT
|
|
sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
lcl_DBGCheckStack();
|
|
#endif
|
|
EndStructureElements();
|
|
|
|
#ifndef PRODUCT
|
|
nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
lcl_DBGCheckStack();
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::CheckReopenTag()
|
|
*/
|
|
bool SwTaggedPDFHelper::CheckReopenTag()
|
|
{
|
|
bool bRet = false;
|
|
sal_Int32 nReopenTag = -1;
|
|
bool bContinue = false; // in some cases we just have to reopen a tag without early returning
|
|
|
|
if ( mpFrmInfo )
|
|
{
|
|
const SwFrm& rFrm = mpFrmInfo->mrFrm;
|
|
const SwFrm* pKeyFrm = 0;
|
|
void* pKey = 0;
|
|
|
|
// Reopen an existing structure element if
|
|
// - rFrm is not the first page frame (reopen Document tag)
|
|
// - rFrm is a follow frame (reopen Master tag)
|
|
// - rFrm is a fly frame anchored at content (reopen Anchor paragraph tag)
|
|
// - rFrm is a fly frame anchord at page (reopen Document tag)
|
|
// - rFrm is a follow flow row (reopen TableRow tag)
|
|
// - rFrm is a cell frame in a follow flow row (reopen TableData tag)
|
|
if ( ( rFrm.IsPageFrm() && static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
|
|
( rFrm.IsFlowFrm() && SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() ) ||
|
|
( rFrm.IsRowFrm() && rFrm.IsInFollowFlowRow() ) ||
|
|
( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetPrevCellLeaf( MAKEPAGE_NONE ) ) )
|
|
{
|
|
pKeyFrm = &rFrm;
|
|
}
|
|
else if ( rFrm.IsFlyFrm() )
|
|
{
|
|
const SwFmtAnchor& rAnchor =
|
|
static_cast<const SwFlyFrm*>(&rFrm)->GetFmt()->GetAnchor();
|
|
if ( FLY_AT_CNTNT == rAnchor.GetAnchorId() ||
|
|
FLY_AUTO_CNTNT == rAnchor.GetAnchorId() ||
|
|
FLY_PAGE == rAnchor.GetAnchorId() )
|
|
{
|
|
pKeyFrm = static_cast<const SwFlyFrm&>(rFrm).GetAnchorFrm();
|
|
bContinue = true;
|
|
}
|
|
}
|
|
|
|
if ( pKeyFrm )
|
|
{
|
|
pKey = lcl_GetKeyFromFrame( *pKeyFrm );
|
|
|
|
if ( pKey )
|
|
{
|
|
FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
|
|
const FrmTagIdMap::const_iterator aIter = rFrmTagIdMap.find( pKey );
|
|
nReopenTag = (*aIter).second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( -1 != nReopenTag )
|
|
{
|
|
nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
|
|
ASSERT( bSuccess, "Failed to reopen tag" )
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.push_back( 99 );
|
|
#endif
|
|
|
|
bRet = bSuccess;
|
|
}
|
|
|
|
return bRet && !bContinue;
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::CheckRestoreTag()
|
|
*/
|
|
bool SwTaggedPDFHelper::CheckRestoreTag() const
|
|
{
|
|
bool bRet = false;
|
|
if ( nRestoreCurrentTag != -1 )
|
|
{
|
|
const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nRestoreCurrentTag );
|
|
(void)bSuccess;
|
|
ASSERT( bSuccess, "Failed to restore reopened tag" )
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.pop_back();
|
|
#endif
|
|
|
|
bRet = true;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::BeginTag()
|
|
*/
|
|
void SwTaggedPDFHelper::BeginTag( vcl::PDFWriter::StructElement eType, const String& rString )
|
|
{
|
|
// write new tag
|
|
const sal_Int32 nId = mpPDFExtOutDevData->BeginStructureElement( eType, rtl::OUString( rString ) );
|
|
++nEndStructureElement;
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.push_back( static_cast<USHORT>(eType) );
|
|
#endif
|
|
|
|
// Store the id of the current structure element if
|
|
// - it is a list structure element
|
|
// - it is a list body element with children
|
|
// - rFrm is the first page frame
|
|
// - rFrm is a master frame
|
|
// - rFrm has objects anchored to it
|
|
// - rFrm is a row frame or cell frame in a split table row
|
|
|
|
if ( mpNumInfo )
|
|
{
|
|
const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(mpNumInfo->mrFrm);
|
|
const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
|
|
const SwNodeNum* pNodeNum = pTxtNd->GetNum();
|
|
|
|
if ( vcl::PDFWriter::List == eType )
|
|
{
|
|
NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
|
|
rNumListIdMap[ pNodeNum ] = nId;
|
|
}
|
|
else if ( vcl::PDFWriter::LIBody == eType )
|
|
{
|
|
NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
|
|
rNumListBodyIdMap[ pNodeNum ] = nId;
|
|
}
|
|
}
|
|
else if ( mpFrmInfo )
|
|
{
|
|
const SwFrm& rFrm = mpFrmInfo->mrFrm;
|
|
|
|
if ( ( rFrm.IsPageFrm() && !static_cast<const SwPageFrm&>(rFrm).GetPrev() ) ||
|
|
( rFrm.IsFlowFrm() && !SwFlowFrm::CastFlowFrm(&rFrm)->IsFollow() && SwFlowFrm::CastFlowFrm(&rFrm)->HasFollow() ) ||
|
|
( rFrm.IsTxtFrm() && rFrm.GetDrawObjs() ) ||
|
|
( rFrm.IsRowFrm() && rFrm.IsInSplitTableRow() ) ||
|
|
( rFrm.IsCellFrm() && const_cast<SwFrm&>(rFrm).GetNextCellLeaf( MAKEPAGE_NONE ) ) )
|
|
{
|
|
const void* pKey = lcl_GetKeyFromFrame( rFrm );
|
|
|
|
if ( pKey )
|
|
{
|
|
FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
|
|
rFrmTagIdMap[ pKey ] = nId;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetAttributes( eType );
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::EndTag()
|
|
*/
|
|
void SwTaggedPDFHelper::EndTag()
|
|
{
|
|
mpPDFExtOutDevData->EndStructureElement();
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.pop_back();
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::SetAttributes()
|
|
*
|
|
* Sets the attributes according to the structure type.
|
|
*/
|
|
void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType )
|
|
{
|
|
vcl::PDFWriter::StructAttributeValue eVal;
|
|
sal_Int32 nVal;
|
|
|
|
/*
|
|
* ATTRIBUTES FOR BLSE
|
|
*/
|
|
if ( mpFrmInfo )
|
|
{
|
|
const SwFrm* pFrm = &mpFrmInfo->mrFrm;
|
|
SWRECTFN( pFrm )
|
|
|
|
bool bPlacement = false;
|
|
bool bWritingMode = false;
|
|
bool bSpaceBefore = false;
|
|
bool bSpaceAfter = false;
|
|
bool bStartIndent = false;
|
|
bool bEndIndent = false;
|
|
bool bTextIndent = false;
|
|
bool bTextAlign = false;
|
|
bool bAlternateText = false;
|
|
bool bWidth = false;
|
|
bool bHeight = false;
|
|
bool bBox = false;
|
|
bool bRowSpan = false;
|
|
|
|
//
|
|
// Check which attributes to set:
|
|
//
|
|
switch ( eType )
|
|
{
|
|
case vcl::PDFWriter::Document :
|
|
bWritingMode = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::Table :
|
|
bPlacement =
|
|
bWritingMode =
|
|
bSpaceBefore =
|
|
bSpaceAfter =
|
|
bStartIndent =
|
|
bEndIndent =
|
|
bWidth =
|
|
bHeight =
|
|
bBox = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::TableRow :
|
|
bPlacement =
|
|
bWritingMode = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::TableHeader :
|
|
case vcl::PDFWriter::TableData :
|
|
bPlacement =
|
|
bWritingMode =
|
|
bWidth =
|
|
bHeight =
|
|
bRowSpan = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::H1 :
|
|
case vcl::PDFWriter::H2 :
|
|
case vcl::PDFWriter::H3 :
|
|
case vcl::PDFWriter::H4 :
|
|
case vcl::PDFWriter::H5 :
|
|
case vcl::PDFWriter::H6 :
|
|
case vcl::PDFWriter::Paragraph :
|
|
case vcl::PDFWriter::Heading :
|
|
case vcl::PDFWriter::Caption :
|
|
case vcl::PDFWriter::BlockQuote :
|
|
|
|
bPlacement =
|
|
bWritingMode =
|
|
bSpaceBefore =
|
|
bSpaceAfter =
|
|
bStartIndent =
|
|
bEndIndent =
|
|
bTextIndent =
|
|
bTextAlign = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::Formula :
|
|
case vcl::PDFWriter::Figure :
|
|
bPlacement =
|
|
bAlternateText =
|
|
bWidth =
|
|
bHeight =
|
|
bBox = true;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the attributes:
|
|
//
|
|
if ( bPlacement )
|
|
{
|
|
eVal = vcl::PDFWriter::TableHeader == eType ||
|
|
vcl::PDFWriter::TableData == eType ?
|
|
vcl::PDFWriter::Inline :
|
|
vcl::PDFWriter::Block;
|
|
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::Placement, eVal );
|
|
}
|
|
|
|
if ( bWritingMode )
|
|
{
|
|
eVal = pFrm->IsVertical() ?
|
|
vcl::PDFWriter::TbRl :
|
|
pFrm->IsRightToLeft() ?
|
|
vcl::PDFWriter::RlTb :
|
|
vcl::PDFWriter::LrTb;
|
|
|
|
if ( vcl::PDFWriter::LrTb != eVal )
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::WritingMode, eVal );
|
|
}
|
|
|
|
if ( bSpaceBefore )
|
|
{
|
|
nVal = (pFrm->*fnRect->fnGetTopMargin)();
|
|
if ( 0 != nVal )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceBefore, nVal );
|
|
}
|
|
|
|
if ( bSpaceAfter )
|
|
{
|
|
nVal = (pFrm->*fnRect->fnGetBottomMargin)();
|
|
if ( 0 != nVal )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceAfter, nVal );
|
|
}
|
|
|
|
if ( bStartIndent )
|
|
{
|
|
nVal = (pFrm->*fnRect->fnGetLeftMargin)();
|
|
if ( 0 != nVal )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::StartIndent, nVal );
|
|
}
|
|
|
|
if ( bEndIndent )
|
|
{
|
|
nVal = (pFrm->*fnRect->fnGetRightMargin)();
|
|
if ( 0 != nVal )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::EndIndent, nVal );
|
|
}
|
|
|
|
if ( bTextIndent )
|
|
{
|
|
ASSERT( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" )
|
|
const SvxLRSpaceItem &rSpace =
|
|
static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
|
|
nVal = rSpace.GetTxtFirstLineOfst();
|
|
if ( 0 != nVal )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::TextIndent, nVal );
|
|
}
|
|
|
|
if ( bTextAlign )
|
|
{
|
|
ASSERT( pFrm->IsTxtFrm(), "Frame type <-> tag attribute mismatch" )
|
|
const SwAttrSet& aSet = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode()->GetSwAttrSet();
|
|
const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
|
|
if ( SVX_ADJUST_BLOCK == nAdjust || SVX_ADJUST_CENTER == nAdjust ||
|
|
( pFrm->IsRightToLeft() && SVX_ADJUST_LEFT == nAdjust ||
|
|
!pFrm->IsRightToLeft() && SVX_ADJUST_RIGHT == nAdjust ) )
|
|
{
|
|
eVal = SVX_ADJUST_BLOCK == nAdjust ?
|
|
vcl::PDFWriter::Justify :
|
|
SVX_ADJUST_CENTER == nAdjust ?
|
|
vcl::PDFWriter::Center :
|
|
vcl::PDFWriter::End;
|
|
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextAlign, eVal );
|
|
}
|
|
}
|
|
|
|
if ( bAlternateText )
|
|
{
|
|
ASSERT( pFrm->IsFlyFrm(), "Frame type <-> tag attribute mismatch" )
|
|
const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
|
|
if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
|
|
{
|
|
const SwNoTxtFrm* pNoTxtFrm = static_cast<const SwNoTxtFrm*>(pFly->Lower());
|
|
const SwNoTxtNode* pNoTxtNode = static_cast<const SwNoTxtNode*>(pNoTxtFrm->GetNode());
|
|
|
|
const String aAlternateTxt( pNoTxtNode->GetAlternateText() );
|
|
mpPDFExtOutDevData->SetAlternateText( aAlternateTxt );
|
|
}
|
|
}
|
|
|
|
if ( bWidth )
|
|
{
|
|
nVal = (pFrm->Frm().*fnRect->fnGetWidth)();
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Width, nVal );
|
|
}
|
|
|
|
if ( bHeight )
|
|
{
|
|
nVal = (pFrm->Frm().*fnRect->fnGetHeight)();
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Height, nVal );
|
|
}
|
|
|
|
if ( bBox )
|
|
{
|
|
// BBox only for non-split tables:
|
|
if ( vcl::PDFWriter::Table != eType ||
|
|
( pFrm->IsTabFrm() &&
|
|
!static_cast<const SwTabFrm*>(pFrm)->IsFollow() &&
|
|
!static_cast<const SwTabFrm*>(pFrm)->HasFollow() ) )
|
|
mpPDFExtOutDevData->SetStructureBoundingBox( pFrm->Frm().SVRect() );
|
|
}
|
|
|
|
if ( bRowSpan )
|
|
{
|
|
const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(pFrm);
|
|
if ( pThisCell )
|
|
{
|
|
nVal = pThisCell->GetTabBox()->getRowSpan();
|
|
if ( nVal > 1 )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::RowSpan, nVal );
|
|
|
|
// calculate colspan:
|
|
const SwTabFrm* pTabFrm = pThisCell->FindTabFrm();
|
|
const SwTable* pTable = pTabFrm->GetTable();
|
|
|
|
SWRECTFNX( pTabFrm )
|
|
|
|
const TableColumnsMapEntry& rCols = SwEnhancedPDFExportHelper::GetTableColumnsMap()[ pTable ];
|
|
|
|
const long nLeft = (pThisCell->Frm().*fnRectX->fnGetLeft)();
|
|
const long nRight = (pThisCell->Frm().*fnRectX->fnGetRight)();
|
|
const TableColumnsMapEntry::const_iterator aLeftIter = rCols.find( nLeft );
|
|
const TableColumnsMapEntry::const_iterator aRightIter = rCols.find( nRight );
|
|
|
|
ASSERT( aLeftIter != rCols.end() && aRightIter != rCols.end(), "Colspan trouble" )
|
|
if ( aLeftIter != rCols.end() && aRightIter != rCols.end() )
|
|
{
|
|
nVal = std::distance( aLeftIter, aRightIter );
|
|
if ( nVal > 1 )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::ColSpan, nVal );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ATTRIBUTES FOR ILSE
|
|
*/
|
|
else if ( mpPorInfo )
|
|
{
|
|
const SwLinePortion* pPor = &mpPorInfo->mrPor;
|
|
const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
|
|
|
|
bool bActualText = false;
|
|
bool bBaselineShift = false;
|
|
bool bTextDecorationType = false;
|
|
bool bLinkAttribute = false;
|
|
bool bLanguage = false;
|
|
|
|
//
|
|
// Check which attributes to set:
|
|
//
|
|
switch ( eType )
|
|
{
|
|
case vcl::PDFWriter::Span :
|
|
case vcl::PDFWriter::Quote :
|
|
case vcl::PDFWriter::Code :
|
|
bActualText =
|
|
bBaselineShift =
|
|
bTextDecorationType =
|
|
bLanguage = true;
|
|
break;
|
|
|
|
case vcl::PDFWriter::Link :
|
|
bTextDecorationType =
|
|
bBaselineShift =
|
|
bLinkAttribute =
|
|
bLanguage = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( bActualText )
|
|
{
|
|
const String aActualTxt( rInf.GetTxt(), rInf.GetIdx(), pPor->GetLen() );
|
|
mpPDFExtOutDevData->SetActualText( aActualTxt );
|
|
}
|
|
|
|
if ( bBaselineShift )
|
|
{
|
|
// TODO: Calculate correct values!
|
|
nVal = rInf.GetFont()->GetEscapement();
|
|
if ( nVal > 0 ) nVal = 33;
|
|
else if ( nVal < 0 ) nVal = -33;
|
|
|
|
if ( 0 != nVal )
|
|
{
|
|
nVal = nVal * pPor->Height() / 100;
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::BaselineShift, nVal );
|
|
}
|
|
}
|
|
|
|
if ( bTextDecorationType )
|
|
{
|
|
if ( UNDERLINE_NONE != rInf.GetFont()->GetUnderline() )
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Underline );
|
|
if ( UNDERLINE_NONE != rInf.GetFont()->GetOverline() )
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
|
|
if ( STRIKEOUT_NONE != rInf.GetFont()->GetStrikeout() )
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::LineThrough );
|
|
if ( EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() )
|
|
mpPDFExtOutDevData->SetStructureAttribute( vcl::PDFWriter::TextDecorationType, vcl::PDFWriter::Overline );
|
|
}
|
|
|
|
if ( bLanguage )
|
|
{
|
|
|
|
const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
|
|
const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
|
|
|
|
if ( nDefaultLang != nCurrentLanguage )
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Language, nCurrentLanguage );
|
|
}
|
|
|
|
if ( bLinkAttribute )
|
|
{
|
|
const LinkIdMap& rLinkIdMap = SwEnhancedPDFExportHelper::GetLinkIdMap();
|
|
SwRect aPorRect;
|
|
rInf.CalcRect( *pPor, &aPorRect );
|
|
const Point aPorCenter = aPorRect.Center();
|
|
LinkIdMap::const_iterator aIter;
|
|
for ( aIter = rLinkIdMap.begin(); aIter != rLinkIdMap.end(); ++aIter )
|
|
{
|
|
const SwRect& rLinkRect = (*aIter).first;
|
|
if ( rLinkRect.IsInside( aPorCenter ) )
|
|
{
|
|
sal_Int32 nLinkId = (*aIter).second;
|
|
mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::LinkAnnotation, nLinkId );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::BeginNumberedListStructureElements()
|
|
*/
|
|
void SwTaggedPDFHelper::BeginNumberedListStructureElements()
|
|
{
|
|
ASSERT( mpNumInfo, "List without mpNumInfo?" )
|
|
if ( !mpNumInfo )
|
|
return;
|
|
|
|
const SwFrm& rFrm = mpNumInfo->mrFrm;
|
|
ASSERT( rFrm.IsTxtFrm(), "numbered only for text frames" )
|
|
const SwTxtFrm& rTxtFrm = static_cast<const SwTxtFrm&>(rFrm);
|
|
|
|
//
|
|
// Lowers of NonStructureElements should not be considered:
|
|
//
|
|
if ( lcl_IsInNonStructEnv( rTxtFrm ) || rTxtFrm.IsFollow() )
|
|
return;
|
|
|
|
const SwTxtNode* pTxtNd = rTxtFrm.GetTxtNode();
|
|
const SwNumRule* pNumRule = pTxtNd->GetNumRule();
|
|
const SwNodeNum* pNodeNum = pTxtNd->GetNum();
|
|
|
|
const bool bNumbered = !pTxtNd->IsOutline() && pNodeNum && pNodeNum->GetParent() && pNumRule;
|
|
|
|
// Check, if we have to reopen a list or a list body:
|
|
// First condition:
|
|
// Paragraph is numbered/bulleted
|
|
if ( !bNumbered )
|
|
return;
|
|
|
|
const SwNumberTreeNode* pParent = pNodeNum->GetParent();
|
|
const bool bSameNumbering = lcl_HasPreviousParaSameNumRule(*pTxtNd);
|
|
|
|
// Second condition: current numbering is not 'interrupted'
|
|
if ( bSameNumbering )
|
|
{
|
|
sal_Int32 nReopenTag = -1;
|
|
|
|
// Two cases:
|
|
// 1. We have to reopen an existing list body tag:
|
|
// - If the current node is either the first child of its parent
|
|
// and its level > 1 or
|
|
// - Numbering should restart at the current node and its level > 1
|
|
// - The current item has no label
|
|
const bool bNewSubListStart = pParent->GetParent() && (pParent->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() );
|
|
const bool bNoLabel = !pTxtNd->IsCountedInList() && !pTxtNd->IsListRestart();
|
|
if ( bNewSubListStart || bNoLabel )
|
|
{
|
|
// Fine, we try to reopen the appropriate list body
|
|
NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
|
|
|
|
if ( bNewSubListStart )
|
|
{
|
|
// The list body tag associated with the parent has to be reopened
|
|
// to start a new list inside the list body
|
|
NumListBodyIdMap::const_iterator aIter;
|
|
|
|
do
|
|
aIter = rNumListBodyIdMap.find( pParent );
|
|
while ( aIter == rNumListBodyIdMap.end() && 0 != ( pParent = pParent->GetParent() ) );
|
|
|
|
if ( aIter != rNumListBodyIdMap.end() )
|
|
nReopenTag = (*aIter).second;
|
|
}
|
|
else // if(bNoLabel)
|
|
{
|
|
// The list body tag of a 'counted' predecessor has to be reopened
|
|
const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
|
|
while ( pPrevious )
|
|
{
|
|
if ( pPrevious->IsCounted())
|
|
{
|
|
// get id of list body tag
|
|
const NumListBodyIdMap::const_iterator aIter = rNumListBodyIdMap.find( pPrevious );
|
|
if ( aIter != rNumListBodyIdMap.end() )
|
|
{
|
|
nReopenTag = (*aIter).second;
|
|
break;
|
|
}
|
|
}
|
|
pPrevious = pPrevious->GetPred(true);
|
|
}
|
|
}
|
|
}
|
|
// 2. We have to reopen an existing list tag:
|
|
else if ( !pParent->IsFirst( pNodeNum ) && !pTxtNd->IsListRestart() )
|
|
{
|
|
// any other than the first node in a list level has to reopen the current
|
|
// list. The current list is associated in a map with the first child of the list:
|
|
NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
|
|
|
|
// Search backwards and check if any of the previous nodes has a list associated with it:
|
|
const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
|
|
while ( pPrevious )
|
|
{
|
|
// get id of list tag
|
|
const NumListIdMap::const_iterator aIter = rNumListIdMap.find( pPrevious );
|
|
if ( aIter != rNumListIdMap.end() )
|
|
{
|
|
nReopenTag = (*aIter).second;
|
|
break;
|
|
}
|
|
|
|
pPrevious = pPrevious->GetPred(true);
|
|
}
|
|
}
|
|
|
|
if ( -1 != nReopenTag )
|
|
{
|
|
nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
|
|
mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.push_back( 99 );
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// clear list maps in case a list has been interrupted
|
|
NumListIdMap& rNumListIdMap = SwEnhancedPDFExportHelper::GetNumListIdMap();
|
|
rNumListIdMap.clear();
|
|
NumListBodyIdMap& rNumListBodyIdMap = SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
|
|
rNumListBodyIdMap.clear();
|
|
}
|
|
|
|
// New tags:
|
|
const bool bNewListTag = (pNodeNum->GetParent()->IsFirst( pNodeNum ) || pTxtNd->IsListRestart() || !bSameNumbering);
|
|
const bool bNewItemTag = bNewListTag || pTxtNd->IsCountedInList(); // If the text node is not counted, we do not start a new list item:
|
|
|
|
if ( bNewListTag )
|
|
BeginTag( vcl::PDFWriter::List, aListString );
|
|
|
|
if ( bNewItemTag )
|
|
{
|
|
BeginTag( vcl::PDFWriter::ListItem, aListItemString );
|
|
BeginTag( vcl::PDFWriter::LIBody, aListBodyString );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::BeginBlockStructureElements()
|
|
*/
|
|
void SwTaggedPDFHelper::BeginBlockStructureElements()
|
|
{
|
|
const SwFrm* pFrm = &mpFrmInfo->mrFrm;
|
|
|
|
//
|
|
// Lowers of NonStructureElements should not be considered:
|
|
//
|
|
if ( lcl_IsInNonStructEnv( *pFrm ) )
|
|
return;
|
|
|
|
// Check if we have to reopen an existing structure element.
|
|
// This has to be done e.g., if pFrm is a follow frame.
|
|
if ( CheckReopenTag() )
|
|
return;
|
|
|
|
USHORT nPDFType = USHRT_MAX;
|
|
String aPDFType;
|
|
|
|
switch ( pFrm->GetType() )
|
|
{
|
|
/*
|
|
* GROUPING ELEMENTS
|
|
*/
|
|
|
|
case FRM_PAGE :
|
|
//
|
|
// Document: Document
|
|
//
|
|
nPDFType = vcl::PDFWriter::Document;
|
|
aPDFType = aDocumentString;
|
|
break;
|
|
|
|
case FRM_HEADER :
|
|
case FRM_FOOTER :
|
|
//
|
|
// Header, Footer: NonStructElement
|
|
//
|
|
nPDFType = vcl::PDFWriter::NonStructElement;
|
|
break;
|
|
|
|
case FRM_FTNCONT :
|
|
//
|
|
// Footnote container: Division
|
|
//
|
|
nPDFType = vcl::PDFWriter::Division;
|
|
aPDFType = aDivString;
|
|
break;
|
|
|
|
case FRM_FTN :
|
|
//
|
|
// Footnote frame: Note
|
|
//
|
|
// Note: vcl::PDFWriter::Note is actually a ILSE. Nevertheless
|
|
// we treat it like a grouping element!
|
|
nPDFType = vcl::PDFWriter::Note;
|
|
aPDFType = aNoteString;
|
|
break;
|
|
|
|
case FRM_SECTION :
|
|
//
|
|
// Section: TOX, Index, or Sect
|
|
//
|
|
{
|
|
const SwSection* pSection =
|
|
static_cast<const SwSectionFrm*>(pFrm)->GetSection();
|
|
if ( TOX_CONTENT_SECTION == pSection->GetType() )
|
|
{
|
|
const SwTOXBase* pTOXBase = pSection->GetTOXBase();
|
|
if ( pTOXBase )
|
|
{
|
|
if ( TOX_INDEX == pTOXBase->GetType() )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Index;
|
|
aPDFType = aIndexString;
|
|
}
|
|
else
|
|
{
|
|
nPDFType = vcl::PDFWriter::TOC;
|
|
aPDFType = aTOCString;
|
|
}
|
|
}
|
|
}
|
|
else if ( CONTENT_SECTION == pSection->GetType() )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Section;
|
|
aPDFType = aSectString;
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* BLOCK-LEVEL STRUCTURE ELEMENTS
|
|
*/
|
|
|
|
case FRM_TXT :
|
|
{
|
|
const SwTxtNode* pTxtNd =
|
|
static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
|
|
|
|
const SwFmt* pTxtFmt = pTxtNd->GetFmtColl();
|
|
const SwFmt* pParentTxtFmt = pTxtFmt->DerivedFrom();
|
|
|
|
String sStyleName;
|
|
String sParentStyleName;
|
|
|
|
if ( pTxtFmt)
|
|
SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
|
|
if ( pParentTxtFmt)
|
|
SwStyleNameMapper::FillProgName( pParentTxtFmt->GetName(), sParentStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
|
|
|
|
// This is the default. If the paragraph could not be mapped to
|
|
// any of the standard pdf tags, we write a user defined tag
|
|
// <stylename> with role = P
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::Paragraph);
|
|
aPDFType = sStyleName;
|
|
|
|
//
|
|
// Quotations: BlockQuote
|
|
//
|
|
if ( sStyleName == aQuotations )
|
|
{
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::BlockQuote);
|
|
aPDFType = aBlockQuoteString;
|
|
}
|
|
|
|
//
|
|
// Caption: Caption
|
|
//
|
|
else if ( sStyleName == aCaption)
|
|
{
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::Caption);
|
|
aPDFType = aCaptionString;
|
|
}
|
|
|
|
//
|
|
// Caption: Caption
|
|
//
|
|
else if ( sParentStyleName == aCaption)
|
|
{
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::Caption);
|
|
aPDFType = sStyleName.Append(aCaptionString);
|
|
}
|
|
|
|
//
|
|
// Heading: H
|
|
//
|
|
else if ( sStyleName == aHeading )
|
|
{
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::Heading);
|
|
aPDFType = aHString;
|
|
}
|
|
|
|
//
|
|
// Heading: H1 - H6
|
|
//
|
|
if ( pTxtNd->IsOutline() )
|
|
{
|
|
//int nRealLevel = pTxtNd->GetOutlineLevel(); //#outline level,zhaojianwei
|
|
int nRealLevel = pTxtNd->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
|
|
nRealLevel = nRealLevel > 5 ? 5 : nRealLevel;
|
|
|
|
nPDFType = static_cast<USHORT>(vcl::PDFWriter::H1 + nRealLevel);
|
|
switch(nRealLevel)
|
|
{
|
|
case 0 :
|
|
aPDFType = aH1String;
|
|
break;
|
|
case 1 :
|
|
aPDFType = aH2String;
|
|
break;
|
|
case 2 :
|
|
aPDFType = aH3String;
|
|
break;
|
|
case 3 :
|
|
aPDFType = aH4String;
|
|
break;
|
|
case 4 :
|
|
aPDFType = aH5String;
|
|
break;
|
|
default:
|
|
aPDFType = aH6String;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Section: TOCI
|
|
//
|
|
else if ( pFrm->IsInSct() )
|
|
{
|
|
const SwSectionFrm* pSctFrm = pFrm->FindSctFrm();
|
|
const SwSection* pSection =
|
|
static_cast<const SwSectionFrm*>(pSctFrm)->GetSection();
|
|
|
|
if ( TOX_CONTENT_SECTION == pSection->GetType() )
|
|
{
|
|
const SwTOXBase* pTOXBase = pSection->GetTOXBase();
|
|
if ( pTOXBase && TOX_INDEX != pTOXBase->GetType() )
|
|
{
|
|
// Special case: Open additional TOCI tag:
|
|
BeginTag( vcl::PDFWriter::TOCI, aTOCIString );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FRM_TAB :
|
|
//
|
|
// TabFrm: Table
|
|
//
|
|
nPDFType = vcl::PDFWriter::Table;
|
|
aPDFType = aTableString;
|
|
|
|
{
|
|
// set up table column data:
|
|
const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>(pFrm);
|
|
const SwTable* pTable = pTabFrm->GetTable();
|
|
|
|
TableColumnsMap& rTableColumnsMap = SwEnhancedPDFExportHelper::GetTableColumnsMap();
|
|
const TableColumnsMap::const_iterator aIter = rTableColumnsMap.find( pTable );
|
|
|
|
if ( aIter == rTableColumnsMap.end() )
|
|
{
|
|
SWRECTFN( pTabFrm )
|
|
TableColumnsMapEntry& rCols = rTableColumnsMap[ pTable ];
|
|
|
|
const SwTabFrm* pMasterFrm = pTabFrm->IsFollow() ? pTabFrm->FindMaster( true ) : pTabFrm;
|
|
|
|
while ( pMasterFrm )
|
|
{
|
|
const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pMasterFrm->GetLower());
|
|
|
|
while ( pRowFrm )
|
|
{
|
|
const SwFrm* pCellFrm = pRowFrm->GetLower();
|
|
|
|
const long nLeft = (pCellFrm->Frm().*fnRect->fnGetLeft)();
|
|
rCols.insert( nLeft );
|
|
|
|
while ( pCellFrm )
|
|
{
|
|
const long nRight = (pCellFrm->Frm().*fnRect->fnGetRight)();
|
|
rCols.insert( nRight );
|
|
pCellFrm = pCellFrm->GetNext();
|
|
}
|
|
pRowFrm = static_cast<const SwRowFrm*>(pRowFrm->GetNext());
|
|
}
|
|
pMasterFrm = static_cast<const SwTabFrm*>(pMasterFrm->GetFollow());
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
/*
|
|
* TABLE ELEMENTS
|
|
*/
|
|
|
|
case FRM_ROW :
|
|
//
|
|
// RowFrm: TR
|
|
//
|
|
if ( !static_cast<const SwRowFrm*>(pFrm)->IsRepeatedHeadline() )
|
|
{
|
|
nPDFType = vcl::PDFWriter::TableRow;
|
|
aPDFType = aTRString;
|
|
}
|
|
else
|
|
{
|
|
nPDFType = vcl::PDFWriter::NonStructElement;
|
|
}
|
|
break;
|
|
|
|
case FRM_CELL :
|
|
//
|
|
// CellFrm: TH, TD
|
|
//
|
|
{
|
|
const SwTabFrm* pTable = static_cast<const SwCellFrm*>(pFrm)->FindTabFrm();
|
|
if ( pTable->IsInHeadline( *pFrm ) || lcl_IsHeadlineCell( *static_cast<const SwCellFrm*>(pFrm) ) )
|
|
{
|
|
nPDFType = vcl::PDFWriter::TableHeader;
|
|
aPDFType = aTHString;
|
|
}
|
|
else
|
|
{
|
|
nPDFType = vcl::PDFWriter::TableData;
|
|
aPDFType = aTDString;
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* ILLUSTRATION
|
|
*/
|
|
|
|
case FRM_FLY :
|
|
//
|
|
// FlyFrm: Figure, Formula, Control
|
|
// fly in content or fly at page
|
|
{
|
|
bool bFormula = false;
|
|
const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pFrm);
|
|
if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
|
|
{
|
|
const SwNoTxtFrm* pNoTxtFrm = static_cast<const SwNoTxtFrm*>(pFly->Lower());
|
|
SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTxtFrm->GetNode()->GetOLENode());
|
|
if ( pOLENd )
|
|
{
|
|
SwOLEObj& aOLEObj = pOLENd->GetOLEObj();
|
|
uno::Reference< embed::XEmbeddedObject > aRef = aOLEObj.GetOleRef();
|
|
if ( aRef.is() )
|
|
{
|
|
bFormula = 0 != SotExchange::IsMath( SvGlobalName( aRef->getClassID() ) );
|
|
}
|
|
}
|
|
if ( bFormula )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Formula;
|
|
aPDFType = aFormulaString;
|
|
}
|
|
else
|
|
{
|
|
nPDFType = vcl::PDFWriter::Figure;
|
|
aPDFType = aFigureString;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nPDFType = vcl::PDFWriter::Division;
|
|
aPDFType = aDivString;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( USHRT_MAX != nPDFType )
|
|
{
|
|
BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::EndStructureElements()
|
|
*/
|
|
void SwTaggedPDFHelper::EndStructureElements()
|
|
{
|
|
while ( nEndStructureElement > 0 )
|
|
{
|
|
EndTag();
|
|
--nEndStructureElement;
|
|
}
|
|
|
|
CheckRestoreTag();
|
|
}
|
|
|
|
|
|
/*
|
|
* SwTaggedPDFHelper::BeginInlineStructureElements()
|
|
*/
|
|
void SwTaggedPDFHelper::BeginInlineStructureElements()
|
|
{
|
|
const SwLinePortion* pPor = &mpPorInfo->mrPor;
|
|
const SwTxtPaintInfo& rInf = mpPorInfo->mrTxtPainter.GetInfo();
|
|
const SwTxtFrm* pFrm = rInf.GetTxtFrm();
|
|
|
|
//
|
|
// Lowers of NonStructureElements should not be considered:
|
|
//
|
|
if ( lcl_IsInNonStructEnv( *pFrm ) )
|
|
return;
|
|
|
|
USHORT nPDFType = USHRT_MAX;
|
|
String aPDFType;
|
|
|
|
switch ( pPor->GetWhichPor() )
|
|
{
|
|
// Check for alternative spelling:
|
|
case POR_HYPHSTR :
|
|
case POR_SOFTHYPHSTR :
|
|
nPDFType = vcl::PDFWriter::Span;
|
|
aPDFType = aSpanString;
|
|
break;
|
|
|
|
case POR_LAY :
|
|
case POR_TXT :
|
|
case POR_PARA :
|
|
{
|
|
SwTxtNode* pNd = (SwTxtNode*)pFrm->GetTxtNode();
|
|
SwIndex aIndex( pNd, rInf.GetIdx() );
|
|
const SwTxtAttr* pInetFmtAttr = pNd->GetTxtAttr( aIndex, RES_TXTATR_INETFMT );
|
|
|
|
String sStyleName;
|
|
if ( !pInetFmtAttr )
|
|
{
|
|
const SwTxtAttr* pCharFmtAttr = pNd->GetTxtAttr( aIndex, RES_TXTATR_CHARFMT );
|
|
const SwCharFmt* pCharFmt = pCharFmtAttr ? pCharFmtAttr->GetCharFmt().GetCharFmt() : 0;
|
|
if ( pCharFmt )
|
|
SwStyleNameMapper::FillProgName( pCharFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
|
|
}
|
|
|
|
// Check for Link:
|
|
if( pInetFmtAttr )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Link;
|
|
aPDFType = aLinkString;
|
|
}
|
|
// Check for Quote/Code character style:
|
|
else if ( sStyleName == aQuotation )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Quote;
|
|
aPDFType = aQuoteString;
|
|
}
|
|
else if ( sStyleName == aSourceText )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Code;
|
|
aPDFType = aCodeString;
|
|
}
|
|
else
|
|
{
|
|
const LanguageType nCurrentLanguage = rInf.GetFont()->GetLanguage();
|
|
const USHORT nFont = rInf.GetFont()->GetActual();
|
|
const LanguageType nDefaultLang = SwEnhancedPDFExportHelper::GetDefaultLanguage();
|
|
|
|
if ( UNDERLINE_NONE != rInf.GetFont()->GetUnderline() ||
|
|
UNDERLINE_NONE != rInf.GetFont()->GetOverline() ||
|
|
STRIKEOUT_NONE != rInf.GetFont()->GetStrikeout() ||
|
|
EMPHASISMARK_NONE != rInf.GetFont()->GetEmphasisMark() ||
|
|
0 != rInf.GetFont()->GetEscapement() ||
|
|
SW_LATIN != nFont ||
|
|
nCurrentLanguage != nDefaultLang ||
|
|
sStyleName.Len() > 0 )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Span;
|
|
if ( sStyleName.Len() > 0 )
|
|
aPDFType = sStyleName;
|
|
else
|
|
aPDFType = aSpanString;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POR_FTN :
|
|
nPDFType = vcl::PDFWriter::Link;
|
|
aPDFType = aLinkString;
|
|
break;
|
|
|
|
case POR_FLD :
|
|
{
|
|
// check field type:
|
|
const xub_StrLen nIdx = static_cast<const SwFldPortion*>(pPor)->IsFollow() ?
|
|
rInf.GetIdx() - 1 :
|
|
rInf.GetIdx();
|
|
const SwTxtAttr* pHint = mpPorInfo->mrTxtPainter.GetAttr( nIdx );
|
|
const SwField* pFld = 0;
|
|
if ( pHint && RES_TXTATR_FIELD == pHint->Which() )
|
|
{
|
|
pFld = (SwField*)pHint->GetFld().GetFld();
|
|
if ( RES_GETREFFLD == pFld->Which() )
|
|
{
|
|
nPDFType = vcl::PDFWriter::Link;
|
|
aPDFType = aLinkString;
|
|
}
|
|
else if ( RES_AUTHORITY == pFld->Which() )
|
|
{
|
|
nPDFType = vcl::PDFWriter::BibEntry;
|
|
aPDFType = aBibEntryString;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POR_TAB :
|
|
case POR_TABRIGHT :
|
|
case POR_TABCENTER :
|
|
case POR_TABDECIMAL :
|
|
nPDFType = vcl::PDFWriter::NonStructElement;
|
|
break;
|
|
}
|
|
|
|
if ( USHRT_MAX != nPDFType )
|
|
{
|
|
BeginTag( static_cast<vcl::PDFWriter::StructElement>(nPDFType), aPDFType );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* static SwTaggedPDFHelper::IsExportTaggedPDF
|
|
*/
|
|
bool SwTaggedPDFHelper::IsExportTaggedPDF( const OutputDevice& rOut )
|
|
{
|
|
vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
|
|
return pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF();
|
|
}
|
|
|
|
/*
|
|
* SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper()
|
|
*/
|
|
SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper( SwEditShell& rSh,
|
|
OutputDevice& rOut,
|
|
const rtl::OUString& rPageRange,
|
|
bool bSkipEmptyPages,
|
|
bool bEditEngineOnly )
|
|
: mrSh( rSh ),
|
|
mrOut( rOut ),
|
|
pPageRange( 0 ),
|
|
mbSkipEmptyPages( bSkipEmptyPages ),
|
|
mbEditEngineOnly( bEditEngineOnly )
|
|
{
|
|
if ( rPageRange.getLength() )
|
|
pPageRange = new MultiSelection( rPageRange );
|
|
|
|
aTableColumnsMap.clear();
|
|
aLinkIdMap.clear();
|
|
aNumListIdMap.clear();
|
|
aNumListBodyIdMap.clear();
|
|
aFrmTagIdMap.clear();
|
|
|
|
#ifndef PRODUCT
|
|
aStructStack.clear();
|
|
#endif
|
|
|
|
const BYTE nScript = (BYTE)GetI18NScriptTypeOfLanguage( (USHORT)GetAppLanguage() );
|
|
USHORT nLangRes = RES_CHRATR_LANGUAGE;
|
|
|
|
if ( i18n::ScriptType::ASIAN == nScript )
|
|
nLangRes = RES_CHRATR_CJK_LANGUAGE;
|
|
else if ( i18n::ScriptType::COMPLEX == nScript )
|
|
nLangRes = RES_CHRATR_CTL_LANGUAGE;
|
|
|
|
eLanguageDefault = static_cast<const SvxLanguageItem*>(&mrSh.GetDoc()->GetDefault( nLangRes ))->GetLanguage();
|
|
|
|
EnhancedPDFExport();
|
|
}
|
|
|
|
SwEnhancedPDFExportHelper::~SwEnhancedPDFExportHelper()
|
|
{
|
|
delete pPageRange;
|
|
}
|
|
|
|
/*
|
|
* SwEnhancedPDFExportHelper::EnhancedPDFExport()
|
|
*/
|
|
void SwEnhancedPDFExportHelper::EnhancedPDFExport()
|
|
{
|
|
vcl::PDFExtOutDevData* pPDFExtOutDevData =
|
|
PTR_CAST( vcl::PDFExtOutDevData, mrOut.GetExtOutDevData() );
|
|
|
|
if ( !pPDFExtOutDevData )
|
|
return;
|
|
|
|
//
|
|
// set the document locale
|
|
//
|
|
com::sun::star::lang::Locale aDocLocale = MsLangId::convertLanguageToLocale( SwEnhancedPDFExportHelper::GetDefaultLanguage() );
|
|
pPDFExtOutDevData->SetDocumentLocale( aDocLocale );
|
|
|
|
//
|
|
// Prepare the output device:
|
|
//
|
|
mrOut.Push( PUSH_MAPMODE );
|
|
MapMode aMapMode( mrOut.GetMapMode() );
|
|
aMapMode.SetMapUnit( MAP_TWIP );
|
|
mrOut.SetMapMode( aMapMode );
|
|
|
|
//
|
|
// Create new cursor and lock the view:
|
|
//
|
|
SwDoc* pDoc = mrSh.GetDoc();
|
|
mrSh.SwCrsrShell::Push();
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
const BOOL bOldLockView = mrSh.IsViewLocked();
|
|
mrSh.LockView( TRUE );
|
|
|
|
if ( !mbEditEngineOnly )
|
|
{
|
|
//
|
|
// POSTITS
|
|
//
|
|
if ( pPDFExtOutDevData->GetIsExportNotes() )
|
|
{
|
|
SwFieldType* pType = mrSh.GetFldType( RES_POSTITFLD, aEmptyStr );
|
|
SwClientIter aIter( *pType );
|
|
const SwClient * pFirst = aIter.GoStart();
|
|
while( pFirst )
|
|
{
|
|
if( ((SwFmtFld*)pFirst)->GetTxtFld() &&
|
|
((SwFmtFld*)pFirst)->IsFldInDoc())
|
|
{
|
|
const SwTxtNode* pTNd =
|
|
(SwTxtNode*)((SwFmtFld*)pFirst)->GetTxtFld()->GetpTxtNode();
|
|
ASSERT( 0 != pTNd, "Enhanced pdf export - text node is missing" )
|
|
|
|
// 1. Check if the whole paragraph is hidden
|
|
// 2. Move to the field
|
|
// 3. Check for hidden text attribute
|
|
if ( !pTNd->IsHidden() &&
|
|
mrSh.GotoFld( *(SwFmtFld*)pFirst ) &&
|
|
!mrSh.SelectHiddenRange() )
|
|
{
|
|
// Link Rectangle
|
|
const SwRect& rNoteRect = mrSh.GetCharRect();
|
|
|
|
// Link PageNum
|
|
const sal_Int32 nNotePageNum = CalcOutputPageNum( rNoteRect );
|
|
if ( -1 != nNotePageNum )
|
|
{
|
|
// Link Note
|
|
vcl::PDFNote aNote;
|
|
|
|
// Use the NumberFormatter to get the date string:
|
|
const SwPostItField* pField = (SwPostItField*)((SwFmtFld*)pFirst)->GetFld();
|
|
SvNumberFormatter* pNumFormatter = pDoc->GetNumberFormatter();
|
|
const Date aDateDiff( pField->GetDate() -
|
|
*pNumFormatter->GetNullDate() );
|
|
const ULONG nFormat =
|
|
pNumFormatter->GetStandardFormat( NUMBERFORMAT_DATE, pField->GetLanguage() );
|
|
String sDate;
|
|
Color* pColor;
|
|
pNumFormatter->GetOutputString( aDateDiff.GetDate(), nFormat, sDate, &pColor );
|
|
|
|
// The title should consist of the author and the date:
|
|
String sTitle( pField->GetPar1() );
|
|
sTitle.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
|
|
sTitle += sDate;
|
|
aNote.Title = sTitle;
|
|
// Guess what the contents contains...
|
|
aNote.Contents = pField->GetTxt();
|
|
|
|
// Link Export
|
|
pPDFExtOutDevData->CreateNote( rNoteRect.SVRect(), aNote, nNotePageNum );
|
|
}
|
|
}
|
|
}
|
|
pFirst = aIter++;
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
}
|
|
}
|
|
|
|
//
|
|
// HYPERLINKS
|
|
//
|
|
SwGetINetAttrs aArr;
|
|
const sal_uInt16 nHyperLinkCount = mrSh.GetINetAttrs( aArr );
|
|
for( sal_uInt16 n = 0; n < nHyperLinkCount; ++n )
|
|
{
|
|
SwGetINetAttr* p = aArr[ n ];
|
|
ASSERT( 0 != p, "Enhanced pdf export - SwGetINetAttr is missing" )
|
|
|
|
const SwTxtNode* pTNd = p->rINetAttr.GetpTxtNode();
|
|
ASSERT( 0 != pTNd, "Enhanced pdf export - text node is missing" )
|
|
|
|
// 1. Check if the whole paragraph is hidden
|
|
// 2. Move to the hyperlink
|
|
// 3. Check for hidden text attribute
|
|
if ( !pTNd->IsHidden() &&
|
|
mrSh.GotoINetAttr( p->rINetAttr ) &&
|
|
!mrSh.SelectHiddenRange() )
|
|
{
|
|
// Select the hyperlink:
|
|
mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
|
|
if ( mrSh.SwCrsrShell::SelectTxtAttr( RES_TXTATR_INETFMT, sal_True ) )
|
|
{
|
|
// First, we create the destination, because there may be more
|
|
// than one link to this destination:
|
|
String aURL( INetURLObject::decode(
|
|
p->rINetAttr.GetINetFmt().GetValue(),
|
|
INET_HEX_ESCAPE,
|
|
INetURLObject::DECODE_UNAMBIGUOUS,
|
|
RTL_TEXTENCODING_UTF8 ) );
|
|
|
|
// We have to distinguish between intern and real URLs
|
|
const bool bIntern = '#' == aURL.GetChar( 0 );
|
|
|
|
// _GetCrsr() is a SwShellCrsr, which is derived from
|
|
// SwSelPaintRects, therefore the rectangles of the current
|
|
// selection can be easily obtained:
|
|
// Note: We make a copy of the rectangles, because they may
|
|
// be deleted again in JumpToSwMark.
|
|
SwRects aTmp;
|
|
aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
|
|
ASSERT( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" )
|
|
|
|
// Create the destination for internal links:
|
|
sal_Int32 nDestId = -1;
|
|
if ( bIntern )
|
|
{
|
|
aURL.Erase( 0, 1 );
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
JumpToSwMark( &mrSh, aURL );
|
|
|
|
// Destination Rectangle
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
// Destination Export
|
|
if ( -1 != nDestPageNum )
|
|
nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
}
|
|
|
|
if ( !bIntern || -1 != nDestId )
|
|
{
|
|
// --> FME 2005-05-09 #i44368# Links in Header/Footer
|
|
const SwPosition aPos( *pTNd );
|
|
const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
|
|
// <--
|
|
|
|
// Create links for all selected rectangles:
|
|
const USHORT nNumOfRects = aTmp.Count();
|
|
for ( USHORT i = 0; i < nNumOfRects; ++i )
|
|
{
|
|
// Link Rectangle
|
|
const SwRect& rLinkRect( aTmp[ i ] );
|
|
|
|
// Link PageNum
|
|
const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
|
|
|
|
if ( -1 != nLinkPageNum )
|
|
{
|
|
// Link Export
|
|
const sal_Int32 nLinkId =
|
|
pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), nLinkPageNum );
|
|
|
|
// Store link info for tagged pdf output:
|
|
const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
|
|
aLinkIdMap.push_back( aLinkEntry );
|
|
|
|
// Connect Link and Destination:
|
|
if ( bIntern )
|
|
pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
|
|
else
|
|
pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
|
|
|
|
// --> FME 2005-05-09 #i44368# Links in Header/Footer
|
|
if ( bHeaderFooter )
|
|
MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aURL, bIntern );
|
|
// <--
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
}
|
|
|
|
//
|
|
// HYPERLINKS (Graphics, Frames, OLEs )
|
|
//
|
|
const SwSpzFrmFmts* pTbl = pDoc->GetSpzFrmFmts();
|
|
const sal_uInt16 nSpzFrmFmtsCount = pTbl->Count();
|
|
for( sal_uInt16 n = 0; n < nSpzFrmFmtsCount; ++n )
|
|
{
|
|
const SwFrmFmt* pFrmFmt = (*pTbl)[n];
|
|
const SfxPoolItem* pItem;
|
|
if ( RES_DRAWFRMFMT != pFrmFmt->Which() &&
|
|
SFX_ITEM_SET == pFrmFmt->GetAttrSet().GetItemState( RES_URL, TRUE, &pItem ) )
|
|
{
|
|
String aURL( static_cast<const SwFmtURL*>(pItem)->GetURL() );
|
|
const bool bIntern = '#' == aURL.GetChar( 0 );
|
|
|
|
// Create the destination for internal links:
|
|
sal_Int32 nDestId = -1;
|
|
if ( bIntern )
|
|
{
|
|
aURL.Erase( 0, 1 );
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
JumpToSwMark( &mrSh, aURL );
|
|
|
|
// Destination Rectangle
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
// Destination Export
|
|
if ( -1 != nDestPageNum )
|
|
nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
}
|
|
|
|
if ( !bIntern || -1 != nDestId )
|
|
{
|
|
Point aNullPt;
|
|
const SwRect aLinkRect = pFrmFmt->FindLayoutRect( sal_False, &aNullPt );
|
|
|
|
// Link PageNum
|
|
const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
|
|
|
|
// Link Export
|
|
if ( -1 != nLinkPageNum )
|
|
{
|
|
const sal_Int32 nLinkId =
|
|
pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), nLinkPageNum );
|
|
|
|
// Connect Link and Destination:
|
|
if ( bIntern )
|
|
pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
|
|
else
|
|
pPDFExtOutDevData->SetLinkURL( nLinkId, aURL );
|
|
|
|
// --> FME 2005-05-09 #i44368# Links in Header/Footer
|
|
const SwFmtAnchor &rAnch = pFrmFmt->GetAnchor();
|
|
if ( FLY_PAGE != rAnch.GetAnchorId() )
|
|
{
|
|
const SwPosition* pPosition = rAnch.GetCntntAnchor();
|
|
if ( pPosition && pDoc->IsInHeaderFooter( pPosition->nNode ) )
|
|
{
|
|
const SwTxtNode* pTNd = pPosition->nNode.GetNode().GetTxtNode();
|
|
if ( pTNd )
|
|
MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern );
|
|
}
|
|
}
|
|
// <--
|
|
}
|
|
}
|
|
}
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
}
|
|
|
|
//
|
|
// REFERENCES
|
|
//
|
|
SwFieldType* pType = mrSh.GetFldType( RES_GETREFFLD, aEmptyStr );
|
|
SwClientIter aIter( *pType );
|
|
const SwClient * pFirst = aIter.GoStart();
|
|
while( pFirst )
|
|
{
|
|
if( ((SwFmtFld*)pFirst)->GetTxtFld() &&
|
|
((SwFmtFld*)pFirst)->IsFldInDoc())
|
|
{
|
|
const SwTxtNode* pTNd =
|
|
(SwTxtNode*)((SwFmtFld*)pFirst)->GetTxtFld()->GetpTxtNode();
|
|
ASSERT( 0 != pTNd, "Enhanced pdf export - text node is missing" )
|
|
|
|
// 1. Check if the whole paragraph is hidden
|
|
// 2. Move to the field
|
|
// 3. Check for hidden text attribute
|
|
if ( !pTNd->IsHidden() &&
|
|
mrSh.GotoFld( *(SwFmtFld*)pFirst ) &&
|
|
!mrSh.SelectHiddenRange() )
|
|
{
|
|
// Select the field:
|
|
mrSh.SwCrsrShell::SetMark();
|
|
mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
|
|
|
|
// Link Rectangles
|
|
SwRects aTmp;
|
|
aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
|
|
ASSERT( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" )
|
|
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
|
|
// Destination Rectangle
|
|
const SwGetRefField* pField =
|
|
(SwGetRefField*)((SwFmtFld*)pFirst)->GetFld();
|
|
const String& rRefName = pField->GetSetRefName();
|
|
mrSh.GotoRefMark( rRefName, pField->GetSubType(), pField->GetSeqNo() );
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
if ( -1 != nDestPageNum )
|
|
{
|
|
// Destination Export
|
|
const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
|
|
// --> FME 2005-05-09 #i44368# Links in Header/Footer
|
|
const SwPosition aPos( *pTNd );
|
|
const bool bHeaderFooter = pDoc->IsInHeaderFooter( aPos.nNode );
|
|
// <--
|
|
|
|
// Create links for all selected rectangles:
|
|
const USHORT nNumOfRects = aTmp.Count();
|
|
for ( USHORT i = 0; i < nNumOfRects; ++i )
|
|
{
|
|
// Link rectangle
|
|
const SwRect& rLinkRect( aTmp[ i ] );
|
|
|
|
// Link PageNum
|
|
const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
|
|
|
|
if ( -1 != nLinkPageNum )
|
|
{
|
|
// Link Export
|
|
const sal_Int32 nLinkId =
|
|
pPDFExtOutDevData->CreateLink( rLinkRect.SVRect(), nLinkPageNum );
|
|
|
|
// Store link info for tagged pdf output:
|
|
const IdMapEntry aLinkEntry( rLinkRect, nLinkId );
|
|
aLinkIdMap.push_back( aLinkEntry );
|
|
|
|
// Connect Link and Destination:
|
|
pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
|
|
|
|
// --> FME 2005-05-09 #i44368# Links in Header/Footer
|
|
if ( bHeaderFooter )
|
|
{
|
|
const String aDummy;
|
|
MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, rLinkRect, nDestId, aDummy, true );
|
|
}
|
|
// <--
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pFirst = aIter++;
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
}
|
|
|
|
//
|
|
// FOOTNOTES
|
|
//
|
|
const USHORT nFtnCount = pDoc->GetFtnIdxs().Count();
|
|
for ( USHORT nIdx = 0; nIdx < nFtnCount; ++nIdx )
|
|
{
|
|
// Set cursor to text node that contains the footnote:
|
|
const SwTxtFtn* pTxtFtn = pDoc->GetFtnIdxs()[ nIdx ];
|
|
SwTxtNode& rTNd = const_cast<SwTxtNode&>(pTxtFtn->GetTxtNode());
|
|
|
|
mrSh._GetCrsr()->GetPoint()->nNode = rTNd;
|
|
mrSh._GetCrsr()->GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
|
|
|
|
// 1. Check if the whole paragraph is hidden
|
|
// 2. Check for hidden text attribute
|
|
if ( static_cast<const SwTxtNode&>(rTNd).IsHidden() ||
|
|
mrSh.SelectHiddenRange() )
|
|
continue;
|
|
|
|
SwCrsrSaveState aSaveState( *mrSh._GetCrsr() );
|
|
|
|
// Select the footnote:
|
|
mrSh.SwCrsrShell::SetMark();
|
|
mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
|
|
|
|
// Link Rectangle
|
|
SwRects aTmp;
|
|
aTmp.Insert( mrSh.SwCrsrShell::_GetCrsr(), 0 );
|
|
ASSERT( aTmp.Count() > 0, "Enhanced pdf export - rectangles are missing" )
|
|
const SwRect aLinkRect( aTmp[ 0 ] );
|
|
|
|
mrSh._GetCrsr()->RestoreSavePos();
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
|
|
// Goto footnote text:
|
|
if ( mrSh.GotoFtnTxt() )
|
|
{
|
|
// Link PageNum
|
|
const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
|
|
|
|
if ( -1 != nLinkPageNum )
|
|
{
|
|
// Link Export
|
|
const sal_Int32 nLinkId =
|
|
pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), nLinkPageNum );
|
|
|
|
// Store link info for tagged pdf output:
|
|
const IdMapEntry aLinkEntry( aLinkRect, nLinkId );
|
|
aLinkIdMap.push_back( aLinkEntry );
|
|
|
|
// Destination Rectangle
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
if ( -1 != nDestPageNum )
|
|
{
|
|
// Destination Export
|
|
const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
|
|
// Connect Link and Destination:
|
|
pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// OUTLINE
|
|
//
|
|
if( pPDFExtOutDevData->GetIsExportBookmarks() )
|
|
{
|
|
typedef std::pair< sal_Int8, sal_Int32 > StackEntry;
|
|
std::stack< StackEntry > aOutlineStack;
|
|
aOutlineStack.push( StackEntry( -1, -1 ) ); // push default value
|
|
|
|
const sal_uInt16 nOutlineCount =
|
|
static_cast<sal_uInt16>(mrSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount());
|
|
for ( sal_uInt16 i = 0; i < nOutlineCount; ++i )
|
|
{
|
|
// Check if outline is hidden
|
|
const SwTxtNode* pTNd = mrSh.GetNodes().GetOutLineNds()[ i ]->GetTxtNode();
|
|
ASSERT( 0 != pTNd, "Enhanced pdf export - text node is missing" )
|
|
|
|
if ( pTNd->IsHidden() ||
|
|
// --> FME 2005-01-10 #i40292# Skip empty outlines:
|
|
0 == pTNd->GetTxt().Len() )
|
|
// <--
|
|
continue;
|
|
|
|
// Get parent id from stack:
|
|
const sal_Int8 nLevel = (sal_Int8)mrSh.getIDocumentOutlineNodesAccess()->getOutlineLevel( i );
|
|
sal_Int8 nLevelOnTopOfStack = aOutlineStack.top().first;
|
|
while ( nLevelOnTopOfStack >= nLevel &&
|
|
nLevelOnTopOfStack != -1 )
|
|
{
|
|
aOutlineStack.pop();
|
|
nLevelOnTopOfStack = aOutlineStack.top().first;
|
|
}
|
|
const sal_Int32 nParent = aOutlineStack.top().second;
|
|
|
|
// Destination rectangle
|
|
mrSh.GotoOutline(i);
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
if ( -1 != nDestPageNum )
|
|
{
|
|
// Destination Export
|
|
const sal_Int32 nDestId =
|
|
pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
|
|
// Outline entry text
|
|
const String& rEntry = mrSh.getIDocumentOutlineNodesAccess()->getOutlineText( i );
|
|
|
|
// Create a new outline item:
|
|
const sal_Int32 nOutlineId =
|
|
pPDFExtOutDevData->CreateOutlineItem( nParent, rEntry, nDestId );
|
|
|
|
// Push current level and nOutlineId on stack:
|
|
aOutlineStack.push( StackEntry( nLevel, nOutlineId ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pPDFExtOutDevData->GetIsExportNamedDestinations() )
|
|
{
|
|
//---> i56629 the iteration to convert the OOo bookmark (#bookmark)
|
|
// into PDF named destination, see section 8.2.1 in PDF 1.4 spec
|
|
// We need:
|
|
// 1. a name for the destination, formed from the standard OOo bookmark name
|
|
// 2. the destination, obtained from where the bookmark destination lies
|
|
const SwBookmarks& rBkmks = mrSh.GetDoc()->getBookmarks();
|
|
//iterate trhrough bookmarks
|
|
sal_uInt16 nBkmks = rBkmks.Count(), nCnt;
|
|
for(nCnt = 0; nCnt < nBkmks; nCnt++)
|
|
{
|
|
//get the name
|
|
SwBookmark* pBkmk = rBkmks[ nCnt ];
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
rtl::OUString sBkName = pBkmk->GetName();
|
|
//jump to it
|
|
JumpToSwMark( &mrSh, sBkName );
|
|
|
|
// Destination Rectangle
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
// Destination Export
|
|
if ( -1 != nDestPageNum )
|
|
pPDFExtOutDevData->CreateNamedDest( sBkName, rDestRect.SVRect(), nDestPageNum );
|
|
}
|
|
mrSh.SwCrsrShell::ClearMark();
|
|
}
|
|
//<--- i56629
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// LINKS FROM EDITENGINE
|
|
//
|
|
std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
|
|
std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIBeg = rBookmarks.begin();
|
|
const std::vector< vcl::PDFExtOutDevBookmarkEntry >::const_iterator aIEnd = rBookmarks.end();
|
|
while ( aIBeg != aIEnd )
|
|
{
|
|
String aBookmarkName( aIBeg->aBookmark );
|
|
const bool bIntern = '#' == aBookmarkName.GetChar( 0 );
|
|
if ( bIntern )
|
|
{
|
|
aBookmarkName.Erase( 0, 1 );
|
|
JumpToSwMark( &mrSh, aBookmarkName );
|
|
|
|
// Destination Rectangle
|
|
const SwRect& rDestRect = mrSh.GetCharRect();
|
|
|
|
// Destination PageNum
|
|
const sal_Int32 nDestPageNum = CalcOutputPageNum( rDestRect );
|
|
|
|
if ( -1 != nDestPageNum )
|
|
{
|
|
// Destination Export
|
|
const sal_Int32 nDestId =
|
|
pPDFExtOutDevData->CreateDest( rDestRect.SVRect(), nDestPageNum );
|
|
|
|
// Connect Link and Destination:
|
|
pPDFExtOutDevData->SetLinkDest( aIBeg->nLinkId, nDestId );
|
|
}
|
|
}
|
|
else
|
|
pPDFExtOutDevData->SetLinkURL( aIBeg->nLinkId, aBookmarkName );
|
|
|
|
aIBeg++;
|
|
}
|
|
rBookmarks.clear();
|
|
}
|
|
|
|
// Restore view, cursor, and outdev:
|
|
mrSh.LockView( bOldLockView );
|
|
mrSh.SwCrsrShell::Pop( FALSE );
|
|
mrOut.Pop();
|
|
}
|
|
|
|
/*
|
|
* SwEnhancedPDFExportHelper::CalcOutputPageNum()
|
|
*/
|
|
sal_Int32 SwEnhancedPDFExportHelper::CalcOutputPageNum( const SwRect& rRect ) const
|
|
{
|
|
// Document page numbers are 0, 1, 2, ...
|
|
const sal_Int32 nPageNumOfRect = mrSh.GetPageNumAndSetOffsetForPDF( mrOut, rRect );
|
|
|
|
// Shortcut:
|
|
if ( -1 == nPageNumOfRect || ( !pPageRange && !mbSkipEmptyPages ) )
|
|
return nPageNumOfRect;
|
|
|
|
// pPageRange page numbers are 1, 2, 3, ...
|
|
if ( pPageRange && !pPageRange->IsSelected( nPageNumOfRect + 1 ) )
|
|
return -1;
|
|
|
|
// What will be the page number of page nPageNumOfRect in the output doc?
|
|
sal_Int32 nOutputPageNum = -1;
|
|
const SwRootFrm* pRootFrm = mrSh.GetLayout();
|
|
const SwPageFrm* pCurrPage = static_cast<const SwPageFrm*>(pRootFrm->Lower());
|
|
|
|
for ( sal_Int32 nPageIndex = 0;
|
|
nPageIndex <= nPageNumOfRect && pCurrPage;
|
|
++nPageIndex )
|
|
{
|
|
if ( ( !pPageRange || pPageRange->IsSelected( nPageIndex + 1 ) ) &&
|
|
( !mbSkipEmptyPages || !pCurrPage->IsEmptyPage() ) )
|
|
++nOutputPageNum;
|
|
|
|
pCurrPage = static_cast<const SwPageFrm*>(pCurrPage->GetNext());
|
|
}
|
|
|
|
// pdf export page numbers are 0, 1, 2, ...
|
|
return nOutputPageNum;
|
|
}
|
|
|
|
void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData& rPDFExtOutDevData,
|
|
const SwTxtNode& rTNd,
|
|
const SwRect& rLinkRect,
|
|
sal_Int32 nDestId,
|
|
const String& rURL,
|
|
bool bIntern ) const
|
|
{
|
|
// We assume, that the primary link has just been exported. Therefore
|
|
// the offset of the link rectangle calculates as follows:
|
|
const Point aOffset = rLinkRect.Pos() + mrOut.GetMapMode().GetOrigin();
|
|
|
|
SwClientIter aClientIter( const_cast<SwTxtNode&>(rTNd) );
|
|
SwClient* pLast = aClientIter.GoStart();
|
|
|
|
while( pLast )
|
|
{
|
|
if ( pLast->ISA( SwTxtFrm ) )
|
|
{
|
|
// Add offset to current page:
|
|
SwTxtFrm* pTmpFrm = static_cast<SwTxtFrm*>(pLast);
|
|
const SwPageFrm* pPageFrm = pTmpFrm->FindPageFrm();
|
|
SwRect aHFLinkRect( rLinkRect );
|
|
aHFLinkRect.Pos() = pPageFrm->Frm().Pos() + aOffset;
|
|
|
|
if ( aHFLinkRect != rLinkRect )
|
|
{
|
|
// Link PageNum
|
|
const sal_Int32 nHFLinkPageNum = CalcOutputPageNum( aHFLinkRect );
|
|
|
|
if ( -1 != nHFLinkPageNum )
|
|
{
|
|
// Link Export
|
|
const sal_Int32 nHFLinkId =
|
|
rPDFExtOutDevData.CreateLink( aHFLinkRect.SVRect(), nHFLinkPageNum );
|
|
|
|
// Connect Link and Destination:
|
|
if ( bIntern )
|
|
rPDFExtOutDevData.SetLinkDest( nHFLinkId, nDestId );
|
|
else
|
|
rPDFExtOutDevData.SetLinkURL( nHFLinkId, rURL );
|
|
}
|
|
}
|
|
}
|
|
|
|
pLast = ++aClientIter;
|
|
}
|
|
}
|
|
|