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