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