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