1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
34 struct PDFExtOutDevDataSync
36 enum Action
{ CreateNamedDest
,
49 BeginStructureElement
,
51 SetCurrentStructureElement
,
52 SetStructureAttribute
,
53 SetStructureAttributeNumerical
,
54 SetStructureBoundingBox
,
66 struct PDFLinkDestination
68 tools::Rectangle mRect
;
71 PDFWriter::DestAreaType mAreaType
;
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
);
91 std::vector
< sal_Int32
> mParaIds
;
92 std::vector
< sal_Int32
> mStructIdMap
;
94 sal_Int32 mCurrentStructElement
;
95 std::vector
< sal_Int32
> mStructParents
;
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
116 if ( (sal_uInt32
)nLinkId
< mParaIds
.size() )
117 nLinkId
= mParaIds
[ nLinkId
];
121 SAL_WARN_IF( nLinkId
< 0, "vcl", "unmapped id in GlobalSyncData" );
127 sal_Int32
GlobalSyncData::GetMappedStructId( sal_Int32 nStructId
)
129 if ( (sal_uInt32
)nStructId
< mStructIdMap
.size() )
130 nStructId
= mStructIdMap
[ nStructId
];
134 SAL_WARN_IF( nStructId
< 0, "vcl", "unmapped structure id in GlobalSyncData" );
139 void GlobalSyncData::PlayGlobalActions( PDFWriter
& rWriter
)
141 for (std::deque
< PDFExtOutDevDataSync::Action
>::const_iterator
aIter( mActions
.begin() ), aEnd( mActions
.end() ) ;
142 aIter
!= aEnd
; ++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();
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();
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();
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();
195 case PDFExtOutDevDataSync::SetLinkDest
:
197 sal_Int32 nLinkId
= GetMappedId();
198 sal_Int32 nDestId
= GetMappedId();
199 rWriter
.SetLinkDest( nLinkId
, nDestId
);
202 case PDFExtOutDevDataSync::SetLinkURL
:
204 sal_Int32 nLinkId
= GetMappedId();
205 rWriter
.SetLinkURL( nLinkId
, mParaOUStrings
.front() );
206 mParaOUStrings
.pop_front();
209 case PDFExtOutDevDataSync::SetScreenURL
:
211 sal_Int32 nScreenId
= GetMappedId();
212 rWriter
.SetScreenURL(nScreenId
, mParaOUStrings
.front());
213 mParaOUStrings
.pop_front();
216 case PDFExtOutDevDataSync::SetScreenStream
:
218 sal_Int32 nScreenId
= GetMappedId();
219 rWriter
.SetScreenStream(nScreenId
, mParaOUStrings
.front());
220 mParaOUStrings
.pop_front();
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
) );
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();
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();
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();
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
:
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
> >
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
;
315 aSync
.nIdx
= pMtf
->GetActionSize();
317 aSync
.nIdx
= 0x7fffffff; // sync not possible
318 mActions
.push_back( aSync
);
320 bool PageSyncData::PlaySyncPageAct( PDFWriter
& rWriter
, sal_uInt32
& rCurGDIMtfAction
, const PDFExtOutDevData
& rOutDevData
)
323 if ( mActions
.size() && ( mActions
.front().nIdx
== rCurGDIMtfAction
) )
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
);
338 case PDFExtOutDevDataSync::EndStructureElement
:
340 rWriter
.EndStructureElement();
343 case PDFExtOutDevDataSync::SetCurrentStructureElement
:
345 rWriter
.SetCurrentStructureElement( mpGlobalData
->GetMappedStructId( mParaInts
.front() ) );
346 mParaInts
.pop_front();
349 case PDFExtOutDevDataSync::SetStructureAttribute
:
351 rWriter
.SetStructureAttribute( mParaStructAttributes
.front(), mParaStructAttributeValues
.front() );
352 mParaStructAttributeValues
.pop_front();
353 mParaStructAttributes
.pop_front();
356 case PDFExtOutDevDataSync::SetStructureAttributeNumerical
:
358 rWriter
.SetStructureAttributeNumerical( mParaStructAttributes
.front(), mParaInts
.front() );
359 mParaStructAttributes
.pop_front();
360 mParaInts
.pop_front();
363 case PDFExtOutDevDataSync::SetStructureBoundingBox
:
365 rWriter
.SetStructureBoundingBox( mParaRects
.front() );
366 mParaRects
.pop_front();
369 case PDFExtOutDevDataSync::SetActualText
:
371 rWriter
.SetActualText( mParaOUStrings
.front() );
372 mParaOUStrings
.pop_front();
375 case PDFExtOutDevDataSync::SetAlternateText
:
377 rWriter
.SetAlternateText( mParaOUStrings
.front() );
378 mParaOUStrings
.pop_front();
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();
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
;
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
)
446 basegfx::B2DPolyPolygon
aRect( basegfx::tools::createPolygonFromRect(
447 basegfx::B2DRectangle( aVisibleOutputRect
.Left(), aVisibleOutputRect
.Top(),
448 aVisibleOutputRect
.Right(), aVisibleOutputRect
.Bottom() ) ) );
449 rWriter
.SetClipRegion( aRect
);
455 AlphaMask
aAlphaMask(aGraphic
.GetSizePixel());
456 aAlphaMask
.Erase(nTransparency
);
457 aMask
= aAlphaMask
.GetBitmap();
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
)
472 mbGroupIgnoreGDIMtfActions
= false;
474 mCurrentGraphic
.Clear();
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
:
492 else if ( mbGroupIgnoreGDIMtfActions
)
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 ),
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
)
537 void PDFExtOutDevData::SetCurrentPageNumber( const sal_Int32 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
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
++;
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
);
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
);
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
);
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
);
728 sal_Int32 nNewId
= mpGlobalSyncData
->mStructParents
.size();
729 mpGlobalSyncData
->mStructParents
.push_back( mpGlobalSyncData
->mCurrentStructElement
);
730 mpGlobalSyncData
->mCurrentStructElement
= 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
);
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
);
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
);
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 )
824 // FIXME: ideally we'd also pre-empt the DPI related scaling too.
826 Size aSize
= rGraphic
.GetSizePixel();
827 if (rGraphic
.GetLink().GetDataSize() == 0)
829 sal_Int32 nCurrentRatio
= (100 * aSize
.Width() * aSize
.Height() * 4) /
830 rGraphic
.GetLink().GetDataSize();
832 if ( GetIsLosslessCompression() )
833 return !bReduceResolution
&& !GetIsReduceImageResolution();
836 static const struct {
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;
852 nTargetRatio
= rRatio
.mnRatio
;
855 return ((nCurrentRatio
> nTargetRatio
) && bIsTargetRatioReached
);
861 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */