Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / gdi / pdfextoutdevdata.cxx
blobccc242061fa47a23da0f806e65572c42c94600a9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/pdfextoutdevdata.hxx>
21 #include <vcl/graph.hxx>
22 #include <vcl/outdev.hxx>
23 #include <vcl/gfxlink.hxx>
24 #include "vcl/dllapi.h"
25 #include "basegfx/polygon/b2dpolygon.hxx"
26 #include "basegfx/polygon/b2dpolygontools.hxx"
28 #include <set>
29 #include <memory>
30 #include <map>
32 namespace vcl
34 struct PDFExtOutDevDataSync
36 enum Action{ CreateNamedDest,
37 CreateDest,
38 CreateLink,
39 CreateScreen,
40 SetLinkDest,
41 SetLinkURL,
42 SetScreenURL,
43 SetScreenStream,
44 RegisterDest,
45 CreateOutlineItem,
46 CreateNote,
47 SetPageTransition,
49 BeginStructureElement,
50 EndStructureElement,
51 SetCurrentStructureElement,
52 SetStructureAttribute,
53 SetStructureAttributeNumerical,
54 SetStructureBoundingBox,
55 SetActualText,
56 SetAlternateText,
57 CreateControl,
58 BeginGroup,
59 EndGroupGfxLink
62 sal_uInt32 nIdx;
63 Action eAct;
66 struct PDFLinkDestination
68 tools::Rectangle mRect;
69 MapMode mMapMode;
70 sal_Int32 mPageNr;
71 PDFWriter::DestAreaType mAreaType;
74 struct GlobalSyncData
76 std::deque< PDFExtOutDevDataSync::Action > mActions;
77 std::deque< MapMode > mParaMapModes;
78 std::deque< tools::Rectangle > mParaRects;
79 std::deque< sal_Int32 > mParaInts;
80 std::deque< sal_uInt32 > mParauInts;
81 std::deque< OUString > mParaOUStrings;
82 std::deque< PDFWriter::DestAreaType > mParaDestAreaTypes;
83 std::deque< PDFNote > mParaPDFNotes;
84 std::deque< PDFWriter::PageTransition > mParaPageTransitions;
85 ::std::map< sal_Int32, PDFLinkDestination > mFutureDestinations;
87 sal_Int32 GetMappedId();
88 sal_Int32 GetMappedStructId( sal_Int32 );
90 sal_Int32 mCurId;
91 std::vector< sal_Int32 > mParaIds;
92 std::vector< sal_Int32 > mStructIdMap;
94 sal_Int32 mCurrentStructElement;
95 std::vector< sal_Int32 > mStructParents;
96 GlobalSyncData() :
97 mCurId ( 0 ),
98 mCurrentStructElement( 0 )
100 mStructParents.push_back( 0 );
101 mStructIdMap.push_back( 0 );
103 void PlayGlobalActions( PDFWriter& rWriter );
106 sal_Int32 GlobalSyncData::GetMappedId()
108 sal_Int32 nLinkId = mParaInts.front();
109 mParaInts.pop_front();
111 /* negative values are intentionally passed as invalid IDs
112 * e.g. to create a new top level outline item
114 if( nLinkId >= 0 )
116 if ( (sal_uInt32)nLinkId < mParaIds.size() )
117 nLinkId = mParaIds[ nLinkId ];
118 else
119 nLinkId = -1;
121 SAL_WARN_IF( nLinkId < 0, "vcl", "unmapped id in GlobalSyncData" );
124 return nLinkId;
127 sal_Int32 GlobalSyncData::GetMappedStructId( sal_Int32 nStructId )
129 if ( (sal_uInt32)nStructId < mStructIdMap.size() )
130 nStructId = mStructIdMap[ nStructId ];
131 else
132 nStructId = -1;
134 SAL_WARN_IF( nStructId < 0, "vcl", "unmapped structure id in GlobalSyncData" );
136 return nStructId;
139 void GlobalSyncData::PlayGlobalActions( PDFWriter& rWriter )
141 for (std::deque< PDFExtOutDevDataSync::Action >::const_iterator aIter( mActions.begin() ), aEnd( mActions.end() ) ;
142 aIter != aEnd ; ++aIter)
144 switch( *aIter )
146 case PDFExtOutDevDataSync::CreateNamedDest : //i56629
148 rWriter.Push( PushFlags::MAPMODE );
149 rWriter.SetMapMode( mParaMapModes.front() );
150 mParaMapModes.pop_front();
151 mParaIds.push_back( rWriter.CreateNamedDest( mParaOUStrings.front(), mParaRects.front(), mParaInts.front(), mParaDestAreaTypes.front() ) );
152 mParaOUStrings.pop_front();
153 mParaRects.pop_front();
154 mParaInts.pop_front();
155 mParaDestAreaTypes.pop_front();
156 rWriter.Pop();
158 break;
159 case PDFExtOutDevDataSync::CreateDest :
161 rWriter.Push( PushFlags::MAPMODE );
162 rWriter.SetMapMode( mParaMapModes.front() );
163 mParaMapModes.pop_front();
164 mParaIds.push_back( rWriter.CreateDest( mParaRects.front(), mParaInts.front(), mParaDestAreaTypes.front() ) );
165 mParaRects.pop_front();
166 mParaInts.pop_front();
167 mParaDestAreaTypes.pop_front();
168 rWriter.Pop();
170 break;
171 case PDFExtOutDevDataSync::CreateLink :
173 rWriter.Push( PushFlags::MAPMODE );
174 rWriter.SetMapMode( mParaMapModes.front() );
175 mParaMapModes.pop_front();
176 mParaIds.push_back( rWriter.CreateLink( mParaRects.front(), mParaInts.front() ) );
177 // resolve LinkAnnotation structural attribute
178 rWriter.SetLinkPropertyID( mParaIds.back(), sal_Int32(mParaIds.size()-1) );
179 mParaRects.pop_front();
180 mParaInts.pop_front();
181 rWriter.Pop();
183 break;
184 case PDFExtOutDevDataSync::CreateScreen:
186 rWriter.Push(PushFlags::MAPMODE);
187 rWriter.SetMapMode(mParaMapModes.front());
188 mParaMapModes.pop_front();
189 mParaIds.push_back(rWriter.CreateScreen(mParaRects.front(), mParaInts.front()));
190 mParaRects.pop_front();
191 mParaInts.pop_front();
192 rWriter.Pop();
194 break;
195 case PDFExtOutDevDataSync::SetLinkDest :
197 sal_Int32 nLinkId = GetMappedId();
198 sal_Int32 nDestId = GetMappedId();
199 rWriter.SetLinkDest( nLinkId, nDestId );
201 break;
202 case PDFExtOutDevDataSync::SetLinkURL :
204 sal_Int32 nLinkId = GetMappedId();
205 rWriter.SetLinkURL( nLinkId, mParaOUStrings.front() );
206 mParaOUStrings.pop_front();
208 break;
209 case PDFExtOutDevDataSync::SetScreenURL:
211 sal_Int32 nScreenId = GetMappedId();
212 rWriter.SetScreenURL(nScreenId, mParaOUStrings.front());
213 mParaOUStrings.pop_front();
215 break;
216 case PDFExtOutDevDataSync::SetScreenStream:
218 sal_Int32 nScreenId = GetMappedId();
219 rWriter.SetScreenStream(nScreenId, mParaOUStrings.front());
220 mParaOUStrings.pop_front();
222 break;
223 case PDFExtOutDevDataSync::RegisterDest :
225 const sal_Int32 nDestId = mParaInts.front();
226 mParaInts.pop_front();
227 OSL_ENSURE( mFutureDestinations.find( nDestId ) != mFutureDestinations.end(),
228 "GlobalSyncData::PlayGlobalActions: DescribeRegisteredRequest has not been called for that destination!" );
230 PDFLinkDestination& rDest = mFutureDestinations[ nDestId ];
232 rWriter.Push( PushFlags::MAPMODE );
233 rWriter.SetMapMode( rDest.mMapMode );
234 mParaIds.push_back( rWriter.RegisterDestReference( nDestId, rDest.mRect, rDest.mPageNr, rDest.mAreaType ) );
235 rWriter.Pop();
237 break;
238 case PDFExtOutDevDataSync::CreateOutlineItem :
240 sal_Int32 nParent = GetMappedId();
241 sal_Int32 nLinkId = GetMappedId();
242 mParaIds.push_back( rWriter.CreateOutlineItem( nParent, mParaOUStrings.front(), nLinkId ) );
243 mParaOUStrings.pop_front();
245 break;
246 case PDFExtOutDevDataSync::CreateNote :
248 rWriter.Push( PushFlags::MAPMODE );
249 rWriter.SetMapMode( mParaMapModes.front() );
250 rWriter.CreateNote( mParaRects.front(), mParaPDFNotes.front(), mParaInts.front() );
251 mParaMapModes.pop_front();
252 mParaRects.pop_front();
253 mParaPDFNotes.pop_front();
254 mParaInts.pop_front();
256 break;
257 case PDFExtOutDevDataSync::SetPageTransition :
259 rWriter.SetPageTransition( mParaPageTransitions.front(), mParauInts.front(), mParaInts.front() );
260 mParaPageTransitions.pop_front();
261 mParauInts.pop_front();
262 mParaInts.pop_front();
264 break;
265 case PDFExtOutDevDataSync::BeginStructureElement:
266 case PDFExtOutDevDataSync::EndStructureElement:
267 case PDFExtOutDevDataSync::SetCurrentStructureElement:
268 case PDFExtOutDevDataSync::SetStructureAttribute:
269 case PDFExtOutDevDataSync::SetStructureAttributeNumerical:
270 case PDFExtOutDevDataSync::SetStructureBoundingBox:
271 case PDFExtOutDevDataSync::SetActualText:
272 case PDFExtOutDevDataSync::SetAlternateText:
273 case PDFExtOutDevDataSync::CreateControl:
274 case PDFExtOutDevDataSync::BeginGroup:
275 case PDFExtOutDevDataSync::EndGroupGfxLink:
276 break;
281 struct PageSyncData
283 std::deque< PDFExtOutDevDataSync > mActions;
284 std::deque< tools::Rectangle > mParaRects;
285 std::deque< sal_Int32 > mParaInts;
286 std::deque< OUString > mParaOUStrings;
287 std::deque< PDFWriter::StructElement > mParaStructElements;
288 std::deque< PDFWriter::StructAttribute > mParaStructAttributes;
289 std::deque< PDFWriter::StructAttributeValue > mParaStructAttributeValues;
290 std::deque< Graphic > mGraphics;
291 Graphic mCurrentGraphic;
292 std::deque< std::shared_ptr< PDFWriter::AnyWidget > >
293 mControls;
294 GlobalSyncData* mpGlobalData;
296 bool mbGroupIgnoreGDIMtfActions;
299 explicit PageSyncData( GlobalSyncData* pGlobal )
300 : mbGroupIgnoreGDIMtfActions ( false )
301 { mpGlobalData = pGlobal; }
303 void PushAction( const OutputDevice& rOutDev, const PDFExtOutDevDataSync::Action eAct );
304 bool PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAction, const PDFExtOutDevData& rOutDevData );
307 void PageSyncData::PushAction( const OutputDevice& rOutDev, const PDFExtOutDevDataSync::Action eAct )
309 GDIMetaFile* pMtf = rOutDev.GetConnectMetaFile();
310 SAL_WARN_IF( !pMtf, "vcl", "PageSyncData::PushAction -> no ConnectMetaFile !!!" );
312 PDFExtOutDevDataSync aSync;
313 aSync.eAct = eAct;
314 if ( pMtf )
315 aSync.nIdx = pMtf->GetActionSize();
316 else
317 aSync.nIdx = 0x7fffffff; // sync not possible
318 mActions.push_back( aSync );
320 bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAction, const PDFExtOutDevData& rOutDevData )
322 bool bRet = false;
323 if ( mActions.size() && ( mActions.front().nIdx == rCurGDIMtfAction ) )
325 bRet = true;
326 PDFExtOutDevDataSync aDataSync = mActions.front();
327 mActions.pop_front();
328 switch( aDataSync.eAct )
330 case PDFExtOutDevDataSync::BeginStructureElement :
332 sal_Int32 nNewEl = rWriter.BeginStructureElement( mParaStructElements.front(), mParaOUStrings.front() ) ;
333 mParaStructElements.pop_front();
334 mParaOUStrings.pop_front();
335 mpGlobalData->mStructIdMap.push_back( nNewEl );
337 break;
338 case PDFExtOutDevDataSync::EndStructureElement :
340 rWriter.EndStructureElement();
342 break;
343 case PDFExtOutDevDataSync::SetCurrentStructureElement:
345 rWriter.SetCurrentStructureElement( mpGlobalData->GetMappedStructId( mParaInts.front() ) );
346 mParaInts.pop_front();
348 break;
349 case PDFExtOutDevDataSync::SetStructureAttribute :
351 rWriter.SetStructureAttribute( mParaStructAttributes.front(), mParaStructAttributeValues.front() );
352 mParaStructAttributeValues.pop_front();
353 mParaStructAttributes.pop_front();
355 break;
356 case PDFExtOutDevDataSync::SetStructureAttributeNumerical :
358 rWriter.SetStructureAttributeNumerical( mParaStructAttributes.front(), mParaInts.front() );
359 mParaStructAttributes.pop_front();
360 mParaInts.pop_front();
362 break;
363 case PDFExtOutDevDataSync::SetStructureBoundingBox :
365 rWriter.SetStructureBoundingBox( mParaRects.front() );
366 mParaRects.pop_front();
368 break;
369 case PDFExtOutDevDataSync::SetActualText :
371 rWriter.SetActualText( mParaOUStrings.front() );
372 mParaOUStrings.pop_front();
374 break;
375 case PDFExtOutDevDataSync::SetAlternateText :
377 rWriter.SetAlternateText( mParaOUStrings.front() );
378 mParaOUStrings.pop_front();
380 break;
381 case PDFExtOutDevDataSync::CreateControl:
383 std::shared_ptr< PDFWriter::AnyWidget > pControl( mControls.front() );
384 SAL_WARN_IF( !pControl.get(), "vcl", "PageSyncData::PlaySyncPageAct: invalid widget!" );
385 if ( pControl.get() )
386 rWriter.CreateControl( *pControl );
387 mControls.pop_front();
389 break;
390 case PDFExtOutDevDataSync::BeginGroup :
392 /* first determining if this BeginGroup is starting a GfxLink,
393 by searching for a EndGroup or a EndGroupGfxLink */
394 mbGroupIgnoreGDIMtfActions = false;
395 std::deque< PDFExtOutDevDataSync >::iterator aBeg = mActions.begin();
396 std::deque< PDFExtOutDevDataSync >::iterator aEnd = mActions.end();
397 while ( aBeg != aEnd )
399 if ( aBeg->eAct == PDFExtOutDevDataSync::EndGroupGfxLink )
401 Graphic& rGraphic = mGraphics.front();
402 if ( rGraphic.IsLink() )
404 GfxLinkType eType = rGraphic.GetLink().GetType();
405 if ( eType == GfxLinkType::NativeJpg && mParaRects.size() >= 2 )
407 mbGroupIgnoreGDIMtfActions = rOutDevData.HasAdequateCompression(rGraphic);
408 if ( !mbGroupIgnoreGDIMtfActions )
409 mCurrentGraphic = rGraphic;
411 else if ((eType == GfxLinkType::NativePng || eType == GfxLinkType::NativePdf) && mParaRects.size() >= 2)
413 if ( rOutDevData.HasAdequateCompression(rGraphic) || eType == GfxLinkType::NativePdf )
414 mCurrentGraphic = rGraphic;
417 break;
419 ++aBeg;
422 break;
423 case PDFExtOutDevDataSync::EndGroupGfxLink :
425 tools::Rectangle aOutputRect, aVisibleOutputRect;
426 Graphic aGraphic( mGraphics.front() );
428 mGraphics.pop_front();
429 sal_Int32 nTransparency = mParaInts.front();
430 mParaInts.pop_front();
431 aOutputRect = mParaRects.front();
432 mParaRects.pop_front();
433 aVisibleOutputRect = mParaRects.front();
434 mParaRects.pop_front();
436 if ( mbGroupIgnoreGDIMtfActions )
438 bool bClippingNeeded = ( aOutputRect != aVisibleOutputRect ) && !aVisibleOutputRect.IsEmpty();
440 GfxLink aGfxLink( aGraphic.GetLink() );
441 if ( aGfxLink.GetType() == GfxLinkType::NativeJpg )
443 if ( bClippingNeeded )
445 rWriter.Push();
446 basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect(
447 basegfx::B2DRectangle( aVisibleOutputRect.Left(), aVisibleOutputRect.Top(),
448 aVisibleOutputRect.Right(), aVisibleOutputRect.Bottom() ) ) );
449 rWriter.SetClipRegion( aRect);
452 Bitmap aMask;
453 if (nTransparency)
455 AlphaMask aAlphaMask(aGraphic.GetSizePixel());
456 aAlphaMask.Erase(nTransparency);
457 aMask = aAlphaMask.GetBitmap();
460 SvMemoryStream aTmp;
461 const sal_uInt8* pData = aGfxLink.GetData();
462 sal_uInt32 nBytes = aGfxLink.GetDataSize();
463 if( pData && nBytes )
465 aTmp.WriteBytes( pData, nBytes );
466 rWriter.DrawJPGBitmap( aTmp, aGraphic.GetBitmap().GetBitCount() > 8, aGraphic.GetSizePixel(), aOutputRect, aMask, aGraphic );
469 if ( bClippingNeeded )
470 rWriter.Pop();
472 mbGroupIgnoreGDIMtfActions = false;
474 mCurrentGraphic.Clear();
476 break;
477 case PDFExtOutDevDataSync::CreateNamedDest:
478 case PDFExtOutDevDataSync::CreateDest:
479 case PDFExtOutDevDataSync::CreateLink:
480 case PDFExtOutDevDataSync::CreateScreen:
481 case PDFExtOutDevDataSync::SetLinkDest:
482 case PDFExtOutDevDataSync::SetLinkURL:
483 case PDFExtOutDevDataSync::SetScreenURL:
484 case PDFExtOutDevDataSync::SetScreenStream:
485 case PDFExtOutDevDataSync::RegisterDest:
486 case PDFExtOutDevDataSync::CreateOutlineItem:
487 case PDFExtOutDevDataSync::CreateNote:
488 case PDFExtOutDevDataSync::SetPageTransition:
489 break;
492 else if ( mbGroupIgnoreGDIMtfActions )
494 rCurGDIMtfAction++;
495 bRet = true;
497 return bRet;
500 PDFExtOutDevData::PDFExtOutDevData( const OutputDevice& rOutDev ) :
501 mrOutDev ( rOutDev ),
502 mbTaggedPDF ( false ),
503 mbExportNotes ( true ),
504 mbExportNotesPages ( false ),
505 mbTransitionEffects ( true ),
506 mbUseLosslessCompression( true ),
507 mbReduceImageResolution ( false ),
508 mbExportFormFields ( false ),
509 mbExportBookmarks ( false ),
510 mbExportHiddenSlides ( false ),
511 mbExportNDests ( false ),
512 mnFormsFormat ( 0 ),
513 mnPage ( -1 ),
514 mnCompressionQuality ( 90 ),
515 mnMaxImageResolution ( 300 ),
516 mpPageSyncData ( nullptr ),
517 mpGlobalSyncData ( new GlobalSyncData() )
519 mpPageSyncData = new PageSyncData( mpGlobalSyncData );
522 PDFExtOutDevData::~PDFExtOutDevData()
524 delete mpPageSyncData;
525 delete mpGlobalSyncData;
528 const Graphic& PDFExtOutDevData::GetCurrentGraphic() const
530 return mpPageSyncData->mCurrentGraphic;
533 void PDFExtOutDevData::SetDocumentLocale( const css::lang::Locale& rLoc )
535 maDocLocale = rLoc;
537 void PDFExtOutDevData::SetCurrentPageNumber( const sal_Int32 nPage )
539 mnPage = nPage;
541 void PDFExtOutDevData::SetIsLosslessCompression( const bool bUseLosslessCompression )
543 mbUseLosslessCompression = bUseLosslessCompression;
545 void PDFExtOutDevData::SetCompressionQuality( const sal_Int32 nQuality )
547 mnCompressionQuality = nQuality;
549 void PDFExtOutDevData::SetMaxImageResolution( const sal_Int32 nMaxImageResolution )
551 mnMaxImageResolution = nMaxImageResolution;
553 void PDFExtOutDevData::SetIsReduceImageResolution( const bool bReduceImageResolution )
555 mbReduceImageResolution = bReduceImageResolution;
557 void PDFExtOutDevData::SetIsExportNotes( const bool bExportNotes )
559 mbExportNotes = bExportNotes;
561 void PDFExtOutDevData::SetIsExportNotesPages( const bool bExportNotesPages )
563 mbExportNotesPages = bExportNotesPages;
565 void PDFExtOutDevData::SetIsExportTaggedPDF( const bool bTaggedPDF )
567 mbTaggedPDF = bTaggedPDF;
569 void PDFExtOutDevData::SetIsExportTransitionEffects( const bool bTransitionEffects )
571 mbTransitionEffects = bTransitionEffects;
573 void PDFExtOutDevData::SetIsExportFormFields( const bool bExportFomtFields )
575 mbExportFormFields = bExportFomtFields;
577 void PDFExtOutDevData::SetFormsFormat( const sal_Int32 nFormsFormat )
579 mnFormsFormat = nFormsFormat;
581 void PDFExtOutDevData::SetIsExportBookmarks( const bool bExportBookmarks )
583 mbExportBookmarks = bExportBookmarks;
585 void PDFExtOutDevData::SetIsExportHiddenSlides( const bool bExportHiddenSlides )
587 mbExportHiddenSlides = bExportHiddenSlides;
589 void PDFExtOutDevData::SetIsExportNamedDestinations( const bool bExportNDests )
591 mbExportNDests = bExportNDests;
593 void PDFExtOutDevData::ResetSyncData()
595 *mpPageSyncData = PageSyncData( mpGlobalSyncData );
597 bool PDFExtOutDevData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rIdx )
599 return mpPageSyncData->PlaySyncPageAct( rWriter, rIdx, *this );
601 void PDFExtOutDevData::PlayGlobalActions( PDFWriter& rWriter )
603 mpGlobalSyncData->PlayGlobalActions( rWriter );
606 /* global actions, synchronisation to the recorded metafile isn't needed,
607 all actions will be played after the last page was recorded
609 //--->i56629
610 sal_Int32 PDFExtOutDevData::CreateNamedDest(const OUString& sDestName, const tools::Rectangle& rRect, sal_Int32 nPageNr )
612 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateNamedDest );
613 mpGlobalSyncData->mParaOUStrings.push_back( sDestName );
614 mpGlobalSyncData->mParaRects.push_back( rRect );
615 mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
616 mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
617 mpGlobalSyncData->mParaDestAreaTypes.push_back( PDFWriter::DestAreaType::XYZ );
619 return mpGlobalSyncData->mCurId++;
621 //<---i56629
622 sal_Int32 PDFExtOutDevData::RegisterDest()
624 const sal_Int32 nLinkDestID = mpGlobalSyncData->mCurId++;
625 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::RegisterDest );
626 mpGlobalSyncData->mParaInts.push_back( nLinkDestID );
628 return nLinkDestID;
630 void PDFExtOutDevData::DescribeRegisteredDest( sal_Int32 nDestId, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
632 OSL_PRECOND( nDestId != -1, "PDFExtOutDevData::DescribeRegisteredDest: invalid destination Id!" );
633 PDFLinkDestination aLinkDestination;
634 aLinkDestination.mRect = rRect;
635 aLinkDestination.mMapMode = mrOutDev.GetMapMode();
636 aLinkDestination.mPageNr = nPageNr == -1 ? mnPage : nPageNr;
637 aLinkDestination.mAreaType = eType;
638 mpGlobalSyncData->mFutureDestinations[ nDestId ] = aLinkDestination;
640 sal_Int32 PDFExtOutDevData::CreateDest( const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
642 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateDest );
643 mpGlobalSyncData->mParaRects.push_back( rRect );
644 mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
645 mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
646 mpGlobalSyncData->mParaDestAreaTypes.push_back( eType );
647 return mpGlobalSyncData->mCurId++;
649 sal_Int32 PDFExtOutDevData::CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr )
651 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateLink );
652 mpGlobalSyncData->mParaRects.push_back( rRect );
653 mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
654 mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
655 return mpGlobalSyncData->mCurId++;
658 sal_Int32 PDFExtOutDevData::CreateScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr)
660 mpGlobalSyncData->mActions.push_back(PDFExtOutDevDataSync::CreateScreen);
661 mpGlobalSyncData->mParaRects.push_back(rRect);
662 mpGlobalSyncData->mParaMapModes.push_back(mrOutDev.GetMapMode());
663 mpGlobalSyncData->mParaInts.push_back(nPageNr);
664 return mpGlobalSyncData->mCurId++;
667 sal_Int32 PDFExtOutDevData::SetLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId )
669 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::SetLinkDest );
670 mpGlobalSyncData->mParaInts.push_back( nLinkId );
671 mpGlobalSyncData->mParaInts.push_back( nDestId );
672 return 0;
674 sal_Int32 PDFExtOutDevData::SetLinkURL( sal_Int32 nLinkId, const OUString& rURL )
676 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::SetLinkURL );
677 mpGlobalSyncData->mParaInts.push_back( nLinkId );
678 mpGlobalSyncData->mParaOUStrings.push_back( rURL );
679 return 0;
682 void PDFExtOutDevData::SetScreenURL(sal_Int32 nScreenId, const OUString& rURL)
684 mpGlobalSyncData->mActions.push_back(PDFExtOutDevDataSync::SetScreenURL);
685 mpGlobalSyncData->mParaInts.push_back(nScreenId);
686 mpGlobalSyncData->mParaOUStrings.push_back(rURL);
689 void PDFExtOutDevData::SetScreenStream(sal_Int32 nScreenId, const OUString& rURL)
691 mpGlobalSyncData->mActions.push_back(PDFExtOutDevDataSync::SetScreenStream);
692 mpGlobalSyncData->mParaInts.push_back(nScreenId);
693 mpGlobalSyncData->mParaOUStrings.push_back(rURL);
696 sal_Int32 PDFExtOutDevData::CreateOutlineItem( sal_Int32 nParent, const OUString& rText, sal_Int32 nDestID )
698 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateOutlineItem );
699 mpGlobalSyncData->mParaInts.push_back( nParent );
700 mpGlobalSyncData->mParaOUStrings.push_back( rText );
701 mpGlobalSyncData->mParaInts.push_back( nDestID );
702 return mpGlobalSyncData->mCurId++;
704 void PDFExtOutDevData::CreateNote( const tools::Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr )
706 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateNote );
707 mpGlobalSyncData->mParaRects.push_back( rRect );
708 mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
709 mpGlobalSyncData->mParaPDFNotes.push_back( rNote );
710 mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
712 void PDFExtOutDevData::SetPageTransition( PDFWriter::PageTransition eType, sal_uInt32 nMilliSec )
714 mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::SetPageTransition );
715 mpGlobalSyncData->mParaPageTransitions.push_back( eType );
716 mpGlobalSyncData->mParauInts.push_back( nMilliSec );
717 mpGlobalSyncData->mParaInts.push_back( mnPage );
720 /* local (page), actions have to be played synchronously to the actions of
721 of the recorded metafile (created by each xRenderable->render()) */
722 sal_Int32 PDFExtOutDevData::BeginStructureElement( PDFWriter::StructElement eType, const OUString& rAlias )
724 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::BeginStructureElement );
725 mpPageSyncData->mParaStructElements.push_back( eType );
726 mpPageSyncData->mParaOUStrings.push_back( rAlias );
727 // need a global id
728 sal_Int32 nNewId = mpGlobalSyncData->mStructParents.size();
729 mpGlobalSyncData->mStructParents.push_back( mpGlobalSyncData->mCurrentStructElement );
730 mpGlobalSyncData->mCurrentStructElement = nNewId;
731 return nNewId;
733 void PDFExtOutDevData::EndStructureElement()
735 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::EndStructureElement );
736 mpGlobalSyncData->mCurrentStructElement = mpGlobalSyncData->mStructParents[ mpGlobalSyncData->mCurrentStructElement ];
738 bool PDFExtOutDevData::SetCurrentStructureElement( sal_Int32 nStructId )
740 bool bSuccess = false;
741 if( sal_uInt32(nStructId) < mpGlobalSyncData->mStructParents.size() )
743 mpGlobalSyncData->mCurrentStructElement = nStructId;
744 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetCurrentStructureElement );
745 mpPageSyncData->mParaInts.push_back( nStructId );
746 bSuccess = true;
748 return bSuccess;
750 sal_Int32 PDFExtOutDevData::GetCurrentStructureElement()
752 return mpGlobalSyncData->mCurrentStructElement;
754 bool PDFExtOutDevData::SetStructureAttribute( PDFWriter::StructAttribute eAttr, PDFWriter::StructAttributeValue eVal )
756 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetStructureAttribute );
757 mpPageSyncData->mParaStructAttributes.push_back( eAttr );
758 mpPageSyncData->mParaStructAttributeValues.push_back( eVal );
759 return true;
761 bool PDFExtOutDevData::SetStructureAttributeNumerical( PDFWriter::StructAttribute eAttr, sal_Int32 nValue )
763 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetStructureAttributeNumerical );
764 mpPageSyncData->mParaStructAttributes.push_back( eAttr );
765 mpPageSyncData->mParaInts.push_back( nValue );
766 return true;
768 void PDFExtOutDevData::SetStructureBoundingBox( const tools::Rectangle& rRect )
770 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetStructureBoundingBox );
771 mpPageSyncData->mParaRects.push_back( rRect );
773 void PDFExtOutDevData::SetActualText( const OUString& rText )
775 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetActualText );
776 mpPageSyncData->mParaOUStrings.push_back( rText );
778 void PDFExtOutDevData::SetAlternateText( const OUString& rText )
780 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::SetAlternateText );
781 mpPageSyncData->mParaOUStrings.push_back( rText );
784 void PDFExtOutDevData::CreateControl( const PDFWriter::AnyWidget& rControlType )
786 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::CreateControl );
788 std::shared_ptr< PDFWriter::AnyWidget > pClone( rControlType.Clone() );
789 mpPageSyncData->mControls.push_back( pClone );
792 void PDFExtOutDevData::BeginGroup()
794 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::BeginGroup );
797 void PDFExtOutDevData::EndGroup( const Graphic& rGraphic,
798 sal_uInt8 nTransparency,
799 const tools::Rectangle& rOutputRect,
800 const tools::Rectangle& rVisibleOutputRect )
802 mpPageSyncData->PushAction( mrOutDev, PDFExtOutDevDataSync::EndGroupGfxLink );
803 mpPageSyncData->mGraphics.push_back( rGraphic );
804 mpPageSyncData->mParaInts.push_back( nTransparency );
805 mpPageSyncData->mParaRects.push_back( rOutputRect );
806 mpPageSyncData->mParaRects.push_back( rVisibleOutputRect );
809 // Avoids expensive de-compression and re-compression of large images.
810 bool PDFExtOutDevData::HasAdequateCompression( const Graphic &rGraphic ) const
812 bool bReduceResolution = false;
814 assert(rGraphic.IsLink() &&
815 (rGraphic.GetLink().GetType() == GfxLinkType::NativeJpg ||
816 rGraphic.GetLink().GetType() == GfxLinkType::NativePng ||
817 rGraphic.GetLink().GetType() == GfxLinkType::NativePdf));
819 // small items better off as PNG anyway
820 if ( rGraphic.GetSizePixel().Width() < 32 &&
821 rGraphic.GetSizePixel().Height() < 32 )
822 return false;
824 // FIXME: ideally we'd also pre-empt the DPI related scaling too.
826 Size aSize = rGraphic.GetSizePixel();
827 if (rGraphic.GetLink().GetDataSize() == 0)
828 return false;
829 sal_Int32 nCurrentRatio = (100 * aSize.Width() * aSize.Height() * 4) /
830 rGraphic.GetLink().GetDataSize();
832 if ( GetIsLosslessCompression() )
833 return !bReduceResolution && !GetIsReduceImageResolution();
834 else
836 static const struct {
837 sal_Int32 mnQuality;
838 sal_Int32 mnRatio;
839 } aRatios[] = { // minimum tolerable compression ratios
840 { 100, 400 }, { 95, 700 }, { 90, 1000 }, { 85, 1200 },
841 { 80, 1500 }, { 75, 1700 }
843 sal_Int32 nTargetRatio = 10000;
844 bool bIsTargetRatioReached = false;
845 for (auto & rRatio : aRatios)
847 if ( mnCompressionQuality > rRatio.mnQuality )
849 bIsTargetRatioReached = true;
850 break;
852 nTargetRatio = rRatio.mnRatio;
855 return ((nCurrentRatio > nTargetRatio) && bIsTargetRatioReached);
861 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */