1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EnhancedPDFExportHelper.cxx,v $
10 * $Revision: 1.26.138.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <com/sun/star/embed/XEmbeddedObject.hpp>
34 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
35 #include <com/sun/star/i18n/ScriptType.hdl>
37 #include <EnhancedPDFExportHelper.hxx>
38 #include <hintids.hxx>
41 #include <vcl/outdev.hxx>
43 #include <tools/multisel.hxx>
44 #include <svx/adjitem.hxx>
45 #include <svx/lrspitem.hxx>
46 #include <svx/langitem.hxx>
47 #include <svx/scripttypeitem.hxx>
48 #include <tools/urlobj.hxx>
49 #include <svtools/zforlist.hxx>
50 #include <swatrset.hxx>
55 #include <section.hxx>
58 #include <txtinet.hxx>
59 #include <fmtinfmt.hxx>
60 #include <fchrfmt.hxx>
61 #include <charfmt.hxx>
62 #include <fmtanchr.hxx>
70 #include <crsskip.hxx>
72 #include <docufld.hxx>
76 #include <rootfrm.hxx>
77 #include <pagefrm.hxx>
81 #include <cellfrm.hxx>
82 #include <sectfrm.hxx>
84 #include <notxtfrm.hxx>
86 #include <SwStyleNameMapper.hxx>
87 #include <itrpaint.hxx>
88 #include "i18npool/mslangid.hxx"
90 #include <SwNodeNum.hxx>
94 #include <tools/globname.hxx>
96 using namespace ::com::sun::star
;
99 // Some static data structures
101 TableColumnsMap
SwEnhancedPDFExportHelper::aTableColumnsMap
;
102 LinkIdMap
SwEnhancedPDFExportHelper::aLinkIdMap
;
103 NumListIdMap
SwEnhancedPDFExportHelper::aNumListIdMap
;
104 NumListBodyIdMap
SwEnhancedPDFExportHelper::aNumListBodyIdMap
;
105 FrmTagIdMap
SwEnhancedPDFExportHelper::aFrmTagIdMap
;
107 LanguageType
SwEnhancedPDFExportHelper::eLanguageDefault
= 0;
111 static std::vector
< USHORT
> aStructStack
;
113 void lcl_DBGCheckStack()
115 /* NonStructElement = 0 Document = 1 Part = 2
116 * Article = 3 Section = 4 Division = 5
117 * BlockQuote = 6 Caption = 7 TOC = 8
118 * TOCI = 9 Index = 10 Paragraph = 11
119 * Heading = 12 H1-6 = 13 - 18 List = 19
120 * ListItem = 20 LILabel = 21 LIBody = 22
121 * Table = 23 TableRow = 24 TableHeader = 25
122 * TableData = 26 Span = 27 Quote = 28
123 * Note = 29 Reference = 30 BibEntry = 31
124 * Code = 32 Link = 33 Figure = 34
125 * Formula = 35 Form = 36 Continued frame = 99
129 std::vector
< USHORT
>::iterator aIter
;
130 for ( aIter
= aStructStack
.begin(); aIter
!= aStructStack
.end(); ++aIter
)
141 const String aTableHeadingName
= String::CreateFromAscii("Table Heading");
142 const String aQuotations
= String::CreateFromAscii("Quotations");
143 const String aCaption
= String::CreateFromAscii("Caption");
144 const String aHeading
= String::CreateFromAscii("Heading");
145 const String aQuotation
= String::CreateFromAscii("Quotation");
146 const String aSourceText
= String::CreateFromAscii("Source Text");
149 const String aDocumentString
= String::CreateFromAscii("Document");
150 const String aDivString
= String::CreateFromAscii("Div");
151 const String aSectString
= String::CreateFromAscii("Sect");
152 const String aHString
= String::CreateFromAscii("H");
153 const String aH1String
= String::CreateFromAscii("H1");
154 const String aH2String
= String::CreateFromAscii("H2");
155 const String aH3String
= String::CreateFromAscii("H3");
156 const String aH4String
= String::CreateFromAscii("H4");
157 const String aH5String
= String::CreateFromAscii("H5");
158 const String aH6String
= String::CreateFromAscii("H6");
159 const String aListString
= String::CreateFromAscii("L");
160 const String aListItemString
= String::CreateFromAscii("LI");
161 const String aListBodyString
= String::CreateFromAscii("LBody");
162 const String aBlockQuoteString
= String::CreateFromAscii("BlockQuote");
163 const String aCaptionString
= String::CreateFromAscii("Caption");
164 const String aIndexString
= String::CreateFromAscii("Index");
165 const String aTOCString
= String::CreateFromAscii("TOC");
166 const String aTOCIString
= String::CreateFromAscii("TOCI");
167 const String aTableString
= String::CreateFromAscii("Table");
168 const String aTRString
= String::CreateFromAscii("TR");
169 const String aTDString
= String::CreateFromAscii("TD");
170 const String aTHString
= String::CreateFromAscii("TH");
171 const String aBibEntryString
= String::CreateFromAscii("BibEntry");
172 const String aQuoteString
= String::CreateFromAscii("Quote");
173 const String aSpanString
= String::CreateFromAscii("Span");
174 const String aCodeString
= String::CreateFromAscii("Code");
175 const String aFigureString
= String::CreateFromAscii("Figure");
176 const String aFormulaString
= String::CreateFromAscii("Formula");
177 const String aLinkString
= String::CreateFromAscii("Link");
178 const String aNoteString
= String::CreateFromAscii("Note");
179 const String aEmptyString
= String::CreateFromAscii("");
181 // returns true if first paragraph in cell frame has 'table heading' style
182 bool lcl_IsHeadlineCell( const SwCellFrm
& rCellFrm
)
186 const SwCntntFrm
*pCnt
= rCellFrm
.ContainsCntnt();
187 if ( pCnt
&& pCnt
->IsTxtFrm() )
189 const SwTxtNode
* pTxtNode
= static_cast<const SwTxtFrm
*>(pCnt
)->GetTxtNode();
190 const SwFmt
* pTxtFmt
= pTxtNode
->GetFmtColl();
193 SwStyleNameMapper::FillProgName( pTxtFmt
->GetName(), sStyleName
, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
, sal_True
);
194 bRet
= sStyleName
== aTableHeadingName
;
200 // List all frames for which the NonStructElement tag is set:
201 bool lcl_IsInNonStructEnv( const SwFrm
& rFrm
)
205 if ( 0 != rFrm
.FindFooterOrHeader() &&
206 !rFrm
.IsHeaderFrm() && !rFrm
.IsFooterFrm() )
210 else if ( rFrm
.IsInTab() && !rFrm
.IsTabFrm() )
212 const SwTabFrm
* pTabFrm
= rFrm
.FindTabFrm();
213 if ( rFrm
.GetUpper() != pTabFrm
&&
214 pTabFrm
->IsFollow() && pTabFrm
->IsInHeadline( rFrm
) )
221 // Generate key from frame for reopening tags:
222 void* lcl_GetKeyFromFrame( const SwFrm
& rFrm
)
226 if ( rFrm
.IsPageFrm() )
227 pKey
= (void*)static_cast<const SwPageFrm
&>(rFrm
).GetFmt()->getIDocumentSettingAccess();
228 else if ( rFrm
.IsTxtFrm() )
229 pKey
= (void*)static_cast<const SwTxtFrm
&>(rFrm
).GetTxtNode();
230 else if ( rFrm
.IsSctFrm() )
231 pKey
= (void*)static_cast<const SwSectionFrm
&>(rFrm
).GetSection();
232 else if ( rFrm
.IsTabFrm() )
233 pKey
= (void*)static_cast<const SwTabFrm
&>(rFrm
).GetTable();
234 else if ( rFrm
.IsRowFrm() )
235 pKey
= (void*)static_cast<const SwRowFrm
&>(rFrm
).GetTabLine();
236 else if ( rFrm
.IsCellFrm() )
238 const SwTabFrm
* pTabFrm
= rFrm
.FindTabFrm();
239 const SwTable
* pTable
= pTabFrm
->GetTable();
240 pKey
= (void*) & static_cast<const SwCellFrm
&>(rFrm
).GetTabBox()->FindStartOfRowSpan( *pTable
);
246 bool lcl_HasPreviousParaSameNumRule( const SwTxtNode
& rNode
)
249 SwNodeIndex
aIdx( rNode
);
250 const SwDoc
* pDoc
= rNode
.GetDoc();
251 const SwNodes
& rNodes
= pDoc
->GetNodes();
252 const SwNode
* pNode
= &rNode
;
253 const SwNumRule
* pNumRule
= rNode
.GetNumRule();
255 while (! (pNode
== rNodes
.DocumentSectionStartNode((SwNode
*)&rNode
) ) )
259 if (aIdx
.GetNode().IsTxtNode())
261 const SwTxtNode
* pPrevTxtNd
= aIdx
.GetNode().GetTxtNode();
262 const SwNumRule
* pPrevNumRule
= pPrevTxtNd
->GetNumRule();
264 // We find the previous text node. Now check, if the previous text node
265 // has the same numrule like rNode:
266 if ( (pPrevNumRule
== pNumRule
) &&
267 (!pPrevTxtNd
->IsOutline() == !rNode
.IsOutline()))
273 pNode
= &aIdx
.GetNode();
281 * SwTaggedPDFHelper::SwTaggedPDFHelper()
283 SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info
* pNumInfo
,
284 const Frm_Info
* pFrmInfo
,
285 const Por_Info
* pPorInfo
,
287 : nEndStructureElement( 0 ),
288 nRestoreCurrentTag( -1 ),
289 mpNumInfo( pNumInfo
),
290 mpFrmInfo( pFrmInfo
),
291 mpPorInfo( pPorInfo
)
294 PTR_CAST( vcl::PDFExtOutDevData
, rOut
.GetExtOutDevData() );
296 if ( mpPDFExtOutDevData
&& mpPDFExtOutDevData
->GetIsExportTaggedPDF() )
299 sal_Int32 nCurrentStruct
= mpPDFExtOutDevData
->GetCurrentStructureElement();
303 BeginNumberedListStructureElements();
304 else if ( mpFrmInfo
)
305 BeginBlockStructureElements();
306 else if ( mpPorInfo
)
307 BeginInlineStructureElements();
309 BeginTag( vcl::PDFWriter::NonStructElement
, aEmptyString
);
312 nCurrentStruct
= mpPDFExtOutDevData
->GetCurrentStructureElement();
320 * SwTaggedPDFHelper::~SwTaggedPDFHelper()
322 SwTaggedPDFHelper::~SwTaggedPDFHelper()
324 if ( mpPDFExtOutDevData
&& mpPDFExtOutDevData
->GetIsExportTaggedPDF() )
327 sal_Int32 nCurrentStruct
= mpPDFExtOutDevData
->GetCurrentStructureElement();
330 EndStructureElements();
333 nCurrentStruct
= mpPDFExtOutDevData
->GetCurrentStructureElement();
341 * SwTaggedPDFHelper::CheckReopenTag()
343 bool SwTaggedPDFHelper::CheckReopenTag()
346 sal_Int32 nReopenTag
= -1;
347 bool bContinue
= false; // in some cases we just have to reopen a tag without early returning
351 const SwFrm
& rFrm
= mpFrmInfo
->mrFrm
;
352 const SwFrm
* pKeyFrm
= 0;
355 // Reopen an existing structure element if
356 // - rFrm is not the first page frame (reopen Document tag)
357 // - rFrm is a follow frame (reopen Master tag)
358 // - rFrm is a fly frame anchored at content (reopen Anchor paragraph tag)
359 // - rFrm is a fly frame anchord at page (reopen Document tag)
360 // - rFrm is a follow flow row (reopen TableRow tag)
361 // - rFrm is a cell frame in a follow flow row (reopen TableData tag)
362 if ( ( rFrm
.IsPageFrm() && static_cast<const SwPageFrm
&>(rFrm
).GetPrev() ) ||
363 ( rFrm
.IsFlowFrm() && SwFlowFrm::CastFlowFrm(&rFrm
)->IsFollow() ) ||
364 ( rFrm
.IsRowFrm() && rFrm
.IsInFollowFlowRow() ) ||
365 ( rFrm
.IsCellFrm() && const_cast<SwFrm
&>(rFrm
).GetPrevCellLeaf( MAKEPAGE_NONE
) ) )
369 else if ( rFrm
.IsFlyFrm() )
371 const SwFmtAnchor
& rAnchor
=
372 static_cast<const SwFlyFrm
*>(&rFrm
)->GetFmt()->GetAnchor();
373 if ( FLY_AT_CNTNT
== rAnchor
.GetAnchorId() ||
374 FLY_AUTO_CNTNT
== rAnchor
.GetAnchorId() ||
375 FLY_PAGE
== rAnchor
.GetAnchorId() )
377 pKeyFrm
= static_cast<const SwFlyFrm
&>(rFrm
).GetAnchorFrm();
384 pKey
= lcl_GetKeyFromFrame( *pKeyFrm
);
388 FrmTagIdMap
& rFrmTagIdMap
= SwEnhancedPDFExportHelper::GetFrmTagIdMap();
389 const FrmTagIdMap::const_iterator aIter
= rFrmTagIdMap
.find( pKey
);
390 nReopenTag
= (*aIter
).second
;
395 if ( -1 != nReopenTag
)
397 nRestoreCurrentTag
= mpPDFExtOutDevData
->GetCurrentStructureElement();
398 const bool bSuccess
= mpPDFExtOutDevData
->SetCurrentStructureElement( nReopenTag
);
399 ASSERT( bSuccess
, "Failed to reopen tag" )
402 aStructStack
.push_back( 99 );
408 return bRet
&& !bContinue
;
413 * SwTaggedPDFHelper::CheckRestoreTag()
415 bool SwTaggedPDFHelper::CheckRestoreTag() const
418 if ( nRestoreCurrentTag
!= -1 )
420 const bool bSuccess
= mpPDFExtOutDevData
->SetCurrentStructureElement( nRestoreCurrentTag
);
422 ASSERT( bSuccess
, "Failed to restore reopened tag" )
425 aStructStack
.pop_back();
436 * SwTaggedPDFHelper::BeginTag()
438 void SwTaggedPDFHelper::BeginTag( vcl::PDFWriter::StructElement eType
, const String
& rString
)
441 const sal_Int32 nId
= mpPDFExtOutDevData
->BeginStructureElement( eType
, rtl::OUString( rString
) );
442 ++nEndStructureElement
;
445 aStructStack
.push_back( static_cast<USHORT
>(eType
) );
448 // Store the id of the current structure element if
449 // - it is a list structure element
450 // - it is a list body element with children
451 // - rFrm is the first page frame
452 // - rFrm is a master frame
453 // - rFrm has objects anchored to it
454 // - rFrm is a row frame or cell frame in a split table row
458 const SwTxtFrm
& rTxtFrm
= static_cast<const SwTxtFrm
&>(mpNumInfo
->mrFrm
);
459 const SwTxtNode
* pTxtNd
= rTxtFrm
.GetTxtNode();
460 const SwNodeNum
* pNodeNum
= pTxtNd
->GetNum();
462 if ( vcl::PDFWriter::List
== eType
)
464 NumListIdMap
& rNumListIdMap
= SwEnhancedPDFExportHelper::GetNumListIdMap();
465 rNumListIdMap
[ pNodeNum
] = nId
;
467 else if ( vcl::PDFWriter::LIBody
== eType
)
469 NumListBodyIdMap
& rNumListBodyIdMap
= SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
470 rNumListBodyIdMap
[ pNodeNum
] = nId
;
473 else if ( mpFrmInfo
)
475 const SwFrm
& rFrm
= mpFrmInfo
->mrFrm
;
477 if ( ( rFrm
.IsPageFrm() && !static_cast<const SwPageFrm
&>(rFrm
).GetPrev() ) ||
478 ( rFrm
.IsFlowFrm() && !SwFlowFrm::CastFlowFrm(&rFrm
)->IsFollow() && SwFlowFrm::CastFlowFrm(&rFrm
)->HasFollow() ) ||
479 ( rFrm
.IsTxtFrm() && rFrm
.GetDrawObjs() ) ||
480 ( rFrm
.IsRowFrm() && rFrm
.IsInSplitTableRow() ) ||
481 ( rFrm
.IsCellFrm() && const_cast<SwFrm
&>(rFrm
).GetNextCellLeaf( MAKEPAGE_NONE
) ) )
483 const void* pKey
= lcl_GetKeyFromFrame( rFrm
);
487 FrmTagIdMap
& rFrmTagIdMap
= SwEnhancedPDFExportHelper::GetFrmTagIdMap();
488 rFrmTagIdMap
[ pKey
] = nId
;
493 SetAttributes( eType
);
498 * SwTaggedPDFHelper::EndTag()
500 void SwTaggedPDFHelper::EndTag()
502 mpPDFExtOutDevData
->EndStructureElement();
505 aStructStack
.pop_back();
511 * SwTaggedPDFHelper::SetAttributes()
513 * Sets the attributes according to the structure type.
515 void SwTaggedPDFHelper::SetAttributes( vcl::PDFWriter::StructElement eType
)
517 vcl::PDFWriter::StructAttributeValue eVal
;
521 * ATTRIBUTES FOR BLSE
525 const SwFrm
* pFrm
= &mpFrmInfo
->mrFrm
;
528 bool bPlacement
= false;
529 bool bWritingMode
= false;
530 bool bSpaceBefore
= false;
531 bool bSpaceAfter
= false;
532 bool bStartIndent
= false;
533 bool bEndIndent
= false;
534 bool bTextIndent
= false;
535 bool bTextAlign
= false;
536 bool bAlternateText
= false;
538 bool bHeight
= false;
540 bool bRowSpan
= false;
543 // Check which attributes to set:
547 case vcl::PDFWriter::Document
:
551 case vcl::PDFWriter::Table
:
563 case vcl::PDFWriter::TableRow
:
568 case vcl::PDFWriter::TableHeader
:
569 case vcl::PDFWriter::TableData
:
577 case vcl::PDFWriter::H1
:
578 case vcl::PDFWriter::H2
:
579 case vcl::PDFWriter::H3
:
580 case vcl::PDFWriter::H4
:
581 case vcl::PDFWriter::H5
:
582 case vcl::PDFWriter::H6
:
583 case vcl::PDFWriter::Paragraph
:
584 case vcl::PDFWriter::Heading
:
585 case vcl::PDFWriter::Caption
:
586 case vcl::PDFWriter::BlockQuote
:
598 case vcl::PDFWriter::Formula
:
599 case vcl::PDFWriter::Figure
:
611 // Set the attributes:
615 eVal
= vcl::PDFWriter::TableHeader
== eType
||
616 vcl::PDFWriter::TableData
== eType
?
617 vcl::PDFWriter::Inline
:
618 vcl::PDFWriter::Block
;
620 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::Placement
, eVal
);
625 eVal
= pFrm
->IsVertical() ?
626 vcl::PDFWriter::TbRl
:
627 pFrm
->IsRightToLeft() ?
628 vcl::PDFWriter::RlTb
:
629 vcl::PDFWriter::LrTb
;
631 if ( vcl::PDFWriter::LrTb
!= eVal
)
632 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::WritingMode
, eVal
);
637 nVal
= (pFrm
->*fnRect
->fnGetTopMargin
)();
639 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceBefore
, nVal
);
644 nVal
= (pFrm
->*fnRect
->fnGetBottomMargin
)();
646 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceAfter
, nVal
);
651 nVal
= (pFrm
->*fnRect
->fnGetLeftMargin
)();
653 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::StartIndent
, nVal
);
658 nVal
= (pFrm
->*fnRect
->fnGetRightMargin
)();
660 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::EndIndent
, nVal
);
665 ASSERT( pFrm
->IsTxtFrm(), "Frame type <-> tag attribute mismatch" )
666 const SvxLRSpaceItem
&rSpace
=
667 static_cast<const SwTxtFrm
*>(pFrm
)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
668 nVal
= rSpace
.GetTxtFirstLineOfst();
670 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::TextIndent
, nVal
);
675 ASSERT( pFrm
->IsTxtFrm(), "Frame type <-> tag attribute mismatch" )
676 const SwAttrSet
& aSet
= static_cast<const SwTxtFrm
*>(pFrm
)->GetTxtNode()->GetSwAttrSet();
677 const SvxAdjust nAdjust
= aSet
.GetAdjust().GetAdjust();
678 if ( SVX_ADJUST_BLOCK
== nAdjust
|| SVX_ADJUST_CENTER
== nAdjust
||
679 ( (pFrm
->IsRightToLeft() && SVX_ADJUST_LEFT
== nAdjust
) ||
680 (!pFrm
->IsRightToLeft() && SVX_ADJUST_RIGHT
== nAdjust
) ) )
682 eVal
= SVX_ADJUST_BLOCK
== nAdjust
?
683 vcl::PDFWriter::Justify
:
684 SVX_ADJUST_CENTER
== nAdjust
?
685 vcl::PDFWriter::Center
:
688 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::TextAlign
, eVal
);
692 if ( bAlternateText
)
694 ASSERT( pFrm
->IsFlyFrm(), "Frame type <-> tag attribute mismatch" )
695 const SwFlyFrm
* pFly
= static_cast<const SwFlyFrm
*>(pFrm
);
696 if ( pFly
->Lower() && pFly
->Lower()->IsNoTxtFrm() )
698 const SwNoTxtFrm
* pNoTxtFrm
= static_cast<const SwNoTxtFrm
*>(pFly
->Lower());
699 const SwNoTxtNode
* pNoTxtNode
= static_cast<const SwNoTxtNode
*>(pNoTxtFrm
->GetNode());
701 const String
aAlternateTxt( pNoTxtNode
->GetTitle() );
702 mpPDFExtOutDevData
->SetAlternateText( aAlternateTxt
);
708 nVal
= (pFrm
->Frm().*fnRect
->fnGetWidth
)();
709 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::Width
, nVal
);
714 nVal
= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
715 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::Height
, nVal
);
720 // BBox only for non-split tables:
721 if ( vcl::PDFWriter::Table
!= eType
||
722 ( pFrm
->IsTabFrm() &&
723 !static_cast<const SwTabFrm
*>(pFrm
)->IsFollow() &&
724 !static_cast<const SwTabFrm
*>(pFrm
)->HasFollow() ) )
725 mpPDFExtOutDevData
->SetStructureBoundingBox( pFrm
->Frm().SVRect() );
730 const SwCellFrm
* pThisCell
= dynamic_cast<const SwCellFrm
*>(pFrm
);
733 nVal
= pThisCell
->GetTabBox()->getRowSpan();
735 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::RowSpan
, nVal
);
737 // calculate colspan:
738 const SwTabFrm
* pTabFrm
= pThisCell
->FindTabFrm();
739 const SwTable
* pTable
= pTabFrm
->GetTable();
743 const TableColumnsMapEntry
& rCols
= SwEnhancedPDFExportHelper::GetTableColumnsMap()[ pTable
];
745 const long nLeft
= (pThisCell
->Frm().*fnRectX
->fnGetLeft
)();
746 const long nRight
= (pThisCell
->Frm().*fnRectX
->fnGetRight
)();
747 const TableColumnsMapEntry::const_iterator aLeftIter
= rCols
.find( nLeft
);
748 const TableColumnsMapEntry::const_iterator aRightIter
= rCols
.find( nRight
);
750 ASSERT( aLeftIter
!= rCols
.end() && aRightIter
!= rCols
.end(), "Colspan trouble" )
751 if ( aLeftIter
!= rCols
.end() && aRightIter
!= rCols
.end() )
753 nVal
= std::distance( aLeftIter
, aRightIter
);
755 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::ColSpan
, nVal
);
762 * ATTRIBUTES FOR ILSE
764 else if ( mpPorInfo
)
766 const SwLinePortion
* pPor
= &mpPorInfo
->mrPor
;
767 const SwTxtPaintInfo
& rInf
= mpPorInfo
->mrTxtPainter
.GetInfo();
769 bool bActualText
= false;
770 bool bBaselineShift
= false;
771 bool bTextDecorationType
= false;
772 bool bLinkAttribute
= false;
773 bool bLanguage
= false;
776 // Check which attributes to set:
780 case vcl::PDFWriter::Span
:
781 case vcl::PDFWriter::Quote
:
782 case vcl::PDFWriter::Code
:
783 if( POR_HYPHSTR
== pPor
->GetWhichPor() || POR_SOFTHYPHSTR
== pPor
->GetWhichPor() )
788 bTextDecorationType
=
793 case vcl::PDFWriter::Link
:
794 bTextDecorationType
=
806 const String
aActualTxt( rInf
.GetTxt(), rInf
.GetIdx(), pPor
->GetLen() );
807 mpPDFExtOutDevData
->SetActualText( aActualTxt
);
810 if ( bBaselineShift
)
812 // TODO: Calculate correct values!
813 nVal
= rInf
.GetFont()->GetEscapement();
814 if ( nVal
> 0 ) nVal
= 33;
815 else if ( nVal
< 0 ) nVal
= -33;
819 nVal
= nVal
* pPor
->Height() / 100;
820 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::BaselineShift
, nVal
);
824 if ( bTextDecorationType
)
826 if ( UNDERLINE_NONE
!= rInf
.GetFont()->GetUnderline() )
827 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::TextDecorationType
, vcl::PDFWriter::Underline
);
828 if ( UNDERLINE_NONE
!= rInf
.GetFont()->GetOverline() )
829 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::TextDecorationType
, vcl::PDFWriter::Overline
);
830 if ( STRIKEOUT_NONE
!= rInf
.GetFont()->GetStrikeout() )
831 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::TextDecorationType
, vcl::PDFWriter::LineThrough
);
832 if ( EMPHASISMARK_NONE
!= rInf
.GetFont()->GetEmphasisMark() )
833 mpPDFExtOutDevData
->SetStructureAttribute( vcl::PDFWriter::TextDecorationType
, vcl::PDFWriter::Overline
);
839 const LanguageType nCurrentLanguage
= rInf
.GetFont()->GetLanguage();
840 const LanguageType nDefaultLang
= SwEnhancedPDFExportHelper::GetDefaultLanguage();
842 if ( nDefaultLang
!= nCurrentLanguage
)
843 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::Language
, nCurrentLanguage
);
846 if ( bLinkAttribute
)
848 const LinkIdMap
& rLinkIdMap
= SwEnhancedPDFExportHelper::GetLinkIdMap();
850 rInf
.CalcRect( *pPor
, &aPorRect
);
851 const Point aPorCenter
= aPorRect
.Center();
852 LinkIdMap::const_iterator aIter
;
853 for ( aIter
= rLinkIdMap
.begin(); aIter
!= rLinkIdMap
.end(); ++aIter
)
855 const SwRect
& rLinkRect
= (*aIter
).first
;
856 if ( rLinkRect
.IsInside( aPorCenter
) )
858 sal_Int32 nLinkId
= (*aIter
).second
;
859 mpPDFExtOutDevData
->SetStructureAttributeNumerical( vcl::PDFWriter::LinkAnnotation
, nLinkId
);
868 * SwTaggedPDFHelper::BeginNumberedListStructureElements()
870 void SwTaggedPDFHelper::BeginNumberedListStructureElements()
872 ASSERT( mpNumInfo
, "List without mpNumInfo?" )
876 const SwFrm
& rFrm
= mpNumInfo
->mrFrm
;
877 ASSERT( rFrm
.IsTxtFrm(), "numbered only for text frames" )
878 const SwTxtFrm
& rTxtFrm
= static_cast<const SwTxtFrm
&>(rFrm
);
881 // Lowers of NonStructureElements should not be considered:
883 if ( lcl_IsInNonStructEnv( rTxtFrm
) || rTxtFrm
.IsFollow() )
886 const SwTxtNode
* pTxtNd
= rTxtFrm
.GetTxtNode();
887 const SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
888 const SwNodeNum
* pNodeNum
= pTxtNd
->GetNum();
890 const bool bNumbered
= !pTxtNd
->IsOutline() && pNodeNum
&& pNodeNum
->GetParent() && pNumRule
;
892 // Check, if we have to reopen a list or a list body:
894 // Paragraph is numbered/bulleted
898 const SwNumberTreeNode
* pParent
= pNodeNum
->GetParent();
899 const bool bSameNumbering
= lcl_HasPreviousParaSameNumRule(*pTxtNd
);
901 // Second condition: current numbering is not 'interrupted'
902 if ( bSameNumbering
)
904 sal_Int32 nReopenTag
= -1;
907 // 1. We have to reopen an existing list body tag:
908 // - If the current node is either the first child of its parent
909 // and its level > 1 or
910 // - Numbering should restart at the current node and its level > 1
911 // - The current item has no label
912 const bool bNewSubListStart
= pParent
->GetParent() && (pParent
->IsFirst( pNodeNum
) || pTxtNd
->IsListRestart() );
913 const bool bNoLabel
= !pTxtNd
->IsCountedInList() && !pTxtNd
->IsListRestart();
914 if ( bNewSubListStart
|| bNoLabel
)
916 // Fine, we try to reopen the appropriate list body
917 NumListBodyIdMap
& rNumListBodyIdMap
= SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
919 if ( bNewSubListStart
)
921 // The list body tag associated with the parent has to be reopened
922 // to start a new list inside the list body
923 NumListBodyIdMap::const_iterator aIter
;
926 aIter
= rNumListBodyIdMap
.find( pParent
);
927 while ( aIter
== rNumListBodyIdMap
.end() && 0 != ( pParent
= pParent
->GetParent() ) );
929 if ( aIter
!= rNumListBodyIdMap
.end() )
930 nReopenTag
= (*aIter
).second
;
934 // The list body tag of a 'counted' predecessor has to be reopened
935 const SwNumberTreeNode
* pPrevious
= pNodeNum
->GetPred(true);
938 if ( pPrevious
->IsCounted())
940 // get id of list body tag
941 const NumListBodyIdMap::const_iterator aIter
= rNumListBodyIdMap
.find( pPrevious
);
942 if ( aIter
!= rNumListBodyIdMap
.end() )
944 nReopenTag
= (*aIter
).second
;
948 pPrevious
= pPrevious
->GetPred(true);
952 // 2. We have to reopen an existing list tag:
953 else if ( !pParent
->IsFirst( pNodeNum
) && !pTxtNd
->IsListRestart() )
955 // any other than the first node in a list level has to reopen the current
956 // list. The current list is associated in a map with the first child of the list:
957 NumListIdMap
& rNumListIdMap
= SwEnhancedPDFExportHelper::GetNumListIdMap();
959 // Search backwards and check if any of the previous nodes has a list associated with it:
960 const SwNumberTreeNode
* pPrevious
= pNodeNum
->GetPred(true);
963 // get id of list tag
964 const NumListIdMap::const_iterator aIter
= rNumListIdMap
.find( pPrevious
);
965 if ( aIter
!= rNumListIdMap
.end() )
967 nReopenTag
= (*aIter
).second
;
971 pPrevious
= pPrevious
->GetPred(true);
975 if ( -1 != nReopenTag
)
977 nRestoreCurrentTag
= mpPDFExtOutDevData
->GetCurrentStructureElement();
978 mpPDFExtOutDevData
->SetCurrentStructureElement( nReopenTag
);
981 aStructStack
.push_back( 99 );
987 // clear list maps in case a list has been interrupted
988 NumListIdMap
& rNumListIdMap
= SwEnhancedPDFExportHelper::GetNumListIdMap();
989 rNumListIdMap
.clear();
990 NumListBodyIdMap
& rNumListBodyIdMap
= SwEnhancedPDFExportHelper::GetNumListBodyIdMap();
991 rNumListBodyIdMap
.clear();
995 const bool bNewListTag
= (pNodeNum
->GetParent()->IsFirst( pNodeNum
) || pTxtNd
->IsListRestart() || !bSameNumbering
);
996 const bool bNewItemTag
= bNewListTag
|| pTxtNd
->IsCountedInList(); // If the text node is not counted, we do not start a new list item:
999 BeginTag( vcl::PDFWriter::List
, aListString
);
1003 BeginTag( vcl::PDFWriter::ListItem
, aListItemString
);
1004 BeginTag( vcl::PDFWriter::LIBody
, aListBodyString
);
1009 * SwTaggedPDFHelper::BeginBlockStructureElements()
1011 void SwTaggedPDFHelper::BeginBlockStructureElements()
1013 const SwFrm
* pFrm
= &mpFrmInfo
->mrFrm
;
1016 // Lowers of NonStructureElements should not be considered:
1018 if ( lcl_IsInNonStructEnv( *pFrm
) )
1021 // Check if we have to reopen an existing structure element.
1022 // This has to be done e.g., if pFrm is a follow frame.
1023 if ( CheckReopenTag() )
1026 USHORT nPDFType
= USHRT_MAX
;
1029 switch ( pFrm
->GetType() )
1037 // Document: Document
1039 nPDFType
= vcl::PDFWriter::Document
;
1040 aPDFType
= aDocumentString
;
1046 // Header, Footer: NonStructElement
1048 nPDFType
= vcl::PDFWriter::NonStructElement
;
1053 // Footnote container: Division
1055 nPDFType
= vcl::PDFWriter::Division
;
1056 aPDFType
= aDivString
;
1061 // Footnote frame: Note
1063 // Note: vcl::PDFWriter::Note is actually a ILSE. Nevertheless
1064 // we treat it like a grouping element!
1065 nPDFType
= vcl::PDFWriter::Note
;
1066 aPDFType
= aNoteString
;
1071 // Section: TOX, Index, or Sect
1074 const SwSection
* pSection
=
1075 static_cast<const SwSectionFrm
*>(pFrm
)->GetSection();
1076 if ( TOX_CONTENT_SECTION
== pSection
->GetType() )
1078 const SwTOXBase
* pTOXBase
= pSection
->GetTOXBase();
1081 if ( TOX_INDEX
== pTOXBase
->GetType() )
1083 nPDFType
= vcl::PDFWriter::Index
;
1084 aPDFType
= aIndexString
;
1088 nPDFType
= vcl::PDFWriter::TOC
;
1089 aPDFType
= aTOCString
;
1093 else if ( CONTENT_SECTION
== pSection
->GetType() )
1095 nPDFType
= vcl::PDFWriter::Section
;
1096 aPDFType
= aSectString
;
1102 * BLOCK-LEVEL STRUCTURE ELEMENTS
1107 const SwTxtNode
* pTxtNd
=
1108 static_cast<const SwTxtFrm
*>(pFrm
)->GetTxtNode();
1110 const SwFmt
* pTxtFmt
= pTxtNd
->GetFmtColl();
1111 const SwFmt
* pParentTxtFmt
= pTxtFmt
->DerivedFrom();
1114 String sParentStyleName
;
1117 SwStyleNameMapper::FillProgName( pTxtFmt
->GetName(), sStyleName
, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
, sal_True
);
1119 SwStyleNameMapper::FillProgName( pParentTxtFmt
->GetName(), sParentStyleName
, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
, sal_True
);
1121 // This is the default. If the paragraph could not be mapped to
1122 // any of the standard pdf tags, we write a user defined tag
1123 // <stylename> with role = P
1124 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::Paragraph
);
1125 aPDFType
= sStyleName
;
1128 // Quotations: BlockQuote
1130 if ( sStyleName
== aQuotations
)
1132 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::BlockQuote
);
1133 aPDFType
= aBlockQuoteString
;
1139 else if ( sStyleName
== aCaption
)
1141 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::Caption
);
1142 aPDFType
= aCaptionString
;
1148 else if ( sParentStyleName
== aCaption
)
1150 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::Caption
);
1151 aPDFType
= sStyleName
.Append(aCaptionString
);
1157 else if ( sStyleName
== aHeading
)
1159 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::Heading
);
1160 aPDFType
= aHString
;
1166 if ( pTxtNd
->IsOutline() )
1168 //int nRealLevel = pTxtNd->GetOutlineLevel(); //#outline level,zhaojianwei
1169 int nRealLevel
= pTxtNd
->GetAttrOutlineLevel()-1; //<-end,zhaojianwei
1170 nRealLevel
= nRealLevel
> 5 ? 5 : nRealLevel
;
1172 nPDFType
= static_cast<USHORT
>(vcl::PDFWriter::H1
+ nRealLevel
);
1176 aPDFType
= aH1String
;
1179 aPDFType
= aH2String
;
1182 aPDFType
= aH3String
;
1185 aPDFType
= aH4String
;
1188 aPDFType
= aH5String
;
1191 aPDFType
= aH6String
;
1199 else if ( pFrm
->IsInSct() )
1201 const SwSectionFrm
* pSctFrm
= pFrm
->FindSctFrm();
1202 const SwSection
* pSection
=
1203 static_cast<const SwSectionFrm
*>(pSctFrm
)->GetSection();
1205 if ( TOX_CONTENT_SECTION
== pSection
->GetType() )
1207 const SwTOXBase
* pTOXBase
= pSection
->GetTOXBase();
1208 if ( pTOXBase
&& TOX_INDEX
!= pTOXBase
->GetType() )
1210 // Special case: Open additional TOCI tag:
1211 BeginTag( vcl::PDFWriter::TOCI
, aTOCIString
);
1222 nPDFType
= vcl::PDFWriter::Table
;
1223 aPDFType
= aTableString
;
1226 // set up table column data:
1227 const SwTabFrm
* pTabFrm
= static_cast<const SwTabFrm
*>(pFrm
);
1228 const SwTable
* pTable
= pTabFrm
->GetTable();
1230 TableColumnsMap
& rTableColumnsMap
= SwEnhancedPDFExportHelper::GetTableColumnsMap();
1231 const TableColumnsMap::const_iterator aIter
= rTableColumnsMap
.find( pTable
);
1233 if ( aIter
== rTableColumnsMap
.end() )
1236 TableColumnsMapEntry
& rCols
= rTableColumnsMap
[ pTable
];
1238 const SwTabFrm
* pMasterFrm
= pTabFrm
->IsFollow() ? pTabFrm
->FindMaster( true ) : pTabFrm
;
1240 while ( pMasterFrm
)
1242 const SwRowFrm
* pRowFrm
= static_cast<const SwRowFrm
*>(pMasterFrm
->GetLower());
1246 const SwFrm
* pCellFrm
= pRowFrm
->GetLower();
1248 const long nLeft
= (pCellFrm
->Frm().*fnRect
->fnGetLeft
)();
1249 rCols
.insert( nLeft
);
1253 const long nRight
= (pCellFrm
->Frm().*fnRect
->fnGetRight
)();
1254 rCols
.insert( nRight
);
1255 pCellFrm
= pCellFrm
->GetNext();
1257 pRowFrm
= static_cast<const SwRowFrm
*>(pRowFrm
->GetNext());
1259 pMasterFrm
= static_cast<const SwTabFrm
*>(pMasterFrm
->GetFollow());
1274 if ( !static_cast<const SwRowFrm
*>(pFrm
)->IsRepeatedHeadline() )
1276 nPDFType
= vcl::PDFWriter::TableRow
;
1277 aPDFType
= aTRString
;
1281 nPDFType
= vcl::PDFWriter::NonStructElement
;
1290 const SwTabFrm
* pTable
= static_cast<const SwCellFrm
*>(pFrm
)->FindTabFrm();
1291 if ( pTable
->IsInHeadline( *pFrm
) || lcl_IsHeadlineCell( *static_cast<const SwCellFrm
*>(pFrm
) ) )
1293 nPDFType
= vcl::PDFWriter::TableHeader
;
1294 aPDFType
= aTHString
;
1298 nPDFType
= vcl::PDFWriter::TableData
;
1299 aPDFType
= aTDString
;
1310 // FlyFrm: Figure, Formula, Control
1311 // fly in content or fly at page
1313 bool bFormula
= false;
1314 const SwFlyFrm
* pFly
= static_cast<const SwFlyFrm
*>(pFrm
);
1315 if ( pFly
->Lower() && pFly
->Lower()->IsNoTxtFrm() )
1317 const SwNoTxtFrm
* pNoTxtFrm
= static_cast<const SwNoTxtFrm
*>(pFly
->Lower());
1318 SwOLENode
* pOLENd
= const_cast<SwOLENode
*>(pNoTxtFrm
->GetNode()->GetOLENode());
1321 SwOLEObj
& aOLEObj
= pOLENd
->GetOLEObj();
1322 uno::Reference
< embed::XEmbeddedObject
> aRef
= aOLEObj
.GetOleRef();
1325 bFormula
= 0 != SotExchange::IsMath( SvGlobalName( aRef
->getClassID() ) );
1330 nPDFType
= vcl::PDFWriter::Formula
;
1331 aPDFType
= aFormulaString
;
1335 nPDFType
= vcl::PDFWriter::Figure
;
1336 aPDFType
= aFigureString
;
1341 nPDFType
= vcl::PDFWriter::Division
;
1342 aPDFType
= aDivString
;
1348 if ( USHRT_MAX
!= nPDFType
)
1350 BeginTag( static_cast<vcl::PDFWriter::StructElement
>(nPDFType
), aPDFType
);
1356 * SwTaggedPDFHelper::EndStructureElements()
1358 void SwTaggedPDFHelper::EndStructureElements()
1360 while ( nEndStructureElement
> 0 )
1363 --nEndStructureElement
;
1371 * SwTaggedPDFHelper::BeginInlineStructureElements()
1373 void SwTaggedPDFHelper::BeginInlineStructureElements()
1375 const SwLinePortion
* pPor
= &mpPorInfo
->mrPor
;
1376 const SwTxtPaintInfo
& rInf
= mpPorInfo
->mrTxtPainter
.GetInfo();
1377 const SwTxtFrm
* pFrm
= rInf
.GetTxtFrm();
1380 // Lowers of NonStructureElements should not be considered:
1382 if ( lcl_IsInNonStructEnv( *pFrm
) )
1385 USHORT nPDFType
= USHRT_MAX
;
1388 switch ( pPor
->GetWhichPor() )
1390 // Check for alternative spelling:
1392 case POR_SOFTHYPHSTR
:
1393 nPDFType
= vcl::PDFWriter::Span
;
1394 aPDFType
= aSpanString
;
1401 SwTxtNode
* pNd
= (SwTxtNode
*)pFrm
->GetTxtNode();
1402 SwIndex
aIndex( pNd
, rInf
.GetIdx() );
1403 const SwTxtAttr
* pInetFmtAttr
= pNd
->GetTxtAttr( aIndex
, RES_TXTATR_INETFMT
);
1406 if ( !pInetFmtAttr
)
1408 const SwTxtAttr
* pCharFmtAttr
= pNd
->GetTxtAttr( aIndex
, RES_TXTATR_CHARFMT
);
1409 const SwCharFmt
* pCharFmt
= pCharFmtAttr
? pCharFmtAttr
->GetCharFmt().GetCharFmt() : 0;
1411 SwStyleNameMapper::FillProgName( pCharFmt
->GetName(), sStyleName
, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL
, sal_True
);
1417 nPDFType
= vcl::PDFWriter::Link
;
1418 aPDFType
= aLinkString
;
1420 // Check for Quote/Code character style:
1421 else if ( sStyleName
== aQuotation
)
1423 nPDFType
= vcl::PDFWriter::Quote
;
1424 aPDFType
= aQuoteString
;
1426 else if ( sStyleName
== aSourceText
)
1428 nPDFType
= vcl::PDFWriter::Code
;
1429 aPDFType
= aCodeString
;
1433 const LanguageType nCurrentLanguage
= rInf
.GetFont()->GetLanguage();
1434 const USHORT nFont
= rInf
.GetFont()->GetActual();
1435 const LanguageType nDefaultLang
= SwEnhancedPDFExportHelper::GetDefaultLanguage();
1437 if ( UNDERLINE_NONE
!= rInf
.GetFont()->GetUnderline() ||
1438 UNDERLINE_NONE
!= rInf
.GetFont()->GetOverline() ||
1439 STRIKEOUT_NONE
!= rInf
.GetFont()->GetStrikeout() ||
1440 EMPHASISMARK_NONE
!= rInf
.GetFont()->GetEmphasisMark() ||
1441 0 != rInf
.GetFont()->GetEscapement() ||
1442 SW_LATIN
!= nFont
||
1443 nCurrentLanguage
!= nDefaultLang
||
1444 sStyleName
.Len() > 0 )
1446 nPDFType
= vcl::PDFWriter::Span
;
1447 if ( sStyleName
.Len() > 0 )
1448 aPDFType
= sStyleName
;
1450 aPDFType
= aSpanString
;
1457 nPDFType
= vcl::PDFWriter::Link
;
1458 aPDFType
= aLinkString
;
1463 // check field type:
1464 const xub_StrLen nIdx
= static_cast<const SwFldPortion
*>(pPor
)->IsFollow() ?
1467 const SwTxtAttr
* pHint
= mpPorInfo
->mrTxtPainter
.GetAttr( nIdx
);
1468 const SwField
* pFld
= 0;
1469 if ( pHint
&& RES_TXTATR_FIELD
== pHint
->Which() )
1471 pFld
= (SwField
*)pHint
->GetFld().GetFld();
1472 if ( RES_GETREFFLD
== pFld
->Which() )
1474 nPDFType
= vcl::PDFWriter::Link
;
1475 aPDFType
= aLinkString
;
1477 else if ( RES_AUTHORITY
== pFld
->Which() )
1479 nPDFType
= vcl::PDFWriter::BibEntry
;
1480 aPDFType
= aBibEntryString
;
1488 case POR_TABCENTER
:
1489 case POR_TABDECIMAL
:
1490 nPDFType
= vcl::PDFWriter::NonStructElement
;
1494 if ( USHRT_MAX
!= nPDFType
)
1496 BeginTag( static_cast<vcl::PDFWriter::StructElement
>(nPDFType
), aPDFType
);
1501 * static SwTaggedPDFHelper::IsExportTaggedPDF
1503 bool SwTaggedPDFHelper::IsExportTaggedPDF( const OutputDevice
& rOut
)
1505 vcl::PDFExtOutDevData
* pPDFExtOutDevData
= PTR_CAST( vcl::PDFExtOutDevData
, rOut
.GetExtOutDevData() );
1506 return pPDFExtOutDevData
&& pPDFExtOutDevData
->GetIsExportTaggedPDF();
1510 * SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper()
1512 SwEnhancedPDFExportHelper::SwEnhancedPDFExportHelper( SwEditShell
& rSh
,
1514 const rtl::OUString
& rPageRange
,
1515 bool bSkipEmptyPages
,
1516 bool bEditEngineOnly
)
1520 mbSkipEmptyPages( bSkipEmptyPages
),
1521 mbEditEngineOnly( bEditEngineOnly
)
1523 if ( rPageRange
.getLength() )
1524 pPageRange
= new MultiSelection( rPageRange
);
1526 aTableColumnsMap
.clear();
1528 aNumListIdMap
.clear();
1529 aNumListBodyIdMap
.clear();
1530 aFrmTagIdMap
.clear();
1533 aStructStack
.clear();
1536 const BYTE nScript
= (BYTE
)GetI18NScriptTypeOfLanguage( (USHORT
)GetAppLanguage() );
1537 USHORT nLangRes
= RES_CHRATR_LANGUAGE
;
1539 if ( i18n::ScriptType::ASIAN
== nScript
)
1540 nLangRes
= RES_CHRATR_CJK_LANGUAGE
;
1541 else if ( i18n::ScriptType::COMPLEX
== nScript
)
1542 nLangRes
= RES_CHRATR_CTL_LANGUAGE
;
1544 eLanguageDefault
= static_cast<const SvxLanguageItem
*>(&mrSh
.GetDoc()->GetDefault( nLangRes
))->GetLanguage();
1546 EnhancedPDFExport();
1549 SwEnhancedPDFExportHelper::~SwEnhancedPDFExportHelper()
1555 * SwEnhancedPDFExportHelper::EnhancedPDFExport()
1557 void SwEnhancedPDFExportHelper::EnhancedPDFExport()
1559 vcl::PDFExtOutDevData
* pPDFExtOutDevData
=
1560 PTR_CAST( vcl::PDFExtOutDevData
, mrOut
.GetExtOutDevData() );
1562 if ( !pPDFExtOutDevData
)
1566 // set the document locale
1568 com::sun::star::lang::Locale aDocLocale
= MsLangId::convertLanguageToLocale( SwEnhancedPDFExportHelper::GetDefaultLanguage() );
1569 pPDFExtOutDevData
->SetDocumentLocale( aDocLocale
);
1572 // Prepare the output device:
1574 mrOut
.Push( PUSH_MAPMODE
);
1575 MapMode
aMapMode( mrOut
.GetMapMode() );
1576 aMapMode
.SetMapUnit( MAP_TWIP
);
1577 mrOut
.SetMapMode( aMapMode
);
1580 // Create new cursor and lock the view:
1582 SwDoc
* pDoc
= mrSh
.GetDoc();
1583 mrSh
.SwCrsrShell::Push();
1584 mrSh
.SwCrsrShell::ClearMark();
1585 const BOOL bOldLockView
= mrSh
.IsViewLocked();
1586 mrSh
.LockView( TRUE
);
1588 if ( !mbEditEngineOnly
)
1593 if ( pPDFExtOutDevData
->GetIsExportNotes() )
1595 SwFieldType
* pType
= mrSh
.GetFldType( RES_POSTITFLD
, aEmptyStr
);
1596 SwClientIter
aIter( *pType
);
1597 const SwClient
* pFirst
= aIter
.GoStart();
1600 if( ((SwFmtFld
*)pFirst
)->GetTxtFld() &&
1601 ((SwFmtFld
*)pFirst
)->IsFldInDoc())
1603 const SwTxtNode
* pTNd
=
1604 (SwTxtNode
*)((SwFmtFld
*)pFirst
)->GetTxtFld()->GetpTxtNode();
1605 ASSERT( 0 != pTNd
, "Enhanced pdf export - text node is missing" )
1607 // 1. Check if the whole paragraph is hidden
1608 // 2. Move to the field
1609 // 3. Check for hidden text attribute
1610 if ( !pTNd
->IsHidden() &&
1611 mrSh
.GotoFld( *(SwFmtFld
*)pFirst
) &&
1612 !mrSh
.SelectHiddenRange() )
1615 const SwRect
& rNoteRect
= mrSh
.GetCharRect();
1618 const sal_Int32 nNotePageNum
= CalcOutputPageNum( rNoteRect
);
1619 if ( -1 != nNotePageNum
)
1624 // Use the NumberFormatter to get the date string:
1625 const SwPostItField
* pField
= (SwPostItField
*)((SwFmtFld
*)pFirst
)->GetFld();
1626 SvNumberFormatter
* pNumFormatter
= pDoc
->GetNumberFormatter();
1627 const Date
aDateDiff( pField
->GetDate() -
1628 *pNumFormatter
->GetNullDate() );
1629 const ULONG nFormat
=
1630 pNumFormatter
->GetStandardFormat( NUMBERFORMAT_DATE
, pField
->GetLanguage() );
1633 pNumFormatter
->GetOutputString( aDateDiff
.GetDate(), nFormat
, sDate
, &pColor
);
1635 // The title should consist of the author and the date:
1636 String
sTitle( pField
->GetPar1() );
1637 sTitle
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " ) );
1639 aNote
.Title
= sTitle
;
1640 // Guess what the contents contains...
1641 aNote
.Contents
= pField
->GetTxt();
1644 pPDFExtOutDevData
->CreateNote( rNoteRect
.SVRect(), aNote
, nNotePageNum
);
1649 mrSh
.SwCrsrShell::ClearMark();
1656 SwGetINetAttrs aArr
;
1657 const sal_uInt16 nHyperLinkCount
= mrSh
.GetINetAttrs( aArr
);
1658 for( sal_uInt16 n
= 0; n
< nHyperLinkCount
; ++n
)
1660 SwGetINetAttr
* p
= aArr
[ n
];
1661 ASSERT( 0 != p
, "Enhanced pdf export - SwGetINetAttr is missing" )
1663 const SwTxtNode
* pTNd
= p
->rINetAttr
.GetpTxtNode();
1664 ASSERT( 0 != pTNd
, "Enhanced pdf export - text node is missing" )
1666 // 1. Check if the whole paragraph is hidden
1667 // 2. Move to the hyperlink
1668 // 3. Check for hidden text attribute
1669 if ( !pTNd
->IsHidden() &&
1670 mrSh
.GotoINetAttr( p
->rINetAttr
) &&
1671 !mrSh
.SelectHiddenRange() )
1673 // Select the hyperlink:
1674 mrSh
.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS
);
1675 if ( mrSh
.SwCrsrShell::SelectTxtAttr( RES_TXTATR_INETFMT
, sal_True
) )
1677 // First, we create the destination, because there may be more
1678 // than one link to this destination:
1679 String
aURL( INetURLObject::decode(
1680 p
->rINetAttr
.GetINetFmt().GetValue(),
1682 INetURLObject::DECODE_UNAMBIGUOUS
,
1683 RTL_TEXTENCODING_UTF8
) );
1685 // We have to distinguish between intern and real URLs
1686 const bool bIntern
= '#' == aURL
.GetChar( 0 );
1688 // _GetCrsr() is a SwShellCrsr, which is derived from
1689 // SwSelPaintRects, therefore the rectangles of the current
1690 // selection can be easily obtained:
1691 // Note: We make a copy of the rectangles, because they may
1692 // be deleted again in JumpToSwMark.
1694 aTmp
.Insert( mrSh
.SwCrsrShell::_GetCrsr(), 0 );
1695 ASSERT( aTmp
.Count() > 0, "Enhanced pdf export - rectangles are missing" )
1697 // Create the destination for internal links:
1698 sal_Int32 nDestId
= -1;
1702 mrSh
.SwCrsrShell::ClearMark();
1703 JumpToSwMark( &mrSh
, aURL
);
1705 // Destination Rectangle
1706 const SwRect
& rDestRect
= mrSh
.GetCharRect();
1708 // Destination PageNum
1709 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
1711 // Destination Export
1712 if ( -1 != nDestPageNum
)
1713 nDestId
= pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
1716 if ( !bIntern
|| -1 != nDestId
)
1718 // --> FME 2005-05-09 #i44368# Links in Header/Footer
1719 const SwPosition
aPos( *pTNd
);
1720 const bool bHeaderFooter
= pDoc
->IsInHeaderFooter( aPos
.nNode
);
1723 // Create links for all selected rectangles:
1724 const USHORT nNumOfRects
= aTmp
.Count();
1725 for ( USHORT i
= 0; i
< nNumOfRects
; ++i
)
1728 const SwRect
& rLinkRect( aTmp
[ i
] );
1731 const sal_Int32 nLinkPageNum
= CalcOutputPageNum( rLinkRect
);
1733 if ( -1 != nLinkPageNum
)
1736 const sal_Int32 nLinkId
=
1737 pPDFExtOutDevData
->CreateLink( rLinkRect
.SVRect(), nLinkPageNum
);
1739 // Store link info for tagged pdf output:
1740 const IdMapEntry
aLinkEntry( rLinkRect
, nLinkId
);
1741 aLinkIdMap
.push_back( aLinkEntry
);
1743 // Connect Link and Destination:
1745 pPDFExtOutDevData
->SetLinkDest( nLinkId
, nDestId
);
1747 pPDFExtOutDevData
->SetLinkURL( nLinkId
, aURL
);
1749 // --> FME 2005-05-09 #i44368# Links in Header/Footer
1750 if ( bHeaderFooter
)
1751 MakeHeaderFooterLinks( *pPDFExtOutDevData
, *pTNd
, rLinkRect
, nDestId
, aURL
, bIntern
);
1758 mrSh
.SwCrsrShell::ClearMark();
1762 // HYPERLINKS (Graphics, Frames, OLEs )
1764 const SwSpzFrmFmts
* pTbl
= pDoc
->GetSpzFrmFmts();
1765 const sal_uInt16 nSpzFrmFmtsCount
= pTbl
->Count();
1766 for( sal_uInt16 n
= 0; n
< nSpzFrmFmtsCount
; ++n
)
1768 const SwFrmFmt
* pFrmFmt
= (*pTbl
)[n
];
1769 const SfxPoolItem
* pItem
;
1770 if ( RES_DRAWFRMFMT
!= pFrmFmt
->Which() &&
1771 SFX_ITEM_SET
== pFrmFmt
->GetAttrSet().GetItemState( RES_URL
, TRUE
, &pItem
) )
1773 String
aURL( static_cast<const SwFmtURL
*>(pItem
)->GetURL() );
1774 const bool bIntern
= '#' == aURL
.GetChar( 0 );
1776 // Create the destination for internal links:
1777 sal_Int32 nDestId
= -1;
1781 mrSh
.SwCrsrShell::ClearMark();
1782 JumpToSwMark( &mrSh
, aURL
);
1784 // Destination Rectangle
1785 const SwRect
& rDestRect
= mrSh
.GetCharRect();
1787 // Destination PageNum
1788 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
1790 // Destination Export
1791 if ( -1 != nDestPageNum
)
1792 nDestId
= pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
1795 if ( !bIntern
|| -1 != nDestId
)
1798 const SwRect aLinkRect
= pFrmFmt
->FindLayoutRect( sal_False
, &aNullPt
);
1801 const sal_Int32 nLinkPageNum
= CalcOutputPageNum( aLinkRect
);
1804 if ( -1 != nLinkPageNum
)
1806 const sal_Int32 nLinkId
=
1807 pPDFExtOutDevData
->CreateLink( aLinkRect
.SVRect(), nLinkPageNum
);
1809 // Connect Link and Destination:
1811 pPDFExtOutDevData
->SetLinkDest( nLinkId
, nDestId
);
1813 pPDFExtOutDevData
->SetLinkURL( nLinkId
, aURL
);
1815 // --> FME 2005-05-09 #i44368# Links in Header/Footer
1816 const SwFmtAnchor
&rAnch
= pFrmFmt
->GetAnchor();
1817 if ( FLY_PAGE
!= rAnch
.GetAnchorId() )
1819 const SwPosition
* pPosition
= rAnch
.GetCntntAnchor();
1820 if ( pPosition
&& pDoc
->IsInHeaderFooter( pPosition
->nNode
) )
1822 const SwTxtNode
* pTNd
= pPosition
->nNode
.GetNode().GetTxtNode();
1824 MakeHeaderFooterLinks( *pPDFExtOutDevData
, *pTNd
, aLinkRect
, nDestId
, aURL
, bIntern
);
1831 mrSh
.SwCrsrShell::ClearMark();
1837 SwFieldType
* pType
= mrSh
.GetFldType( RES_GETREFFLD
, aEmptyStr
);
1838 SwClientIter
aIter( *pType
);
1839 const SwClient
* pFirst
= aIter
.GoStart();
1842 if( ((SwFmtFld
*)pFirst
)->GetTxtFld() &&
1843 ((SwFmtFld
*)pFirst
)->IsFldInDoc())
1845 const SwTxtNode
* pTNd
=
1846 (SwTxtNode
*)((SwFmtFld
*)pFirst
)->GetTxtFld()->GetpTxtNode();
1847 ASSERT( 0 != pTNd
, "Enhanced pdf export - text node is missing" )
1849 // 1. Check if the whole paragraph is hidden
1850 // 2. Move to the field
1851 // 3. Check for hidden text attribute
1852 if ( !pTNd
->IsHidden() &&
1853 mrSh
.GotoFld( *(SwFmtFld
*)pFirst
) &&
1854 !mrSh
.SelectHiddenRange() )
1856 // Select the field:
1857 mrSh
.SwCrsrShell::SetMark();
1858 mrSh
.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS
);
1862 aTmp
.Insert( mrSh
.SwCrsrShell::_GetCrsr(), 0 );
1863 ASSERT( aTmp
.Count() > 0, "Enhanced pdf export - rectangles are missing" )
1865 mrSh
.SwCrsrShell::ClearMark();
1867 // Destination Rectangle
1868 const SwGetRefField
* pField
=
1869 (SwGetRefField
*)((SwFmtFld
*)pFirst
)->GetFld();
1870 const String
& rRefName
= pField
->GetSetRefName();
1871 mrSh
.GotoRefMark( rRefName
, pField
->GetSubType(), pField
->GetSeqNo() );
1872 const SwRect
& rDestRect
= mrSh
.GetCharRect();
1874 // Destination PageNum
1875 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
1877 if ( -1 != nDestPageNum
)
1879 // Destination Export
1880 const sal_Int32 nDestId
= pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
1882 // --> FME 2005-05-09 #i44368# Links in Header/Footer
1883 const SwPosition
aPos( *pTNd
);
1884 const bool bHeaderFooter
= pDoc
->IsInHeaderFooter( aPos
.nNode
);
1887 // Create links for all selected rectangles:
1888 const USHORT nNumOfRects
= aTmp
.Count();
1889 for ( USHORT i
= 0; i
< nNumOfRects
; ++i
)
1892 const SwRect
& rLinkRect( aTmp
[ i
] );
1895 const sal_Int32 nLinkPageNum
= CalcOutputPageNum( rLinkRect
);
1897 if ( -1 != nLinkPageNum
)
1900 const sal_Int32 nLinkId
=
1901 pPDFExtOutDevData
->CreateLink( rLinkRect
.SVRect(), nLinkPageNum
);
1903 // Store link info for tagged pdf output:
1904 const IdMapEntry
aLinkEntry( rLinkRect
, nLinkId
);
1905 aLinkIdMap
.push_back( aLinkEntry
);
1907 // Connect Link and Destination:
1908 pPDFExtOutDevData
->SetLinkDest( nLinkId
, nDestId
);
1910 // --> FME 2005-05-09 #i44368# Links in Header/Footer
1911 if ( bHeaderFooter
)
1913 const String aDummy
;
1914 MakeHeaderFooterLinks( *pPDFExtOutDevData
, *pTNd
, rLinkRect
, nDestId
, aDummy
, true );
1923 mrSh
.SwCrsrShell::ClearMark();
1929 const USHORT nFtnCount
= pDoc
->GetFtnIdxs().Count();
1930 for ( USHORT nIdx
= 0; nIdx
< nFtnCount
; ++nIdx
)
1932 // Set cursor to text node that contains the footnote:
1933 const SwTxtFtn
* pTxtFtn
= pDoc
->GetFtnIdxs()[ nIdx
];
1934 SwTxtNode
& rTNd
= const_cast<SwTxtNode
&>(pTxtFtn
->GetTxtNode());
1936 mrSh
._GetCrsr()->GetPoint()->nNode
= rTNd
;
1937 mrSh
._GetCrsr()->GetPoint()->nContent
.Assign( &rTNd
, *pTxtFtn
->GetStart() );
1939 // 1. Check if the whole paragraph is hidden
1940 // 2. Check for hidden text attribute
1941 if ( static_cast<const SwTxtNode
&>(rTNd
).IsHidden() ||
1942 mrSh
.SelectHiddenRange() )
1945 SwCrsrSaveState
aSaveState( *mrSh
._GetCrsr() );
1947 // Select the footnote:
1948 mrSh
.SwCrsrShell::SetMark();
1949 mrSh
.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS
);
1953 aTmp
.Insert( mrSh
.SwCrsrShell::_GetCrsr(), 0 );
1954 ASSERT( aTmp
.Count() > 0, "Enhanced pdf export - rectangles are missing" )
1955 const SwRect
aLinkRect( aTmp
[ 0 ] );
1957 mrSh
._GetCrsr()->RestoreSavePos();
1958 mrSh
.SwCrsrShell::ClearMark();
1960 // Goto footnote text:
1961 if ( mrSh
.GotoFtnTxt() )
1964 const sal_Int32 nLinkPageNum
= CalcOutputPageNum( aLinkRect
);
1966 if ( -1 != nLinkPageNum
)
1969 const sal_Int32 nLinkId
=
1970 pPDFExtOutDevData
->CreateLink( aLinkRect
.SVRect(), nLinkPageNum
);
1972 // Store link info for tagged pdf output:
1973 const IdMapEntry
aLinkEntry( aLinkRect
, nLinkId
);
1974 aLinkIdMap
.push_back( aLinkEntry
);
1976 // Destination Rectangle
1977 const SwRect
& rDestRect
= mrSh
.GetCharRect();
1979 // Destination PageNum
1980 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
1982 if ( -1 != nDestPageNum
)
1984 // Destination Export
1985 const sal_Int32 nDestId
= pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
1987 // Connect Link and Destination:
1988 pPDFExtOutDevData
->SetLinkDest( nLinkId
, nDestId
);
1997 if( pPDFExtOutDevData
->GetIsExportBookmarks() )
1999 typedef std::pair
< sal_Int8
, sal_Int32
> StackEntry
;
2000 std::stack
< StackEntry
> aOutlineStack
;
2001 aOutlineStack
.push( StackEntry( -1, -1 ) ); // push default value
2003 const sal_uInt16 nOutlineCount
=
2004 static_cast<sal_uInt16
>(mrSh
.getIDocumentOutlineNodesAccess()->getOutlineNodesCount());
2005 for ( sal_uInt16 i
= 0; i
< nOutlineCount
; ++i
)
2007 // Check if outline is hidden
2008 const SwTxtNode
* pTNd
= mrSh
.GetNodes().GetOutLineNds()[ i
]->GetTxtNode();
2009 ASSERT( 0 != pTNd
, "Enhanced pdf export - text node is missing" )
2011 if ( pTNd
->IsHidden() ||
2012 // --> FME 2005-01-10 #i40292# Skip empty outlines:
2013 0 == pTNd
->GetTxt().Len() )
2017 // Get parent id from stack:
2018 const sal_Int8 nLevel
= (sal_Int8
)mrSh
.getIDocumentOutlineNodesAccess()->getOutlineLevel( i
);
2019 sal_Int8 nLevelOnTopOfStack
= aOutlineStack
.top().first
;
2020 while ( nLevelOnTopOfStack
>= nLevel
&&
2021 nLevelOnTopOfStack
!= -1 )
2023 aOutlineStack
.pop();
2024 nLevelOnTopOfStack
= aOutlineStack
.top().first
;
2026 const sal_Int32 nParent
= aOutlineStack
.top().second
;
2028 // Destination rectangle
2029 mrSh
.GotoOutline(i
);
2030 const SwRect
& rDestRect
= mrSh
.GetCharRect();
2032 // Destination PageNum
2033 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
2035 if ( -1 != nDestPageNum
)
2037 // Destination Export
2038 const sal_Int32 nDestId
=
2039 pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
2041 // Outline entry text
2042 const String
& rEntry
= mrSh
.getIDocumentOutlineNodesAccess()->getOutlineText( i
);
2044 // Create a new outline item:
2045 const sal_Int32 nOutlineId
=
2046 pPDFExtOutDevData
->CreateOutlineItem( nParent
, rEntry
, nDestId
);
2048 // Push current level and nOutlineId on stack:
2049 aOutlineStack
.push( StackEntry( nLevel
, nOutlineId
) );
2054 if( pPDFExtOutDevData
->GetIsExportNamedDestinations() )
2056 //---> i56629 the iteration to convert the OOo bookmark (#bookmark)
2057 // into PDF named destination, see section 8.2.1 in PDF 1.4 spec
2059 // 1. a name for the destination, formed from the standard OOo bookmark name
2060 // 2. the destination, obtained from where the bookmark destination lies
2061 IDocumentMarkAccess
* const pMarkAccess
= mrSh
.GetDoc()->getIDocumentMarkAccess();
2062 for(IDocumentMarkAccess::const_iterator_t ppMark
= pMarkAccess
->getBookmarksBegin();
2063 ppMark
!= pMarkAccess
->getBookmarksEnd();
2067 const ::sw::mark::IMark
* pBkmk
= ppMark
->get();
2068 mrSh
.SwCrsrShell::ClearMark();
2069 rtl::OUString sBkName
= pBkmk
->GetName();
2072 JumpToSwMark( &mrSh
, sBkName
);
2074 // Destination Rectangle
2075 const SwRect
& rDestRect
= mrSh
.GetCharRect();
2077 // Destination PageNum
2078 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
2080 // Destination Export
2081 if ( -1 != nDestPageNum
)
2082 pPDFExtOutDevData
->CreateNamedDest( sBkName
, rDestRect
.SVRect(), nDestPageNum
);
2084 mrSh
.SwCrsrShell::ClearMark();
2091 // LINKS FROM EDITENGINE
2093 std::vector
< vcl::PDFExtOutDevBookmarkEntry
>& rBookmarks
= pPDFExtOutDevData
->GetBookmarks();
2094 std::vector
< vcl::PDFExtOutDevBookmarkEntry
>::const_iterator aIBeg
= rBookmarks
.begin();
2095 const std::vector
< vcl::PDFExtOutDevBookmarkEntry
>::const_iterator aIEnd
= rBookmarks
.end();
2096 while ( aIBeg
!= aIEnd
)
2098 String
aBookmarkName( aIBeg
->aBookmark
);
2099 const bool bIntern
= '#' == aBookmarkName
.GetChar( 0 );
2102 aBookmarkName
.Erase( 0, 1 );
2103 JumpToSwMark( &mrSh
, aBookmarkName
);
2105 // Destination Rectangle
2106 const SwRect
& rDestRect
= mrSh
.GetCharRect();
2108 // Destination PageNum
2109 const sal_Int32 nDestPageNum
= CalcOutputPageNum( rDestRect
);
2111 if ( -1 != nDestPageNum
)
2113 // Destination Export
2114 const sal_Int32 nDestId
=
2115 pPDFExtOutDevData
->CreateDest( rDestRect
.SVRect(), nDestPageNum
);
2117 // Connect Link and Destination:
2118 pPDFExtOutDevData
->SetLinkDest( aIBeg
->nLinkId
, nDestId
);
2122 pPDFExtOutDevData
->SetLinkURL( aIBeg
->nLinkId
, aBookmarkName
);
2129 // Restore view, cursor, and outdev:
2130 mrSh
.LockView( bOldLockView
);
2131 mrSh
.SwCrsrShell::Pop( FALSE
);
2136 * SwEnhancedPDFExportHelper::CalcOutputPageNum()
2138 sal_Int32
SwEnhancedPDFExportHelper::CalcOutputPageNum( const SwRect
& rRect
) const
2140 // Document page numbers are 0, 1, 2, ...
2141 const sal_Int32 nPageNumOfRect
= mrSh
.GetPageNumAndSetOffsetForPDF( mrOut
, rRect
);
2144 if ( -1 == nPageNumOfRect
|| ( !pPageRange
&& !mbSkipEmptyPages
) )
2145 return nPageNumOfRect
;
2147 // pPageRange page numbers are 1, 2, 3, ...
2148 if ( pPageRange
&& !pPageRange
->IsSelected( nPageNumOfRect
+ 1 ) )
2151 // What will be the page number of page nPageNumOfRect in the output doc?
2152 sal_Int32 nOutputPageNum
= -1;
2153 const SwRootFrm
* pRootFrm
= mrSh
.GetLayout();
2154 const SwPageFrm
* pCurrPage
= static_cast<const SwPageFrm
*>(pRootFrm
->Lower());
2156 for ( sal_Int32 nPageIndex
= 0;
2157 nPageIndex
<= nPageNumOfRect
&& pCurrPage
;
2160 if ( ( !pPageRange
|| pPageRange
->IsSelected( nPageIndex
+ 1 ) ) &&
2161 ( !mbSkipEmptyPages
|| !pCurrPage
->IsEmptyPage() ) )
2164 pCurrPage
= static_cast<const SwPageFrm
*>(pCurrPage
->GetNext());
2167 // pdf export page numbers are 0, 1, 2, ...
2168 return nOutputPageNum
;
2171 void SwEnhancedPDFExportHelper::MakeHeaderFooterLinks( vcl::PDFExtOutDevData
& rPDFExtOutDevData
,
2172 const SwTxtNode
& rTNd
,
2173 const SwRect
& rLinkRect
,
2176 bool bIntern
) const
2178 // We assume, that the primary link has just been exported. Therefore
2179 // the offset of the link rectangle calculates as follows:
2180 const Point aOffset
= rLinkRect
.Pos() + mrOut
.GetMapMode().GetOrigin();
2182 SwClientIter
aClientIter( const_cast<SwTxtNode
&>(rTNd
) );
2183 SwClient
* pLast
= aClientIter
.GoStart();
2187 if ( pLast
->ISA( SwTxtFrm
) )
2189 // Add offset to current page:
2190 SwTxtFrm
* pTmpFrm
= static_cast<SwTxtFrm
*>(pLast
);
2191 const SwPageFrm
* pPageFrm
= pTmpFrm
->FindPageFrm();
2192 SwRect
aHFLinkRect( rLinkRect
);
2193 aHFLinkRect
.Pos() = pPageFrm
->Frm().Pos() + aOffset
;
2195 // #i97135# the gcc_x64 optimizer gets aHFLinkRect != rLinkRect wrong
2196 // fool it by comparing the position only (the width and height are the
2198 if ( aHFLinkRect
.Pos() != rLinkRect
.Pos() )
2201 const sal_Int32 nHFLinkPageNum
= CalcOutputPageNum( aHFLinkRect
);
2203 if ( -1 != nHFLinkPageNum
)
2206 const sal_Int32 nHFLinkId
=
2207 rPDFExtOutDevData
.CreateLink( aHFLinkRect
.SVRect(), nHFLinkPageNum
);
2209 // Connect Link and Destination:
2211 rPDFExtOutDevData
.SetLinkDest( nHFLinkId
, nDestId
);
2213 rPDFExtOutDevData
.SetLinkURL( nHFLinkId
, rURL
);
2218 pLast
= ++aClientIter
;