Update ooo320-m1
[ooovba.git] / sw / source / core / text / EnhancedPDFExportHelper.cxx
blobd6241c775f5122f164a6080975ae1ca9dd3844c4
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>
36 #endif
37 #include <EnhancedPDFExportHelper.hxx>
38 #include <hintids.hxx>
40 #ifndef _OUTDEV_HXX
41 #include <vcl/outdev.hxx>
42 #endif
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>
51 #include <frmatr.hxx>
52 #include <paratr.hxx>
53 #include <ndtxt.hxx>
54 #include <ndole.hxx>
55 #include <section.hxx>
56 #include <tox.hxx>
57 #include <fmtfld.hxx>
58 #include <txtinet.hxx>
59 #include <fmtinfmt.hxx>
60 #include <fchrfmt.hxx>
61 #include <charfmt.hxx>
62 #include <fmtanchr.hxx>
63 #include <fmturl.hxx>
64 #include <editsh.hxx>
65 #include <viscrs.hxx>
66 #include <txtfld.hxx>
67 #include <reffld.hxx>
68 #include <doc.hxx>
69 #include <docary.hxx>
70 #include <crsskip.hxx>
71 #include <mdiexp.hxx>
72 #include <docufld.hxx>
73 #include <ftnidx.hxx>
74 #include <txtftn.hxx>
75 #include <fmtftn.hxx>
76 #include <rootfrm.hxx>
77 #include <pagefrm.hxx>
78 #include <txtfrm.hxx>
79 #include <tabfrm.hxx>
80 #include <rowfrm.hxx>
81 #include <cellfrm.hxx>
82 #include <sectfrm.hxx>
83 #include <flyfrm.hxx>
84 #include <notxtfrm.hxx>
85 #include <porfld.hxx>
86 #include <SwStyleNameMapper.hxx>
87 #include <itrpaint.hxx>
88 #include "i18npool/mslangid.hxx"
89 #include <IMark.hxx>
90 #include <SwNodeNum.hxx>
92 #include <stack>
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;
109 #ifndef PRODUCT
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
128 USHORT nElement;
129 std::vector< USHORT >::iterator aIter;
130 for ( aIter = aStructStack.begin(); aIter != aStructStack.end(); ++aIter )
132 nElement = *aIter;
136 #endif
138 namespace
140 // ODF Style Names:
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");
148 // PDF Tag Names:
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 )
184 bool bRet = false;
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();
192 String sStyleName;
193 SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
194 bRet = sStyleName == aTableHeadingName;
197 return bRet;
200 // List all frames for which the NonStructElement tag is set:
201 bool lcl_IsInNonStructEnv( const SwFrm& rFrm )
203 bool bRet = false;
205 if ( 0 != rFrm.FindFooterOrHeader() &&
206 !rFrm.IsHeaderFrm() && !rFrm.IsFooterFrm() )
208 bRet = true;
210 else if ( rFrm.IsInTab() && !rFrm.IsTabFrm() )
212 const SwTabFrm* pTabFrm = rFrm.FindTabFrm();
213 if ( rFrm.GetUpper() != pTabFrm &&
214 pTabFrm->IsFollow() && pTabFrm->IsInHeadline( rFrm ) )
215 bRet = true;
218 return bRet;
221 // Generate key from frame for reopening tags:
222 void* lcl_GetKeyFromFrame( const SwFrm& rFrm )
224 void* pKey = 0;
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 );
243 return pKey;
246 bool lcl_HasPreviousParaSameNumRule( const SwTxtNode& rNode )
248 bool bRet = false;
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) ) )
257 --aIdx;
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()))
268 bRet = true;
270 break;
273 pNode = &aIdx.GetNode();
275 return bRet;
278 } // end namespace
281 * SwTaggedPDFHelper::SwTaggedPDFHelper()
283 SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info* pNumInfo,
284 const Frm_Info* pFrmInfo,
285 const Por_Info* pPorInfo,
286 OutputDevice& rOut )
287 : nEndStructureElement( 0 ),
288 nRestoreCurrentTag( -1 ),
289 mpNumInfo( pNumInfo ),
290 mpFrmInfo( pFrmInfo ),
291 mpPorInfo( pPorInfo )
293 mpPDFExtOutDevData =
294 PTR_CAST( vcl::PDFExtOutDevData, rOut.GetExtOutDevData() );
296 if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
298 #ifndef PRODUCT
299 sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
300 lcl_DBGCheckStack();
301 #endif
302 if ( mpNumInfo )
303 BeginNumberedListStructureElements();
304 else if ( mpFrmInfo )
305 BeginBlockStructureElements();
306 else if ( mpPorInfo )
307 BeginInlineStructureElements();
308 else
309 BeginTag( vcl::PDFWriter::NonStructElement, aEmptyString );
311 #ifndef PRODUCT
312 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
313 lcl_DBGCheckStack();
314 #endif
320 * SwTaggedPDFHelper::~SwTaggedPDFHelper()
322 SwTaggedPDFHelper::~SwTaggedPDFHelper()
324 if ( mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportTaggedPDF() )
326 #ifndef PRODUCT
327 sal_Int32 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
328 lcl_DBGCheckStack();
329 #endif
330 EndStructureElements();
332 #ifndef PRODUCT
333 nCurrentStruct = mpPDFExtOutDevData->GetCurrentStructureElement();
334 lcl_DBGCheckStack();
335 #endif
341 * SwTaggedPDFHelper::CheckReopenTag()
343 bool SwTaggedPDFHelper::CheckReopenTag()
345 bool bRet = false;
346 sal_Int32 nReopenTag = -1;
347 bool bContinue = false; // in some cases we just have to reopen a tag without early returning
349 if ( mpFrmInfo )
351 const SwFrm& rFrm = mpFrmInfo->mrFrm;
352 const SwFrm* pKeyFrm = 0;
353 void* pKey = 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 ) ) )
367 pKeyFrm = &rFrm;
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();
378 bContinue = true;
382 if ( pKeyFrm )
384 pKey = lcl_GetKeyFromFrame( *pKeyFrm );
386 if ( pKey )
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" )
401 #ifndef PRODUCT
402 aStructStack.push_back( 99 );
403 #endif
405 bRet = bSuccess;
408 return bRet && !bContinue;
413 * SwTaggedPDFHelper::CheckRestoreTag()
415 bool SwTaggedPDFHelper::CheckRestoreTag() const
417 bool bRet = false;
418 if ( nRestoreCurrentTag != -1 )
420 const bool bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement( nRestoreCurrentTag );
421 (void)bSuccess;
422 ASSERT( bSuccess, "Failed to restore reopened tag" )
424 #ifndef PRODUCT
425 aStructStack.pop_back();
426 #endif
428 bRet = true;
431 return bRet;
436 * SwTaggedPDFHelper::BeginTag()
438 void SwTaggedPDFHelper::BeginTag( vcl::PDFWriter::StructElement eType, const String& rString )
440 // write new tag
441 const sal_Int32 nId = mpPDFExtOutDevData->BeginStructureElement( eType, rtl::OUString( rString ) );
442 ++nEndStructureElement;
444 #ifndef PRODUCT
445 aStructStack.push_back( static_cast<USHORT>(eType) );
446 #endif
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
456 if ( mpNumInfo )
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 );
485 if ( pKey )
487 FrmTagIdMap& rFrmTagIdMap = SwEnhancedPDFExportHelper::GetFrmTagIdMap();
488 rFrmTagIdMap[ pKey ] = nId;
493 SetAttributes( eType );
498 * SwTaggedPDFHelper::EndTag()
500 void SwTaggedPDFHelper::EndTag()
502 mpPDFExtOutDevData->EndStructureElement();
504 #ifndef PRODUCT
505 aStructStack.pop_back();
506 #endif
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;
518 sal_Int32 nVal;
521 * ATTRIBUTES FOR BLSE
523 if ( mpFrmInfo )
525 const SwFrm* pFrm = &mpFrmInfo->mrFrm;
526 SWRECTFN( pFrm )
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;
537 bool bWidth = false;
538 bool bHeight = false;
539 bool bBox = false;
540 bool bRowSpan = false;
543 // Check which attributes to set:
545 switch ( eType )
547 case vcl::PDFWriter::Document :
548 bWritingMode = true;
549 break;
551 case vcl::PDFWriter::Table :
552 bPlacement =
553 bWritingMode =
554 bSpaceBefore =
555 bSpaceAfter =
556 bStartIndent =
557 bEndIndent =
558 bWidth =
559 bHeight =
560 bBox = true;
561 break;
563 case vcl::PDFWriter::TableRow :
564 bPlacement =
565 bWritingMode = true;
566 break;
568 case vcl::PDFWriter::TableHeader :
569 case vcl::PDFWriter::TableData :
570 bPlacement =
571 bWritingMode =
572 bWidth =
573 bHeight =
574 bRowSpan = true;
575 break;
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 :
588 bPlacement =
589 bWritingMode =
590 bSpaceBefore =
591 bSpaceAfter =
592 bStartIndent =
593 bEndIndent =
594 bTextIndent =
595 bTextAlign = true;
596 break;
598 case vcl::PDFWriter::Formula :
599 case vcl::PDFWriter::Figure :
600 bPlacement =
601 bAlternateText =
602 bWidth =
603 bHeight =
604 bBox = true;
605 break;
606 default :
607 break;
611 // Set the attributes:
613 if ( bPlacement )
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 );
623 if ( bWritingMode )
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 );
635 if ( bSpaceBefore )
637 nVal = (pFrm->*fnRect->fnGetTopMargin)();
638 if ( 0 != nVal )
639 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceBefore, nVal );
642 if ( bSpaceAfter )
644 nVal = (pFrm->*fnRect->fnGetBottomMargin)();
645 if ( 0 != nVal )
646 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::SpaceAfter, nVal );
649 if ( bStartIndent )
651 nVal = (pFrm->*fnRect->fnGetLeftMargin)();
652 if ( 0 != nVal )
653 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::StartIndent, nVal );
656 if ( bEndIndent )
658 nVal = (pFrm->*fnRect->fnGetRightMargin)();
659 if ( 0 != nVal )
660 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::EndIndent, nVal );
663 if ( bTextIndent )
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();
669 if ( 0 != nVal )
670 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::TextIndent, nVal );
673 if ( bTextAlign )
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 :
686 vcl::PDFWriter::End;
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 );
706 if ( bWidth )
708 nVal = (pFrm->Frm().*fnRect->fnGetWidth)();
709 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Width, nVal );
712 if ( bHeight )
714 nVal = (pFrm->Frm().*fnRect->fnGetHeight)();
715 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::Height, nVal );
718 if ( bBox )
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() );
728 if ( bRowSpan )
730 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(pFrm);
731 if ( pThisCell )
733 nVal = pThisCell->GetTabBox()->getRowSpan();
734 if ( nVal > 1 )
735 mpPDFExtOutDevData->SetStructureAttributeNumerical( vcl::PDFWriter::RowSpan, nVal );
737 // calculate colspan:
738 const SwTabFrm* pTabFrm = pThisCell->FindTabFrm();
739 const SwTable* pTable = pTabFrm->GetTable();
741 SWRECTFNX( pTabFrm )
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 );
754 if ( nVal > 1 )
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:
778 switch ( eType )
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() )
784 bActualText = true;
785 else
787 bBaselineShift =
788 bTextDecorationType =
789 bLanguage = true;
791 break;
793 case vcl::PDFWriter::Link :
794 bTextDecorationType =
795 bBaselineShift =
796 bLinkAttribute =
797 bLanguage = true;
798 break;
800 default:
801 break;
804 if ( bActualText )
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;
817 if ( 0 != nVal )
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 );
836 if ( bLanguage )
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();
849 SwRect aPorRect;
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 );
860 break;
868 * SwTaggedPDFHelper::BeginNumberedListStructureElements()
870 void SwTaggedPDFHelper::BeginNumberedListStructureElements()
872 ASSERT( mpNumInfo, "List without mpNumInfo?" )
873 if ( !mpNumInfo )
874 return;
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() )
884 return;
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:
893 // First condition:
894 // Paragraph is numbered/bulleted
895 if ( !bNumbered )
896 return;
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;
906 // Two cases:
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;
932 else // if(bNoLabel)
934 // The list body tag of a 'counted' predecessor has to be reopened
935 const SwNumberTreeNode* pPrevious = pNodeNum->GetPred(true);
936 while ( pPrevious )
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;
945 break;
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);
961 while ( pPrevious )
963 // get id of list tag
964 const NumListIdMap::const_iterator aIter = rNumListIdMap.find( pPrevious );
965 if ( aIter != rNumListIdMap.end() )
967 nReopenTag = (*aIter).second;
968 break;
971 pPrevious = pPrevious->GetPred(true);
975 if ( -1 != nReopenTag )
977 nRestoreCurrentTag = mpPDFExtOutDevData->GetCurrentStructureElement();
978 mpPDFExtOutDevData->SetCurrentStructureElement( nReopenTag );
980 #ifndef PRODUCT
981 aStructStack.push_back( 99 );
982 #endif
985 else
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();
994 // New tags:
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:
998 if ( bNewListTag )
999 BeginTag( vcl::PDFWriter::List, aListString );
1001 if ( bNewItemTag )
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 ) )
1019 return;
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() )
1024 return;
1026 USHORT nPDFType = USHRT_MAX;
1027 String aPDFType;
1029 switch ( pFrm->GetType() )
1032 * GROUPING ELEMENTS
1035 case FRM_PAGE :
1037 // Document: Document
1039 nPDFType = vcl::PDFWriter::Document;
1040 aPDFType = aDocumentString;
1041 break;
1043 case FRM_HEADER :
1044 case FRM_FOOTER :
1046 // Header, Footer: NonStructElement
1048 nPDFType = vcl::PDFWriter::NonStructElement;
1049 break;
1051 case FRM_FTNCONT :
1053 // Footnote container: Division
1055 nPDFType = vcl::PDFWriter::Division;
1056 aPDFType = aDivString;
1057 break;
1059 case FRM_FTN :
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;
1067 break;
1069 case FRM_SECTION :
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();
1079 if ( pTOXBase )
1081 if ( TOX_INDEX == pTOXBase->GetType() )
1083 nPDFType = vcl::PDFWriter::Index;
1084 aPDFType = aIndexString;
1086 else
1088 nPDFType = vcl::PDFWriter::TOC;
1089 aPDFType = aTOCString;
1093 else if ( CONTENT_SECTION == pSection->GetType() )
1095 nPDFType = vcl::PDFWriter::Section;
1096 aPDFType = aSectString;
1099 break;
1102 * BLOCK-LEVEL STRUCTURE ELEMENTS
1105 case FRM_TXT :
1107 const SwTxtNode* pTxtNd =
1108 static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
1110 const SwFmt* pTxtFmt = pTxtNd->GetFmtColl();
1111 const SwFmt* pParentTxtFmt = pTxtFmt->DerivedFrom();
1113 String sStyleName;
1114 String sParentStyleName;
1116 if ( pTxtFmt)
1117 SwStyleNameMapper::FillProgName( pTxtFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
1118 if ( pParentTxtFmt)
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;
1137 // Caption: Caption
1139 else if ( sStyleName == aCaption)
1141 nPDFType = static_cast<USHORT>(vcl::PDFWriter::Caption);
1142 aPDFType = aCaptionString;
1146 // Caption: Caption
1148 else if ( sParentStyleName == aCaption)
1150 nPDFType = static_cast<USHORT>(vcl::PDFWriter::Caption);
1151 aPDFType = sStyleName.Append(aCaptionString);
1155 // Heading: H
1157 else if ( sStyleName == aHeading )
1159 nPDFType = static_cast<USHORT>(vcl::PDFWriter::Heading);
1160 aPDFType = aHString;
1164 // Heading: H1 - H6
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);
1173 switch(nRealLevel)
1175 case 0 :
1176 aPDFType = aH1String;
1177 break;
1178 case 1 :
1179 aPDFType = aH2String;
1180 break;
1181 case 2 :
1182 aPDFType = aH3String;
1183 break;
1184 case 3 :
1185 aPDFType = aH4String;
1186 break;
1187 case 4 :
1188 aPDFType = aH5String;
1189 break;
1190 default:
1191 aPDFType = aH6String;
1192 break;
1197 // Section: TOCI
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 );
1216 break;
1218 case FRM_TAB :
1220 // TabFrm: Table
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() )
1235 SWRECTFN( pTabFrm )
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());
1244 while ( pRowFrm )
1246 const SwFrm* pCellFrm = pRowFrm->GetLower();
1248 const long nLeft = (pCellFrm->Frm().*fnRect->fnGetLeft)();
1249 rCols.insert( nLeft );
1251 while ( pCellFrm )
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());
1264 break;
1267 * TABLE ELEMENTS
1270 case FRM_ROW :
1272 // RowFrm: TR
1274 if ( !static_cast<const SwRowFrm*>(pFrm)->IsRepeatedHeadline() )
1276 nPDFType = vcl::PDFWriter::TableRow;
1277 aPDFType = aTRString;
1279 else
1281 nPDFType = vcl::PDFWriter::NonStructElement;
1283 break;
1285 case FRM_CELL :
1287 // CellFrm: TH, TD
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;
1296 else
1298 nPDFType = vcl::PDFWriter::TableData;
1299 aPDFType = aTDString;
1302 break;
1305 * ILLUSTRATION
1308 case FRM_FLY :
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());
1319 if ( pOLENd )
1321 SwOLEObj& aOLEObj = pOLENd->GetOLEObj();
1322 uno::Reference< embed::XEmbeddedObject > aRef = aOLEObj.GetOleRef();
1323 if ( aRef.is() )
1325 bFormula = 0 != SotExchange::IsMath( SvGlobalName( aRef->getClassID() ) );
1328 if ( bFormula )
1330 nPDFType = vcl::PDFWriter::Formula;
1331 aPDFType = aFormulaString;
1333 else
1335 nPDFType = vcl::PDFWriter::Figure;
1336 aPDFType = aFigureString;
1339 else
1341 nPDFType = vcl::PDFWriter::Division;
1342 aPDFType = aDivString;
1345 break;
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 )
1362 EndTag();
1363 --nEndStructureElement;
1366 CheckRestoreTag();
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 ) )
1383 return;
1385 USHORT nPDFType = USHRT_MAX;
1386 String aPDFType;
1388 switch ( pPor->GetWhichPor() )
1390 // Check for alternative spelling:
1391 case POR_HYPHSTR :
1392 case POR_SOFTHYPHSTR :
1393 nPDFType = vcl::PDFWriter::Span;
1394 aPDFType = aSpanString;
1395 break;
1397 case POR_LAY :
1398 case POR_TXT :
1399 case POR_PARA :
1401 SwTxtNode* pNd = (SwTxtNode*)pFrm->GetTxtNode();
1402 SwIndex aIndex( pNd, rInf.GetIdx() );
1403 const SwTxtAttr* pInetFmtAttr = pNd->GetTxtAttr( aIndex, RES_TXTATR_INETFMT );
1405 String sStyleName;
1406 if ( !pInetFmtAttr )
1408 const SwTxtAttr* pCharFmtAttr = pNd->GetTxtAttr( aIndex, RES_TXTATR_CHARFMT );
1409 const SwCharFmt* pCharFmt = pCharFmtAttr ? pCharFmtAttr->GetCharFmt().GetCharFmt() : 0;
1410 if ( pCharFmt )
1411 SwStyleNameMapper::FillProgName( pCharFmt->GetName(), sStyleName, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, sal_True );
1414 // Check for Link:
1415 if( pInetFmtAttr )
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;
1431 else
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;
1449 else
1450 aPDFType = aSpanString;
1454 break;
1456 case POR_FTN :
1457 nPDFType = vcl::PDFWriter::Link;
1458 aPDFType = aLinkString;
1459 break;
1461 case POR_FLD :
1463 // check field type:
1464 const xub_StrLen nIdx = static_cast<const SwFldPortion*>(pPor)->IsFollow() ?
1465 rInf.GetIdx() - 1 :
1466 rInf.GetIdx();
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;
1484 break;
1486 case POR_TAB :
1487 case POR_TABRIGHT :
1488 case POR_TABCENTER :
1489 case POR_TABDECIMAL :
1490 nPDFType = vcl::PDFWriter::NonStructElement;
1491 break;
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,
1513 OutputDevice& rOut,
1514 const rtl::OUString& rPageRange,
1515 bool bSkipEmptyPages,
1516 bool bEditEngineOnly )
1517 : mrSh( rSh ),
1518 mrOut( rOut ),
1519 pPageRange( 0 ),
1520 mbSkipEmptyPages( bSkipEmptyPages ),
1521 mbEditEngineOnly( bEditEngineOnly )
1523 if ( rPageRange.getLength() )
1524 pPageRange = new MultiSelection( rPageRange );
1526 aTableColumnsMap.clear();
1527 aLinkIdMap.clear();
1528 aNumListIdMap.clear();
1529 aNumListBodyIdMap.clear();
1530 aFrmTagIdMap.clear();
1532 #ifndef PRODUCT
1533 aStructStack.clear();
1534 #endif
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()
1551 delete pPageRange;
1555 * SwEnhancedPDFExportHelper::EnhancedPDFExport()
1557 void SwEnhancedPDFExportHelper::EnhancedPDFExport()
1559 vcl::PDFExtOutDevData* pPDFExtOutDevData =
1560 PTR_CAST( vcl::PDFExtOutDevData, mrOut.GetExtOutDevData() );
1562 if ( !pPDFExtOutDevData )
1563 return;
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 )
1591 // POSTITS
1593 if ( pPDFExtOutDevData->GetIsExportNotes() )
1595 SwFieldType* pType = mrSh.GetFldType( RES_POSTITFLD, aEmptyStr );
1596 SwClientIter aIter( *pType );
1597 const SwClient * pFirst = aIter.GoStart();
1598 while( pFirst )
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() )
1614 // Link Rectangle
1615 const SwRect& rNoteRect = mrSh.GetCharRect();
1617 // Link PageNum
1618 const sal_Int32 nNotePageNum = CalcOutputPageNum( rNoteRect );
1619 if ( -1 != nNotePageNum )
1621 // Link Note
1622 vcl::PDFNote aNote;
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() );
1631 String sDate;
1632 Color* pColor;
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( ", " ) );
1638 sTitle += sDate;
1639 aNote.Title = sTitle;
1640 // Guess what the contents contains...
1641 aNote.Contents = pField->GetTxt();
1643 // Link Export
1644 pPDFExtOutDevData->CreateNote( rNoteRect.SVRect(), aNote, nNotePageNum );
1648 pFirst = aIter++;
1649 mrSh.SwCrsrShell::ClearMark();
1654 // HYPERLINKS
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(),
1681 INET_HEX_ESCAPE,
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.
1693 SwRects aTmp;
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;
1699 if ( bIntern )
1701 aURL.Erase( 0, 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 );
1721 // <--
1723 // Create links for all selected rectangles:
1724 const USHORT nNumOfRects = aTmp.Count();
1725 for ( USHORT i = 0; i < nNumOfRects; ++i )
1727 // Link Rectangle
1728 const SwRect& rLinkRect( aTmp[ i ] );
1730 // Link PageNum
1731 const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
1733 if ( -1 != nLinkPageNum )
1735 // Link Export
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:
1744 if ( bIntern )
1745 pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
1746 else
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 );
1752 // <--
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;
1778 if ( bIntern )
1780 aURL.Erase( 0, 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 )
1797 Point aNullPt;
1798 const SwRect aLinkRect = pFrmFmt->FindLayoutRect( sal_False, &aNullPt );
1800 // Link PageNum
1801 const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
1803 // Link Export
1804 if ( -1 != nLinkPageNum )
1806 const sal_Int32 nLinkId =
1807 pPDFExtOutDevData->CreateLink( aLinkRect.SVRect(), nLinkPageNum );
1809 // Connect Link and Destination:
1810 if ( bIntern )
1811 pPDFExtOutDevData->SetLinkDest( nLinkId, nDestId );
1812 else
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();
1823 if ( pTNd )
1824 MakeHeaderFooterLinks( *pPDFExtOutDevData, *pTNd, aLinkRect, nDestId, aURL, bIntern );
1827 // <--
1831 mrSh.SwCrsrShell::ClearMark();
1835 // REFERENCES
1837 SwFieldType* pType = mrSh.GetFldType( RES_GETREFFLD, aEmptyStr );
1838 SwClientIter aIter( *pType );
1839 const SwClient * pFirst = aIter.GoStart();
1840 while( pFirst )
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 );
1860 // Link Rectangles
1861 SwRects aTmp;
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 );
1885 // <--
1887 // Create links for all selected rectangles:
1888 const USHORT nNumOfRects = aTmp.Count();
1889 for ( USHORT i = 0; i < nNumOfRects; ++i )
1891 // Link rectangle
1892 const SwRect& rLinkRect( aTmp[ i ] );
1894 // Link PageNum
1895 const sal_Int32 nLinkPageNum = CalcOutputPageNum( rLinkRect );
1897 if ( -1 != nLinkPageNum )
1899 // Link Export
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 );
1916 // <--
1922 pFirst = aIter++;
1923 mrSh.SwCrsrShell::ClearMark();
1927 // FOOTNOTES
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() )
1943 continue;
1945 SwCrsrSaveState aSaveState( *mrSh._GetCrsr() );
1947 // Select the footnote:
1948 mrSh.SwCrsrShell::SetMark();
1949 mrSh.SwCrsrShell::Right( 1, CRSR_SKIP_CHARS );
1951 // Link Rectangle
1952 SwRects aTmp;
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() )
1963 // Link PageNum
1964 const sal_Int32 nLinkPageNum = CalcOutputPageNum( aLinkRect );
1966 if ( -1 != nLinkPageNum )
1968 // Link Export
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 );
1995 // OUTLINE
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() )
2014 // <--
2015 continue;
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
2058 // We need:
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();
2064 ppMark++)
2066 //get the name
2067 const ::sw::mark::IMark* pBkmk = ppMark->get();
2068 mrSh.SwCrsrShell::ClearMark();
2069 rtl::OUString sBkName = pBkmk->GetName();
2071 //jump to it
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();
2085 //<--- i56629
2088 else
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 );
2100 if ( bIntern )
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 );
2121 else
2122 pPDFExtOutDevData->SetLinkURL( aIBeg->nLinkId, aBookmarkName );
2124 aIBeg++;
2126 rBookmarks.clear();
2129 // Restore view, cursor, and outdev:
2130 mrSh.LockView( bOldLockView );
2131 mrSh.SwCrsrShell::Pop( FALSE );
2132 mrOut.Pop();
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 );
2143 // Shortcut:
2144 if ( -1 == nPageNumOfRect || ( !pPageRange && !mbSkipEmptyPages ) )
2145 return nPageNumOfRect;
2147 // pPageRange page numbers are 1, 2, 3, ...
2148 if ( pPageRange && !pPageRange->IsSelected( nPageNumOfRect + 1 ) )
2149 return -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;
2158 ++nPageIndex )
2160 if ( ( !pPageRange || pPageRange->IsSelected( nPageIndex + 1 ) ) &&
2161 ( !mbSkipEmptyPages || !pCurrPage->IsEmptyPage() ) )
2162 ++nOutputPageNum;
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,
2174 sal_Int32 nDestId,
2175 const String& rURL,
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();
2185 while( pLast )
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
2197 // same anyway)
2198 if ( aHFLinkRect.Pos() != rLinkRect.Pos() )
2200 // Link PageNum
2201 const sal_Int32 nHFLinkPageNum = CalcOutputPageNum( aHFLinkRect );
2203 if ( -1 != nHFLinkPageNum )
2205 // Link Export
2206 const sal_Int32 nHFLinkId =
2207 rPDFExtOutDevData.CreateLink( aHFLinkRect.SVRect(), nHFLinkPageNum );
2209 // Connect Link and Destination:
2210 if ( bIntern )
2211 rPDFExtOutDevData.SetLinkDest( nHFLinkId, nDestId );
2212 else
2213 rPDFExtOutDevData.SetLinkURL( nHFLinkId, rURL );
2218 pLast = ++aClientIter;