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