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