LibreOffice Module vcl (master)  1
pdfextoutdevdata.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/canvastools.hxx>
21 #include <vcl/pdfextoutdevdata.hxx>
22 #include <vcl/graph.hxx>
23 #include <vcl/outdev.hxx>
24 #include <vcl/gfxlink.hxx>
25 #include <vcl/metaact.hxx>
26 #include <vcl/graphicfilter.hxx>
29 #include <sal/log.hxx>
30 #include <osl/diagnose.h>
31 #include <tools/stream.hxx>
32 
33 #include <memory>
34 #include <map>
35 
36 namespace vcl
37 {
39 {
52 
64  };
65 
66  sal_uInt32 nIdx;
68 };
69 
71 {
74  sal_Int32 mPageNr;
76 };
77 
79 {
80  std::deque< PDFExtOutDevDataSync::Action > mActions;
81  std::deque< MapMode > mParaMapModes;
82  std::deque< tools::Rectangle > mParaRects;
83  std::deque< sal_Int32 > mParaInts;
84  std::deque< sal_uInt32 > mParauInts;
85  std::deque< OUString > mParaOUStrings;
86  std::deque< PDFWriter::DestAreaType > mParaDestAreaTypes;
87  std::deque< PDFNote > mParaPDFNotes;
88  std::deque< PDFWriter::PageTransition > mParaPageTransitions;
89  ::std::map< sal_Int32, PDFLinkDestination > mFutureDestinations;
90 
91  sal_Int32 GetMappedId();
92  sal_Int32 GetMappedStructId( sal_Int32 );
93 
94  sal_Int32 mCurId;
95  std::vector< sal_Int32 > mParaIds;
96  std::vector< sal_Int32 > mStructIdMap;
97 
99  std::vector< sal_Int32 > mStructParents;
101  mCurId ( 0 ),
102  mCurrentStructElement( 0 )
103  {
104  mStructParents.push_back( 0 );
105  mStructIdMap.push_back( 0 );
106  }
107  void PlayGlobalActions( PDFWriter& rWriter );
108 };
109 
111 {
112  sal_Int32 nLinkId = mParaInts.front();
113  mParaInts.pop_front();
114 
115  /* negative values are intentionally passed as invalid IDs
116  * e.g. to create a new top level outline item
117  */
118  if( nLinkId >= 0 )
119  {
120  if ( static_cast<sal_uInt32>(nLinkId) < mParaIds.size() )
121  nLinkId = mParaIds[ nLinkId ];
122  else
123  nLinkId = -1;
124 
125  SAL_WARN_IF( nLinkId < 0, "vcl", "unmapped id in GlobalSyncData" );
126  }
127 
128  return nLinkId;
129 }
130 
131 sal_Int32 GlobalSyncData::GetMappedStructId( sal_Int32 nStructId )
132 {
133  if ( static_cast<sal_uInt32>(nStructId) < mStructIdMap.size() )
134  nStructId = mStructIdMap[ nStructId ];
135  else
136  nStructId = -1;
137 
138  SAL_WARN_IF( nStructId < 0, "vcl", "unmapped structure id in GlobalSyncData" );
139 
140  return nStructId;
141 }
142 
144 {
145  for (auto const& action : mActions)
146  {
147  switch (action)
148  {
150  {
151  rWriter.Push( PushFlags::MAPMODE );
152  rWriter.SetMapMode( mParaMapModes.front() );
153  mParaMapModes.pop_front();
154  mParaIds.push_back( rWriter.CreateNamedDest( mParaOUStrings.front(), mParaRects.front(), mParaInts.front(), mParaDestAreaTypes.front() ) );
155  mParaOUStrings.pop_front();
156  mParaRects.pop_front();
157  mParaInts.pop_front();
158  mParaDestAreaTypes.pop_front();
159  rWriter.Pop();
160  }
161  break;
163  {
164  rWriter.Push( PushFlags::MAPMODE );
165  rWriter.SetMapMode( mParaMapModes.front() );
166  mParaMapModes.pop_front();
167  mParaIds.push_back( rWriter.CreateDest( mParaRects.front(), mParaInts.front(), mParaDestAreaTypes.front() ) );
168  mParaRects.pop_front();
169  mParaInts.pop_front();
170  mParaDestAreaTypes.pop_front();
171  rWriter.Pop();
172  }
173  break;
175  {
176  rWriter.Push( PushFlags::MAPMODE );
177  rWriter.SetMapMode( mParaMapModes.front() );
178  mParaMapModes.pop_front();
179  mParaIds.push_back( rWriter.CreateLink( mParaRects.front(), mParaInts.front() ) );
180  // resolve LinkAnnotation structural attribute
181  rWriter.SetLinkPropertyID( mParaIds.back(), sal_Int32(mParaIds.size()-1) );
182  mParaRects.pop_front();
183  mParaInts.pop_front();
184  rWriter.Pop();
185  }
186  break;
188  {
189  rWriter.Push(PushFlags::MAPMODE);
190  rWriter.SetMapMode(mParaMapModes.front());
191  mParaMapModes.pop_front();
192  mParaIds.push_back(rWriter.CreateScreen(mParaRects.front(), mParaInts.front()));
193  mParaRects.pop_front();
194  mParaInts.pop_front();
195  rWriter.Pop();
196  }
197  break;
199  {
200  sal_Int32 nLinkId = GetMappedId();
201  sal_Int32 nDestId = GetMappedId();
202  rWriter.SetLinkDest( nLinkId, nDestId );
203  }
204  break;
206  {
207  sal_Int32 nLinkId = GetMappedId();
208  rWriter.SetLinkURL( nLinkId, mParaOUStrings.front() );
209  mParaOUStrings.pop_front();
210  }
211  break;
213  {
214  sal_Int32 nScreenId = GetMappedId();
215  rWriter.SetScreenURL(nScreenId, mParaOUStrings.front());
216  mParaOUStrings.pop_front();
217  }
218  break;
220  {
221  sal_Int32 nScreenId = GetMappedId();
222  rWriter.SetScreenStream(nScreenId, mParaOUStrings.front());
223  mParaOUStrings.pop_front();
224  }
225  break;
227  {
228  const sal_Int32 nDestId = mParaInts.front();
229  mParaInts.pop_front();
230  OSL_ENSURE( mFutureDestinations.find( nDestId ) != mFutureDestinations.end(),
231  "GlobalSyncData::PlayGlobalActions: DescribeRegisteredRequest has not been called for that destination!" );
232 
233  PDFLinkDestination& rDest = mFutureDestinations[ nDestId ];
234 
235  rWriter.Push( PushFlags::MAPMODE );
236  rWriter.SetMapMode( rDest.mMapMode );
237  mParaIds.push_back( rWriter.RegisterDestReference( nDestId, rDest.mRect, rDest.mPageNr, rDest.mAreaType ) );
238  rWriter.Pop();
239  }
240  break;
242  {
243  sal_Int32 nParent = GetMappedId();
244  sal_Int32 nLinkId = GetMappedId();
245  mParaIds.push_back( rWriter.CreateOutlineItem( nParent, mParaOUStrings.front(), nLinkId ) );
246  mParaOUStrings.pop_front();
247  }
248  break;
250  {
251  rWriter.Push( PushFlags::MAPMODE );
252  rWriter.SetMapMode( mParaMapModes.front() );
253  rWriter.CreateNote( mParaRects.front(), mParaPDFNotes.front(), mParaInts.front() );
254  mParaMapModes.pop_front();
255  mParaRects.pop_front();
256  mParaPDFNotes.pop_front();
257  mParaInts.pop_front();
258  }
259  break;
261  {
262  rWriter.SetPageTransition( mParaPageTransitions.front(), mParauInts.front(), mParaInts.front() );
263  mParaPageTransitions.pop_front();
264  mParauInts.pop_front();
265  mParaInts.pop_front();
266  }
267  break;
279  break;
280  }
281  }
282 }
283 
285 {
286  std::deque< PDFExtOutDevDataSync > mActions;
287  std::deque< tools::Rectangle > mParaRects;
288  std::deque< sal_Int32 > mParaInts;
289  std::deque< OUString > mParaOUStrings;
290  std::deque< PDFWriter::StructElement > mParaStructElements;
291  std::deque< PDFWriter::StructAttribute > mParaStructAttributes;
292  std::deque< PDFWriter::StructAttributeValue > mParaStructAttributeValues;
293  std::deque< Graphic > mGraphics;
295  std::deque< std::shared_ptr< PDFWriter::AnyWidget > >
298 
300 
301 
302  explicit PageSyncData( GlobalSyncData* pGlobal )
303  : mbGroupIgnoreGDIMtfActions ( false )
304  { mpGlobalData = pGlobal; }
305 
306  void PushAction( const OutputDevice& rOutDev, const PDFExtOutDevDataSync::Action eAct );
307  bool PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAction, const GDIMetaFile& rMtf, const PDFExtOutDevData& rOutDevData );
308 };
309 
311 {
312  GDIMetaFile* pMtf = rOutDev.GetConnectMetaFile();
313  SAL_WARN_IF( !pMtf, "vcl", "PageSyncData::PushAction -> no ConnectMetaFile !!!" );
314 
315  PDFExtOutDevDataSync aSync;
316  aSync.eAct = eAct;
317  if ( pMtf )
318  aSync.nIdx = pMtf->GetActionSize();
319  else
320  aSync.nIdx = 0x7fffffff; // sync not possible
321  mActions.push_back( aSync );
322 }
323 bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAction, const GDIMetaFile& rMtf, const PDFExtOutDevData& rOutDevData )
324 {
325  bool bRet = false;
326  if ( !mActions.empty() && ( mActions.front().nIdx == rCurGDIMtfAction ) )
327  {
328  bRet = true;
329  PDFExtOutDevDataSync aDataSync = mActions.front();
330  mActions.pop_front();
331  switch( aDataSync.eAct )
332  {
334  {
335  sal_Int32 nNewEl = rWriter.BeginStructureElement( mParaStructElements.front(), mParaOUStrings.front() ) ;
336  mParaStructElements.pop_front();
337  mParaOUStrings.pop_front();
338  mpGlobalData->mStructIdMap.push_back( nNewEl );
339  }
340  break;
342  {
343  rWriter.EndStructureElement();
344  }
345  break;
347  {
349  mParaInts.pop_front();
350  }
351  break;
353  {
355  mParaStructAttributeValues.pop_front();
356  mParaStructAttributes.pop_front();
357  }
358  break;
360  {
362  mParaStructAttributes.pop_front();
363  mParaInts.pop_front();
364  }
365  break;
367  {
368  rWriter.SetStructureBoundingBox( mParaRects.front() );
369  mParaRects.pop_front();
370  }
371  break;
373  {
374  rWriter.SetActualText( mParaOUStrings.front() );
375  mParaOUStrings.pop_front();
376  }
377  break;
379  {
380  rWriter.SetAlternateText( mParaOUStrings.front() );
381  mParaOUStrings.pop_front();
382  }
383  break;
385  {
386  std::shared_ptr< PDFWriter::AnyWidget > pControl( mControls.front() );
387  SAL_WARN_IF( !pControl.get(), "vcl", "PageSyncData::PlaySyncPageAct: invalid widget!" );
388  if ( pControl.get() )
389  rWriter.CreateControl( *pControl );
390  mControls.pop_front();
391  }
392  break;
394  {
395  /* first determining if this BeginGroup is starting a GfxLink,
396  by searching for an EndGroup or an EndGroupGfxLink */
398  auto isStartingGfxLink = std::any_of(mActions.begin(), mActions.end(),
399  [](const PDFExtOutDevDataSync& rAction) { return rAction.eAct == PDFExtOutDevDataSync::EndGroupGfxLink; });
400  if ( isStartingGfxLink )
401  {
402  Graphic& rGraphic = mGraphics.front();
403  if ( rGraphic.IsGfxLink() && mParaRects.size() >= 2 )
404  {
405  GfxLinkType eType = rGraphic.GetGfxLink().GetType();
406  if ( eType == GfxLinkType::NativeJpg )
407  {
410  mCurrentGraphic = rGraphic;
411  }
412  else if ( eType == GfxLinkType::NativePng || eType == GfxLinkType::NativePdf )
413  {
414  if ( eType == GfxLinkType::NativePdf || rOutDevData.HasAdequateCompression(rGraphic, mParaRects[0], mParaRects[1]) )
415  mCurrentGraphic = rGraphic;
416  }
417  }
418  }
419  }
420  break;
422  {
423  tools::Rectangle aOutputRect, aVisibleOutputRect;
424  Graphic aGraphic( mGraphics.front() );
425 
426  mGraphics.pop_front();
427  sal_Int32 nTransparency = mParaInts.front();
428  mParaInts.pop_front();
429  aOutputRect = mParaRects.front();
430  mParaRects.pop_front();
431  aVisibleOutputRect = mParaRects.front();
432  mParaRects.pop_front();
433 
435  {
436  bool bClippingNeeded = ( aOutputRect != aVisibleOutputRect ) && !aVisibleOutputRect.IsEmpty();
437 
438  GfxLink aGfxLink( aGraphic.GetGfxLink() );
439  if ( aGfxLink.GetType() == GfxLinkType::NativeJpg )
440  {
441  if ( bClippingNeeded )
442  {
443  rWriter.Push();
445  vcl::unotools::b2DRectangleFromRectangle(aVisibleOutputRect) ) );
446  rWriter.SetClipRegion( aRect);
447  }
448 
449  Bitmap aMask;
450  if (nTransparency)
451  {
452  AlphaMask aAlphaMask(aGraphic.GetSizePixel());
453  aAlphaMask.Erase(nTransparency);
454  aMask = aAlphaMask.GetBitmap();
455  }
456 
457  SvMemoryStream aTmp;
458  const sal_uInt8* pData = aGfxLink.GetData();
459  sal_uInt32 nBytes = aGfxLink.GetDataSize();
460  if( pData && nBytes )
461  {
462  aTmp.WriteBytes( pData, nBytes );
463 
464  // Look up the output rectangle from the previous
465  // bitmap scale action if possible. This has the
466  // correct position and size for images with a
467  // custom translation (Writer header) or scaling
468  // (Impress notes page).
469  if (rCurGDIMtfAction > 0)
470  {
471  const MetaAction* pAction = rMtf.GetAction(rCurGDIMtfAction - 1);
472  if (pAction && pAction->GetType() == MetaActionType::BMPSCALE)
473  {
474  const MetaBmpScaleAction* pA
475  = static_cast<const MetaBmpScaleAction*>(pAction);
476  aOutputRect.SetPos(pA->GetPoint());
477  aOutputRect.SetSize(pA->GetSize());
478  }
479  }
480 
481  rWriter.DrawJPGBitmap( aTmp, aGraphic.GetBitmapEx().GetBitCount() > 8, aGraphic.GetSizePixel(), aOutputRect, aMask, aGraphic );
482  }
483 
484  if ( bClippingNeeded )
485  rWriter.Pop();
486  }
488  }
490  }
491  break;
504  break;
505  }
506  }
507  else if ( mbGroupIgnoreGDIMtfActions )
508  {
509  rCurGDIMtfAction++;
510  bRet = true;
511  }
512  return bRet;
513 }
514 
516  mrOutDev ( rOutDev ),
517  mbTaggedPDF ( false ),
518  mbExportNotes ( true ),
519  mbExportNotesPages ( false ),
520  mbTransitionEffects ( true ),
521  mbUseLosslessCompression( true ),
522  mbReduceImageResolution ( false ),
523  mbExportFormFields ( false ),
524  mbExportBookmarks ( false ),
525  mbExportHiddenSlides ( false ),
526  mbSinglePageSheets ( false ),
527  mbExportNDests ( false ),
528  mnPage ( -1 ),
529  mnCompressionQuality ( 90 ),
530  mpGlobalSyncData ( new GlobalSyncData() )
531 {
532  mpPageSyncData.reset( new PageSyncData( mpGlobalSyncData.get() ) );
533 }
534 
536 {
537  mpPageSyncData.reset();
538  mpGlobalSyncData.reset();
539 }
540 
542 {
543  return mpPageSyncData->mCurrentGraphic;
544 }
545 
546 void PDFExtOutDevData::SetDocumentLocale( const css::lang::Locale& rLoc )
547 {
548  maDocLocale = rLoc;
549 }
550 void PDFExtOutDevData::SetCurrentPageNumber( const sal_Int32 nPage )
551 {
552  mnPage = nPage;
553 }
554 void PDFExtOutDevData::SetIsLosslessCompression( const bool bUseLosslessCompression )
555 {
556  mbUseLosslessCompression = bUseLosslessCompression;
557 }
558 void PDFExtOutDevData::SetCompressionQuality( const sal_Int32 nQuality )
559 {
560  mnCompressionQuality = nQuality;
561 }
562 void PDFExtOutDevData::SetIsReduceImageResolution( const bool bReduceImageResolution )
563 {
564  mbReduceImageResolution = bReduceImageResolution;
565 }
566 void PDFExtOutDevData::SetIsExportNotes( const bool bExportNotes )
567 {
568  mbExportNotes = bExportNotes;
569 }
570 void PDFExtOutDevData::SetIsExportNotesPages( const bool bExportNotesPages )
571 {
572  mbExportNotesPages = bExportNotesPages;
573 }
574 void PDFExtOutDevData::SetIsExportTaggedPDF( const bool bTaggedPDF )
575 {
576  mbTaggedPDF = bTaggedPDF;
577 }
578 void PDFExtOutDevData::SetIsExportTransitionEffects( const bool bTransitionEffects )
579 {
580  mbTransitionEffects = bTransitionEffects;
581 }
582 void PDFExtOutDevData::SetIsExportFormFields( const bool bExportFomtFields )
583 {
584  mbExportFormFields = bExportFomtFields;
585 }
586 void PDFExtOutDevData::SetIsExportBookmarks( const bool bExportBookmarks )
587 {
588  mbExportBookmarks = bExportBookmarks;
589 }
590 void PDFExtOutDevData::SetIsExportHiddenSlides( const bool bExportHiddenSlides )
591 {
592  mbExportHiddenSlides = bExportHiddenSlides;
593 }
594 void PDFExtOutDevData::SetIsSinglePageSheets( const bool bSinglePageSheets )
595 {
596  mbSinglePageSheets = bSinglePageSheets;
597 }
598 void PDFExtOutDevData::SetIsExportNamedDestinations( const bool bExportNDests )
599 {
600  mbExportNDests = bExportNDests;
601 }
603 {
605 }
606 bool PDFExtOutDevData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rIdx, const GDIMetaFile& rMtf )
607 {
608  return mpPageSyncData->PlaySyncPageAct( rWriter, rIdx, rMtf, *this );
609 }
611 {
612  mpGlobalSyncData->PlayGlobalActions( rWriter );
613 }
614 
615 /* global actions, synchronisation to the recorded metafile isn't needed,
616  all actions will be played after the last page was recorded
617 */
618 //--->i56629
619 sal_Int32 PDFExtOutDevData::CreateNamedDest(const OUString& sDestName, const tools::Rectangle& rRect, sal_Int32 nPageNr )
620 {
622  mpGlobalSyncData->mParaOUStrings.push_back( sDestName );
623  mpGlobalSyncData->mParaRects.push_back( rRect );
624  mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
625  mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
626  mpGlobalSyncData->mParaDestAreaTypes.push_back( PDFWriter::DestAreaType::XYZ );
627 
628  return mpGlobalSyncData->mCurId++;
629 }
630 //<---i56629
632 {
633  const sal_Int32 nLinkDestID = mpGlobalSyncData->mCurId++;
635  mpGlobalSyncData->mParaInts.push_back( nLinkDestID );
636 
637  return nLinkDestID;
638 }
639 void PDFExtOutDevData::DescribeRegisteredDest( sal_Int32 nDestId, const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
640 {
641  OSL_PRECOND( nDestId != -1, "PDFExtOutDevData::DescribeRegisteredDest: invalid destination Id!" );
642  PDFLinkDestination aLinkDestination;
643  aLinkDestination.mRect = rRect;
644  aLinkDestination.mMapMode = mrOutDev.GetMapMode();
645  aLinkDestination.mPageNr = nPageNr == -1 ? mnPage : nPageNr;
646  aLinkDestination.mAreaType = eType;
647  mpGlobalSyncData->mFutureDestinations[ nDestId ] = aLinkDestination;
648 }
649 sal_Int32 PDFExtOutDevData::CreateDest( const tools::Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
650 {
651  mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateDest );
652  mpGlobalSyncData->mParaRects.push_back( rRect );
653  mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
654  mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
655  mpGlobalSyncData->mParaDestAreaTypes.push_back( eType );
656  return mpGlobalSyncData->mCurId++;
657 }
658 sal_Int32 PDFExtOutDevData::CreateLink( const tools::Rectangle& rRect, sal_Int32 nPageNr )
659 {
660  mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateLink );
661  mpGlobalSyncData->mParaRects.push_back( rRect );
662  mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
663  mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
664  return mpGlobalSyncData->mCurId++;
665 }
666 
667 sal_Int32 PDFExtOutDevData::CreateScreen(const tools::Rectangle& rRect, sal_Int32 nPageNr)
668 {
670  mpGlobalSyncData->mParaRects.push_back(rRect);
671  mpGlobalSyncData->mParaMapModes.push_back(mrOutDev.GetMapMode());
672  mpGlobalSyncData->mParaInts.push_back(nPageNr);
673  return mpGlobalSyncData->mCurId++;
674 }
675 
676 void PDFExtOutDevData::SetLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId )
677 {
679  mpGlobalSyncData->mParaInts.push_back( nLinkId );
680  mpGlobalSyncData->mParaInts.push_back( nDestId );
681 }
682 void PDFExtOutDevData::SetLinkURL( sal_Int32 nLinkId, const OUString& rURL )
683 {
684  mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::SetLinkURL );
685  mpGlobalSyncData->mParaInts.push_back( nLinkId );
686  mpGlobalSyncData->mParaOUStrings.push_back( rURL );
687 }
688 
689 void PDFExtOutDevData::SetScreenURL(sal_Int32 nScreenId, const OUString& rURL)
690 {
692  mpGlobalSyncData->mParaInts.push_back(nScreenId);
693  mpGlobalSyncData->mParaOUStrings.push_back(rURL);
694 }
695 
696 void PDFExtOutDevData::SetScreenStream(sal_Int32 nScreenId, const OUString& rURL)
697 {
699  mpGlobalSyncData->mParaInts.push_back(nScreenId);
700  mpGlobalSyncData->mParaOUStrings.push_back(rURL);
701 }
702 
703 sal_Int32 PDFExtOutDevData::CreateOutlineItem( sal_Int32 nParent, const OUString& rText, sal_Int32 nDestID )
704 {
705  if (nParent == -1)
706  // Has no parent, it's a chapter / heading 1.
707  maChapterNames.push_back(rText);
708 
710  mpGlobalSyncData->mParaInts.push_back( nParent );
711  mpGlobalSyncData->mParaOUStrings.push_back( rText );
712  mpGlobalSyncData->mParaInts.push_back( nDestID );
713  return mpGlobalSyncData->mCurId++;
714 }
715 void PDFExtOutDevData::CreateNote( const tools::Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr )
716 {
717  mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateNote );
718  mpGlobalSyncData->mParaRects.push_back( rRect );
719  mpGlobalSyncData->mParaMapModes.push_back( mrOutDev.GetMapMode() );
720  mpGlobalSyncData->mParaPDFNotes.push_back( rNote );
721  mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
722 }
724 {
726  mpGlobalSyncData->mParaPageTransitions.push_back( eType );
727  mpGlobalSyncData->mParauInts.push_back( nMilliSec );
728  mpGlobalSyncData->mParaInts.push_back( mnPage );
729 }
730 
731 /* local (page), actions have to be played synchronously to the actions of
732  of the recorded metafile (created by each xRenderable->render()) */
733  sal_Int32 PDFExtOutDevData::BeginStructureElement( PDFWriter::StructElement eType, const OUString& rAlias )
734 {
736  mpPageSyncData->mParaStructElements.push_back( eType );
737  mpPageSyncData->mParaOUStrings.push_back( rAlias );
738  // need a global id
739  sal_Int32 nNewId = mpGlobalSyncData->mStructParents.size();
740  mpGlobalSyncData->mStructParents.push_back( mpGlobalSyncData->mCurrentStructElement );
741  mpGlobalSyncData->mCurrentStructElement = nNewId;
742  return nNewId;
743 }
745 {
747  mpGlobalSyncData->mCurrentStructElement = mpGlobalSyncData->mStructParents[ mpGlobalSyncData->mCurrentStructElement ];
748 }
750 {
751  bool bSuccess = false;
752  if( sal_uInt32(nStructId) < mpGlobalSyncData->mStructParents.size() )
753  {
754  mpGlobalSyncData->mCurrentStructElement = nStructId;
756  mpPageSyncData->mParaInts.push_back( nStructId );
757  bSuccess = true;
758  }
759  return bSuccess;
760 }
762 {
763  return mpGlobalSyncData->mCurrentStructElement;
764 }
766 {
768  mpPageSyncData->mParaStructAttributes.push_back( eAttr );
769  mpPageSyncData->mParaStructAttributeValues.push_back( eVal );
770 }
772 {
774  mpPageSyncData->mParaStructAttributes.push_back( eAttr );
775  mpPageSyncData->mParaInts.push_back( nValue );
776 }
778 {
780  mpPageSyncData->mParaRects.push_back( rRect );
781 }
782 void PDFExtOutDevData::SetActualText( const OUString& rText )
783 {
785  mpPageSyncData->mParaOUStrings.push_back( rText );
786 }
787 void PDFExtOutDevData::SetAlternateText( const OUString& rText )
788 {
790  mpPageSyncData->mParaOUStrings.push_back( rText );
791 }
792 
794 {
796 
797  std::shared_ptr< PDFWriter::AnyWidget > pClone( rControlType.Clone() );
798  mpPageSyncData->mControls.push_back( pClone );
799 }
800 
802 {
804 }
805 
806 void PDFExtOutDevData::EndGroup( const Graphic& rGraphic,
807  sal_uInt8 nTransparency,
808  const tools::Rectangle& rOutputRect,
809  const tools::Rectangle& rVisibleOutputRect )
810 {
812  mpPageSyncData->mGraphics.push_back( rGraphic );
813  mpPageSyncData->mParaInts.push_back( nTransparency );
814  mpPageSyncData->mParaRects.push_back( rOutputRect );
815  mpPageSyncData->mParaRects.push_back( rVisibleOutputRect );
816 }
817 
818 // Avoids expensive de-compression and re-compression of large images.
820  const tools::Rectangle & rOutputRect,
821  const tools::Rectangle & rVisibleOutputRect ) const
822 {
823  assert(rGraphic.IsGfxLink() &&
824  (rGraphic.GetGfxLink().GetType() == GfxLinkType::NativeJpg ||
825  rGraphic.GetGfxLink().GetType() == GfxLinkType::NativePng ||
826  rGraphic.GetGfxLink().GetType() == GfxLinkType::NativePdf));
827 
828  if (rOutputRect != rVisibleOutputRect)
829  // rOutputRect is the crop rectangle, re-compress cropped image.
830  return false;
831 
833  // Reducing resolution was requested, implies that re-compressing is
834  // wanted.
835  return false;
836 
837  if (rGraphic.GetGfxLink().GetDataSize() == 0)
838  return false;
839 
840  GfxLink aLink = rGraphic.GetGfxLink();
841  SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(aLink.GetData()), aLink.GetDataSize(),
842  StreamMode::READ | StreamMode::WRITE);
843  GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
844  if (aDescriptor.Detect(true) && aDescriptor.GetNumberOfImageComponents() == 4)
845  // 4 means CMYK, which is not handled.
846  return false;
847 
848  const Size aSize = rGraphic.GetSizePixel();
849 
850  // small items better off as PNG anyway
851  if ( aSize.Width() < 32 &&
852  aSize.Height() < 32 )
853  return false;
854 
856  return !GetIsReduceImageResolution();
857 
858  // FIXME: ideally we'd also pre-empt the DPI related scaling too.
859  sal_Int32 nCurrentRatio = (100 * aSize.Width() * aSize.Height() * 4) /
860  rGraphic.GetGfxLink().GetDataSize();
861 
862  static const struct {
863  sal_Int32 const mnQuality;
864  sal_Int32 const mnRatio;
865  } aRatios[] = { // minimum tolerable compression ratios
866  { 100, 400 }, { 95, 700 }, { 90, 1000 }, { 85, 1200 },
867  { 80, 1500 }, { 75, 1700 }
868  };
869  sal_Int32 nTargetRatio = 10000;
870  bool bIsTargetRatioReached = false;
871  for (auto & rRatio : aRatios)
872  {
873  if ( mnCompressionQuality > rRatio.mnQuality )
874  {
875  bIsTargetRatioReached = true;
876  break;
877  }
878  nTargetRatio = rRatio.mnRatio;
879  }
880 
881  return ((nCurrentRatio > nTargetRatio) && bIsTargetRatioReached);
882 }
883 
884 }
885 
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::deque< PDFWriter::StructAttributeValue > mParaStructAttributeValues
void SetCurrentPageNumber(const sal_Int32 nPage)
long Width() const
std::deque< PDFWriter::StructAttribute > mParaStructAttributes
void SetPos(const Point &rPoint)
std::deque< PDFWriter::StructElement > mParaStructElements
void PushAction(const OutputDevice &rOutDev, const PDFExtOutDevDataSync::Action eAct)
const Point & GetPoint() const
Definition: metaact.hxx:700
void SetIsExportNotes(const bool bExportNotes)
void SetPageTransition(PageTransition eType, sal_uInt32 nMilliSec, sal_Int32 nPageNr)
Sets the transitional effect to be applied when the current page gets shown.
Definition: pdfwriter.cxx:429
void BeginGroup()
Start a new group of render output.
sal_Int32 RegisterDest()
registers a destination for which a destination ID needs to be known immediately, instead of later on...
std::deque< sal_Int32 > mParaInts
Size GetSizePixel(const OutputDevice *pRefDevice=nullptr) const
Definition: graph.cxx:429
long Height() const
bool PlaySyncPageAct(PDFWriter &rWriter, sal_uInt32 &rCurGDIMtfAction, const GDIMetaFile &rMtf)
bool SetCurrentStructureElement(sal_Int32 nElement)
set the current structure element
void SetScreenURL(sal_Int32 nScreenId, const OUString &rURL)
Set URL for a linked Screen annotation.
void SetAlternateText(const OUString &rText)
set the Alt attribute of a strutural element
sal_Int32 BeginStructureElement(enum StructElement eType, const OUString &rAlias)
begin a new logical structure element
Definition: pdfwriter.cxx:389
std::deque< PDFWriter::DestAreaType > mParaDestAreaTypes
void SetStructureAttribute(PDFWriter::StructAttribute eAttr, PDFWriter::StructAttributeValue eVal)
set a structure attribute on the current structural element
void SetActualText(const OUString &rText)
set the ActualText attribute of a structural element
Definition: pdfwriter.cxx:419
std::deque< sal_Int32 > mParaInts
const Size & GetSize() const
Definition: metaact.hxx:701
const MapMode & GetMapMode() const
Definition: outdev.hxx:1674
void SetIsReduceImageResolution(const bool bReduceImageResolution)
virtual ~PDFExtOutDevData() override
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:417
std::deque< tools::Rectangle > mParaRects
void SetIsExportNamedDestinations(const bool bExportNDests)
std::vector< sal_Int32 > mStructParents
bool IsGfxLink() const
Definition: graph.cxx:532
void SetStructureBoundingBox(const tools::Rectangle &rRect)
set the bounding box of a structural element
Definition: pdfwriter.cxx:414
std::unique_ptr< GlobalSyncData > mpGlobalSyncData
bool IsEmpty() const
void Clear()
Definition: graph.cxx:307
bool GetIsLosslessCompression() const
void SetLinkPropertyID(sal_Int32 nLinkId, sal_Int32 nPropertyID)
Resolve link in logical structure.
Definition: pdfwriter.cxx:374
std::deque< std::shared_ptr< PDFWriter::AnyWidget > > mControls
std::deque< sal_uInt32 > mParauInts
void EndStructureElement()
end the current logical structure element
Definition: pdfwriter.cxx:394
std::vector< sal_Int32 > mParaIds
sal_Int32 CreateNamedDest(const OUString &sDestName, const tools::Rectangle &rRect, sal_Int32 nPageNr, DestAreaType eType)
Create a new named destination to be used in a link from another PDF document.
Definition: pdfwriter.cxx:345
void EndGroup(const Graphic &rGraphic, sal_uInt8 nTransparency, const tools::Rectangle &rOutputRect, const tools::Rectangle &rVisibleOutputRect)
End render output.
PDFWriter::DestAreaType mAreaType
void SetLinkDest(sal_Int32 nLinkId, sal_Int32 nDestId)
Set the destination for a link.
PageSyncData(GlobalSyncData *pGlobal)
std::vector< OUString > maChapterNames
sal_Int32 GetCurrentStructureElement() const
get the current structure element id
void DrawJPGBitmap(SvStream &rJPGData, bool bIsTrueColor, const Size &rSrcSizePixel, const tools::Rectangle &rTargetArea, const Bitmap &rMask, const Graphic &rGraphic)
Insert a JPG encoded image (optionally with mask)
Definition: pdfwriter.cxx:325
void SetIsExportFormFields(const bool bExportFormFields)
std::deque< Graphic > mGraphics
std::deque< OUString > mParaOUStrings
void SetAlternateText(const OUString &rText)
set the Alt attribute of a strutural element
Definition: pdfwriter.cxx:424
std::deque< PDFExtOutDevDataSync::Action > mActions
void SetIsSinglePageSheets(const bool bSinglePageSheets)
void SetIsExportBookmarks(const bool bExportBookmarks)
void Erase(sal_uInt8 cTransparency)
Definition: alpha.cxx:75
PDFExtOutDevData(const OutputDevice &rOutDev)
void SetLinkDest(sal_Int32 nLinkId, sal_Int32 nDestId)
Set the destination for a link will change a URL type link to a dest link if necessary.
Definition: pdfwriter.cxx:354
void PlayGlobalActions(PDFWriter &rWriter)
void SetCompressionQuality(const sal_Int32 nQuality)
void SetStructureAttributeNumerical(PDFWriter::StructAttribute eAttr, sal_Int32 nValue)
set a structure attribute on the current structural element
void SetIsExportNotesPages(const bool bExportNotesPages)
std::deque< PDFNote > mParaPDFNotes
void SetSize(const Size &rSize)
void SetIsExportHiddenSlides(const bool bExportHiddenSlides)
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
GlobalSyncData * mpGlobalData
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
std::size_t WriteBytes(const void *pData, std::size_t nSize)
sal_Int32 CreateDest(const tools::Rectangle &rRect, sal_Int32 nPageNr=-1, PDFWriter::DestAreaType eType=PDFWriter::DestAreaType::XYZ)
Create a new destination to be used in a link.
void SetStructureAttributeNumerical(enum StructAttribute eAttr, sal_Int32 nValue)
set a structure attribute on the current structural element
Definition: pdfwriter.cxx:409
virtual std::unique_ptr< AnyWidget > Clone() const =0
std::deque< OUString > mParaOUStrings
void SetIsLosslessCompression(const bool bLosslessCompression)
void SetIsExportTaggedPDF(const bool bTaggedPDF)
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: pdfwriter.cxx:225
std::deque< PDFExtOutDevDataSync > mActions
void SetMapMode(const MapMode &rNewMapMode)
Definition: pdfwriter.cxx:235
GfxLink GetGfxLink() const
Definition: graph.cxx:527
DocumentType const eType
sal_Int32 BeginStructureElement(PDFWriter::StructElement eType, const OUString &rAlias=OUString())
begin a new logical structure element
sal_Int32 CreateScreen(const tools::Rectangle &rRect, sal_Int32 nPageNr)
Create a Screen annotation.
sal_Int32 RegisterDestReference(sal_Int32 nDestId, const tools::Rectangle &rRect, sal_Int32 nPageNr, DestAreaType eType)
creates a destination which is not intended to be referred to by a link, but by a public destination ...
Definition: pdfwriter.cxx:340
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
void DescribeRegisteredDest(sal_Int32 nDestId, const tools::Rectangle &rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType=PDFWriter::DestAreaType::XYZ)
provides detailed information about a destination range which previously has been registered using Re...
bool HasAdequateCompression(const Graphic &rGraphic, const tools::Rectangle &rOutputRect, const tools::Rectangle &rVisibleOutputRect) const
Detect if stream is compressed enough to avoid de-compress / scale & re-compress. ...
void SetLinkURL(sal_Int32 nLinkId, const OUString &rURL)
Set the URL for a link.
std::vector< sal_Int32 > mStructIdMap
void CreateNote(const tools::Rectangle &rRect, const PDFNote &rNote, sal_Int32 nPageNr=-1)
Create a new note on a page.
::std::map< sal_Int32, PDFLinkDestination > mFutureDestinations
sal_Int32 CreateControl(const AnyWidget &rControlType)
create a new form control
Definition: pdfwriter.cxx:434
sal_Int32 CreateOutlineItem(sal_Int32 nParent, const OUString &rText, sal_Int32 nDestID)
Create a new outline item.
Definition: pdfwriter.cxx:379
css::lang::Locale maDocLocale
std::unique_ptr< PageSyncData > mpPageSyncData
void PlayGlobalActions(PDFWriter &rWriter)
void SetStructureAttribute(enum StructAttribute eAttr, enum StructAttributeValue eVal)
set a structure attribute on the current structural element
Definition: pdfwriter.cxx:404
sal_Int32 CreateLink(const tools::Rectangle &rRect, sal_Int32 nPageNr)
Create a new link on a page.
Definition: pdfwriter.cxx:330
#define SAL_WARN_IF(condition, area, stream)
OutputDevice & mrOutDev
void SetScreenURL(sal_Int32 nScreenId, const OUString &rURL)
Sets the URL of a linked screen annotation.
Definition: pdfwriter.cxx:364
unsigned char sal_uInt8
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:158
void SetLinkURL(sal_Int32 nLinkId, const OUString &rURL)
Set the URL for a link will change a dest type link to a URL type link if necessary.
Definition: pdfwriter.cxx:359
sal_Int32 CreateNamedDest(const OUString &sDestName, const tools::Rectangle &rRect, sal_Int32 nPageNr=-1)
Create a new named destination to be used in a link to this document from another PDF document (see P...
sal_Int32 CreateLink(const tools::Rectangle &rRect, sal_Int32 nPageNr=-1)
Create a new link on a page.
bool PlaySyncPageAct(PDFWriter &rWriter, sal_uInt32 &rCurGDIMtfAction, const GDIMetaFile &rMtf, const PDFExtOutDevData &rOutDevData)
size_t GetActionSize() const
Definition: gdimtf.cxx:153
void SetDocumentLocale(const css::lang::Locale &rLoc)
MetaActionType GetType() const
Definition: metaact.hxx:89
std::deque< tools::Rectangle > mParaRects
sal_Int32 CreateOutlineItem(sal_Int32 nParent, const OUString &rText, sal_Int32 nDestID)
Create a new outline item.
sal_Int32 CreateDest(const tools::Rectangle &rRect, sal_Int32 nPageNr, DestAreaType eType)
Create a new destination to be used in a link.
Definition: pdfwriter.cxx:349
void SetActualText(const OUString &rText)
set the ActualText attribute of a structural element
void CreateNote(const tools::Rectangle &rRect, const PDFNote &rNote, sal_Int32 nPageNr)
Create a new note on a page.
Definition: pdfwriter.cxx:384
const OutputDevice & mrOutDev
void SetIsExportTransitionEffects(const bool bTransitionalEffects)
sal_Int32 GetMappedStructId(sal_Int32)
const Graphic & GetCurrentGraphic() const
void CreateControl(const PDFWriter::AnyWidget &rControlType)
create a new form control
sal_Int32 CreateScreen(const tools::Rectangle &rRect, sal_Int32 nPageNr)
Creates a screen annotation.
Definition: pdfwriter.cxx:335
void SetScreenStream(sal_Int32 nScreenId, const OUString &rURL)
Set URL for an embedded Screen annotation.
void SetPageTransition(PDFWriter::PageTransition eType, sal_uInt32 nMilliSec)
Sets the transitional effect to be applied when the current page gets shown.
void SetScreenStream(sal_Int32 nScreenId, const OUString &rURL)
Sets the URL of an embedded screen annotation.
Definition: pdfwriter.cxx:369
void SetClipRegion()
Definition: pdfwriter.cxx:250
std::deque< MapMode > mParaMapModes
void SetStructureBoundingBox(const tools::Rectangle &rRect)
set the bounding box of a structural element
void EndStructureElement()
end a logical structure element
std::deque< PDFWriter::PageTransition > mParaPageTransitions
bool GetIsReduceImageResolution() const
void SetCurrentStructureElement(sal_Int32 nElement)
set the current structure element
Definition: pdfwriter.cxx:399
const void * GetData()