LibreOffice Module filter (master) 1
pdfexport.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
21#include <osl/file.hxx>
22#include <tools/debug.hxx>
23#include <tools/urlobj.hxx>
24#include <tools/poly.hxx>
26#include <utility>
27#include <vcl/canvastools.hxx>
28#include <vcl/mapmod.hxx>
29#include <vcl/gdimtf.hxx>
30#include <rtl/ustring.hxx>
33#include <comphelper/string.hxx>
41#include <officecfg/Office/Common.hxx>
42
43#include "pdfexport.hxx"
44#include <strings.hrc>
45
46#include <com/sun/star/beans/XPropertySet.hpp>
47#include <com/sun/star/configuration/theDefaultProvider.hpp>
48#include <com/sun/star/awt/XDevice.hpp>
49#include <com/sun/star/frame/XModel.hpp>
50#include <com/sun/star/frame/ModuleManager.hpp>
51#include <com/sun/star/frame/XStorable.hpp>
52#include <com/sun/star/document/XDocumentProperties.hpp>
53#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
54#include <com/sun/star/container/XNameAccess.hpp>
55#include <com/sun/star/view/XViewSettingsSupplier.hpp>
56#include <com/sun/star/task/XInteractionRequest.hpp>
57#include <com/sun/star/task/PDFExportException.hpp>
58#include <com/sun/star/io/IOException.hpp>
59#include <com/sun/star/io/XOutputStream.hpp>
60#include <com/sun/star/lang/XServiceInfo.hpp>
61#include <com/sun/star/drawing/XShapes.hpp>
62#include <com/sun/star/security/XCertificate.hpp>
63#include <com/sun/star/beans/XMaterialHolder.hpp>
64#include <com/sun/star/xml/crypto/SEInitializer.hpp>
65
66#include <memory>
67
68using namespace ::com::sun::star;
69using namespace ::com::sun::star::io;
70using namespace ::com::sun::star::uno;
71using namespace ::com::sun::star::lang;
72using namespace ::com::sun::star::beans;
73using namespace ::com::sun::star::view;
74using namespace ::com::sun::star::graphic;
75
76
77PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc,
78 const Reference< task::XStatusIndicator >& rxStatusIndicator,
79 const Reference< task::XInteractionHandler >& rxIH,
80 const Reference< XComponentContext >& xContext ) :
81 mxSrcDoc ( rxSrcDoc ),
82 mxContext ( xContext ),
83 mxStatusIndicator ( rxStatusIndicator ),
84 mxIH ( rxIH ),
85 mbUseTaggedPDF ( false ),
86 mnPDFTypeSelection ( 0 ),
87 mbPDFUACompliance ( false),
88 mbExportNotes ( true ),
89 mbExportNotesInMargin ( false ),
90 mbExportPlaceholders ( false ),
91 mbUseReferenceXObject ( false ),
92 mbExportNotesPages ( false ),
93 mbExportOnlyNotesPages ( false ),
94 mbUseTransitionEffects ( true ),
95 mbExportBookmarks ( true ),
96 mbExportHiddenSlides ( false ),
97 mbSinglePageSheets ( false ),
98 mnOpenBookmarkLevels ( -1 ),
99 mbUseLosslessCompression ( false ),
100 mbReduceImageResolution ( true ),
101 mbSkipEmptyPages ( true ),
102 mbAddStream ( false ),
103 mnMaxImageResolution ( 300 ),
104 mnQuality ( 80 ),
105 mnFormsFormat ( 0 ),
106 mbExportFormFields ( true ),
107 mbAllowDuplicateFieldNames ( false ),
108 mnProgressValue ( 0 ),
109 mbRemoveTransparencies ( false ),
110
111 mbIsRedactMode ( false ),
112 maWatermarkColor ( COL_LIGHTGREEN ),
113 maWatermarkFontName ( "Helvetica" ),
114
115 mbHideViewerToolbar ( false ),
116 mbHideViewerMenubar ( false ),
117 mbHideViewerWindowControls ( false ),
118 mbFitWindow ( false ),
119 mbCenterWindow ( false ),
120 mbOpenInFullScreenMode ( false ),
121 mbDisplayPDFDocumentTitle ( true ),
122 mnPDFDocumentMode ( 0 ),
123 mnPDFDocumentAction ( 0 ),
124 mnZoom ( 100 ),
125 mnInitialPage ( 1 ),
126 mnPDFPageLayout ( 0 ),
127
128 mbEncrypt ( false ),
129 mbRestrictPermissions ( false ),
130 mnPrintAllowed ( 2 ),
131 mnChangesAllowed ( 4 ),
132 mbCanCopyOrExtract ( true ),
133 mbCanExtractForAccessibility( true ),
134
135 // #i56629
136 mbExportRelativeFsysLinks ( false ),
137 mnDefaultLinkAction ( 0 ),
138 mbConvertOOoTargetToPDFTarget( false ),
139 mbExportBmkToDest ( false ),
140 mbSignPDF ( false )
141{
142}
143
144
146{
147}
148
149
151 Reference< css::view::XRenderable > const & rRenderable,
152 const Any& rSelection,
153 const StringRangeEnumerator& rRangeEnum,
154 Sequence< PropertyValue >& rRenderOptions,
155 sal_Int32 nPageCount )
156{
157 bool bRet = false;
158 try
159 {
160 Any* pFirstPage = nullptr;
161 Any* pLastPage = nullptr;
162
163 bool bExportNotesPages = false;
164
165 auto rRenderOptionsRange = asNonConstRange(rRenderOptions);
166 for( sal_Int32 nData = 0, nDataCount = rRenderOptions.getLength(); nData < nDataCount; ++nData )
167 {
168 if ( rRenderOptions[ nData ].Name == "IsFirstPage" )
169 pFirstPage = &rRenderOptionsRange[ nData ].Value;
170 else if ( rRenderOptions[ nData ].Name == "IsLastPage" )
171 pLastPage = &rRenderOptionsRange[ nData ].Value;
172 else if ( rRenderOptions[ nData ].Name == "ExportNotesPages" )
173 rRenderOptionsRange[ nData ].Value >>= bExportNotesPages;
174 }
175
176 OutputDevice* pOut = rPDFWriter.GetReferenceDevice();
177
178 if( pOut )
179 {
180 if ( nPageCount )
181 {
182 vcl::PDFExtOutDevData& rPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData&>(*pOut->GetExtOutDevData());
183 rPDFExtOutDevData.SetIsExportNotesPages( bExportNotesPages );
184
185 sal_Int32 nCurrentPage(0);
186 StringRangeEnumerator::Iterator aIter = rRangeEnum.begin();
187 StringRangeEnumerator::Iterator aEnd = rRangeEnum.end();
188 while ( aIter != aEnd )
189 {
190 const Sequence< PropertyValue > aRenderer( rRenderable->getRenderer( *aIter, rSelection, rRenderOptions ) );
191 awt::Size aPageSize;
192
193 for( const PropertyValue& rProp : aRenderer )
194 {
195 if ( rProp.Name == "PageSize" )
196 {
197 rProp.Value >>= aPageSize;
198 break;
199 }
200 }
201
202 rPDFExtOutDevData.SetCurrentPageNumber( nCurrentPage );
203
204 GDIMetaFile aMtf;
205 const MapMode aMapMode( MapUnit::Map100thMM );
206 const Size aMtfSize( aPageSize.Width, aPageSize.Height );
207
208 pOut->Push();
209 pOut->EnableOutput( false );
210 pOut->SetMapMode( aMapMode );
211
212 aMtf.SetPrefSize( aMtfSize );
213 aMtf.SetPrefMapMode( aMapMode );
214 aMtf.Record( pOut );
215
216 // #i35176#
217 // IsLastPage property.
218 const sal_Int32 nCurrentRenderer = *aIter;
219 ++aIter;
220 if ( pLastPage && aIter == aEnd )
221 *pLastPage <<= true;
222
223 rRenderable->render( nCurrentRenderer, rSelection, rRenderOptions );
224
225 aMtf.Stop();
226 aMtf.WindStart();
227
228 bool bEmptyPage = false;
229 if( aMtf.GetActionSize() &&
230 ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) )
231 {
232 // We convert the whole metafile into a bitmap to get rid of the
233 // text covered by redaction shapes
234 if (mbIsRedactMode)
235 {
236 try
237 {
238 Graphic aGraph(aMtf);
239 // use antialiasing to improve how graphic objects look
240 BitmapEx bmp = aGraph.GetBitmapEx(GraphicConversionParameters(Size(0, 0), false, true, false));
241 Graphic bgraph(bmp);
242 aMtf = bgraph.GetGDIMetaFile();
243 }
244 catch(const Exception&)
245 {
246 TOOLS_WARN_EXCEPTION("filter.pdf", "Something went wrong while converting metafile to bitmap");
247 }
248 }
249
250 ImplExportPage(rPDFWriter, rPDFExtOutDevData, aMtf);
251 bRet = true;
252 }
253 else
254 {
255 bEmptyPage = true;
256 }
257
258 pOut->Pop();
259
260 if ( mxStatusIndicator.is() )
262 if ( pFirstPage )
263 *pFirstPage <<= false;
264
266 if (!bEmptyPage)
267 {
268 // Calculate the page number in the PDF output, which may be smaller than the page number in
269 // case of hidden slides or a partial export.
270 ++nCurrentPage;
271 }
272 }
273 }
274 else
275 {
276 bRet = true; // #i18334# nPageCount == 0,
277 rPDFWriter.NewPage( 10000, 10000 ); // creating dummy page
278 rPDFWriter.SetMapMode(MapMode(MapUnit::Map100thMM));
279 }
280 }
281 }
282 catch(const RuntimeException &)
283 {
284 }
285 return bRet;
286}
287
288namespace {
289
290class PDFExportStreamDoc : public vcl::PDFOutputStream
291{
292private:
293
294 Reference< XComponent > m_xSrcDoc;
295 Sequence< beans::NamedValue > m_aPreparedPassword;
296
297public:
298
299 PDFExportStreamDoc( const Reference< XComponent >& xDoc, const Sequence<beans::NamedValue>& rPwd )
300 : m_xSrcDoc( xDoc ),
301 m_aPreparedPassword( rPwd )
302 {}
303
304 virtual void write( const Reference< XOutputStream >& xStream ) override;
305};
306
307}
308
309void PDFExportStreamDoc::write( const Reference< XOutputStream >& xStream )
310{
311 Reference< css::frame::XStorable > xStore( m_xSrcDoc, UNO_QUERY );
312 if( !xStore.is() )
313 return;
314
315 std::vector<beans::PropertyValue> aArgs {
316 comphelper::makePropertyValue("FilterName", OUString()),
317 comphelper::makePropertyValue("OutputStream", xStream),
318 };
319 if (m_aPreparedPassword.hasElements())
320 aArgs.push_back(comphelper::makePropertyValue("EncryptionData", m_aPreparedPassword));
321
322 try
323 {
324 xStore->storeToURL("private:stream", comphelper::containerToSequence(aArgs));
325 }
326 catch( const IOException& )
327 {
328 }
329}
330
331
332static OUString getMimetypeForDocument( const Reference< XComponentContext >& xContext,
333 const Reference< XComponent >& xDoc ) noexcept
334{
335 OUString aDocMimetype;
336 try
337 {
338 // get document service name
339 Reference< css::frame::XStorable > xStore( xDoc, UNO_QUERY );
340 Reference< frame::XModuleManager2 > xModuleManager = frame::ModuleManager::create(xContext);
341 if( xStore.is() )
342 {
343 OUString aDocServiceName = xModuleManager->identify( Reference< XInterface >( xStore, uno::UNO_QUERY ) );
344 if ( !aDocServiceName.isEmpty() )
345 {
346 // get the actual filter name
347 Reference< lang::XMultiServiceFactory > xConfigProvider =
348 configuration::theDefaultProvider::get( xContext );
349 beans::NamedValue aPathProp;
350 aPathProp.Name = "nodepath";
351 aPathProp.Value <<= OUString( "/org.openoffice.Setup/Office/Factories/" );
352 uno::Sequence< uno::Any > aArgs{ uno::Any(aPathProp) };
353
354 Reference< container::XNameAccess > xSOFConfig(
355 xConfigProvider->createInstanceWithArguments(
356 "com.sun.star.configuration.ConfigurationAccess", aArgs ),
357 uno::UNO_QUERY );
358
359 Reference< container::XNameAccess > xApplConfig;
360 xSOFConfig->getByName( aDocServiceName ) >>= xApplConfig;
361 if ( xApplConfig.is() )
362 {
363 OUString aFilterName;
364 xApplConfig->getByName( "ooSetupFactoryActualFilter" ) >>= aFilterName;
365 if( !aFilterName.isEmpty() )
366 {
367 // find the related type name
368 OUString aTypeName;
369 Reference< container::XNameAccess > xFilterFactory(
370 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext),
371 uno::UNO_QUERY );
372
373 Sequence< beans::PropertyValue > aFilterData;
374 xFilterFactory->getByName( aFilterName ) >>= aFilterData;
375 for ( const beans::PropertyValue& rProp : std::as_const(aFilterData) )
376 if ( rProp.Name == "Type" )
377 rProp.Value >>= aTypeName;
378
379 if ( !aTypeName.isEmpty() )
380 {
381 // find the mediatype
382 Reference< container::XNameAccess > xTypeDetection(
383 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext),
384 UNO_QUERY );
385
386 Sequence< beans::PropertyValue > aTypeData;
387 xTypeDetection->getByName( aTypeName ) >>= aTypeData;
388 for ( const beans::PropertyValue& rProp : std::as_const(aTypeData) )
389 if ( rProp.Name == "MediaType" )
390 rProp.Value >>= aDocMimetype;
391 }
392 }
393 }
394 }
395 }
396 }
397 catch (...)
398 {
399 }
400 return aDocMimetype;
401}
402
403uno::Reference<security::XCertificate>
404PDFExport::GetCertificateFromSubjectName(const std::u16string_view& rSubjectName) const
405{
406 uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
407 = xml::crypto::SEInitializer::create(mxContext);
408 uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
409 = xSEInitializer->createSecurityContext(OUString());
410 uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
411 = xSecurityContext->getSecurityEnvironment();
412 for (const auto& xCertificate : xSecurityEnvironment->getPersonalCertificates())
413 {
414 if (xCertificate->getSubjectName() == rSubjectName)
415 {
416 return xCertificate;
417 }
418 }
419
420 return {};
421}
422
423bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData )
424{
425 INetURLObject aURL( rFile );
426 bool bRet = false;
427
428 std::set< vcl::PDFWriter::ErrorCode > aErrors;
429
430 if( aURL.GetProtocol() != INetProtocol::File )
431 {
432 OUString aTmp;
433
434 if( osl::FileBase::getFileURLFromSystemPath( rFile, aTmp ) == osl::FileBase::E_None )
435 aURL = INetURLObject(aTmp);
436 }
437
438 if( aURL.GetProtocol() == INetProtocol::File )
439 {
440 Reference< XRenderable > xRenderable( mxSrcDoc, UNO_QUERY );
441
442 if( xRenderable.is() )
443 {
445 OUString aPageRange;
446 Any aSelection;
448 OUString aOpenPassword, aPermissionPassword;
449 Reference< beans::XMaterialHolder > xEnc;
450 Sequence< beans::NamedValue > aPreparedPermissionPassword;
451
452
453 // getting the string for the creator
454 OUString aCreator;
455 Reference< XServiceInfo > xInfo( mxSrcDoc, UNO_QUERY );
456 if ( xInfo.is() )
457 {
458 if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
459 aCreator += "Impress";
460 else if ( xInfo->supportsService( "com.sun.star.drawing.DrawingDocument" ) )
461 aCreator += "Draw";
462 else if ( xInfo->supportsService( "com.sun.star.text.TextDocument" ) )
463 aCreator += "Writer";
464 else if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
465 aCreator += "Calc";
466 else if ( xInfo->supportsService( "com.sun.star.formula.FormulaProperties" ) )
467 aCreator += "Math";
468 }
469
470 Reference< document::XDocumentPropertiesSupplier > xDocumentPropsSupplier( mxSrcDoc, UNO_QUERY );
471 if ( xDocumentPropsSupplier.is() )
472 {
473 Reference< document::XDocumentProperties > xDocumentProps( xDocumentPropsSupplier->getDocumentProperties() );
474 if ( xDocumentProps.is() )
475 {
476 aContext.DocumentInfo.Title = xDocumentProps->getTitle();
477 aContext.DocumentInfo.Author = xDocumentProps->getAuthor();
478 aContext.DocumentInfo.Subject = xDocumentProps->getSubject();
479 aContext.DocumentInfo.Keywords = ::comphelper::string::convertCommaSeparated(xDocumentProps->getKeywords());
480 }
481 }
482
484 {
485 // getting the string for the producer
486 OUString aProducerOverride = officecfg::Office::Common::Save::Document::GeneratorOverride::get();
487 if (!aProducerOverride.isEmpty())
488 aContext.DocumentInfo.Producer = aProducerOverride;
489 else
490 aContext.DocumentInfo.Producer =
492 " " +
494 }
495
496 aContext.DocumentInfo.Creator = aCreator;
497
498 OUString aSignCertificateSubjectName;
499 for ( const beans::PropertyValue& rProp : rFilterData )
500 {
501 if ( rProp.Name == "PageRange" )
502 rProp.Value >>= aPageRange;
503 else if ( rProp.Name == "Selection" )
504 aSelection = rProp.Value;
505 else if ( rProp.Name == "UseLosslessCompression" )
506 rProp.Value >>= mbUseLosslessCompression;
507 else if ( rProp.Name == "Quality" )
508 rProp.Value >>= mnQuality;
509 else if ( rProp.Name == "ReduceImageResolution" )
510 rProp.Value >>= mbReduceImageResolution;
511 else if ( rProp.Name == "IsSkipEmptyPages" )
512 rProp.Value >>= mbSkipEmptyPages;
513 else if ( rProp.Name == "MaxImageResolution" )
514 rProp.Value >>= mnMaxImageResolution;
515 else if ( rProp.Name == "UseTaggedPDF" )
516 rProp.Value >>= mbUseTaggedPDF;
517 else if ( rProp.Name == "SelectPdfVersion" )
518 rProp.Value >>= mnPDFTypeSelection;
519 else if ( rProp.Name == "PDFUACompliance" )
520 rProp.Value >>= mbPDFUACompliance;
521 else if ( rProp.Name == "ExportNotes" )
522 rProp.Value >>= mbExportNotes;
523 else if ( rProp.Name == "ExportNotesInMargin" )
524 rProp.Value >>= mbExportNotesInMargin;
525 else if ( rProp.Name == "ExportNotesPages" )
526 rProp.Value >>= mbExportNotesPages;
527 else if ( rProp.Name == "ExportOnlyNotesPages" )
528 rProp.Value >>= mbExportOnlyNotesPages;
529 else if ( rProp.Name == "UseTransitionEffects" )
530 rProp.Value >>= mbUseTransitionEffects;
531 else if ( rProp.Name == "ExportFormFields" )
532 rProp.Value >>= mbExportFormFields;
533 else if ( rProp.Name == "FormsType" )
534 rProp.Value >>= mnFormsFormat;
535 else if ( rProp.Name == "AllowDuplicateFieldNames" )
536 rProp.Value >>= mbAllowDuplicateFieldNames;
537 // viewer properties
538 else if ( rProp.Name == "HideViewerToolbar" )
539 rProp.Value >>= mbHideViewerToolbar;
540 else if ( rProp.Name == "HideViewerMenubar" )
541 rProp.Value >>= mbHideViewerMenubar;
542 else if ( rProp.Name == "HideViewerWindowControls" )
543 rProp.Value >>= mbHideViewerWindowControls;
544 else if ( rProp.Name == "ResizeWindowToInitialPage" )
545 rProp.Value >>= mbFitWindow;
546 else if ( rProp.Name == "CenterWindow" )
547 rProp.Value >>= mbCenterWindow;
548 else if ( rProp.Name == "OpenInFullScreenMode" )
549 rProp.Value >>= mbOpenInFullScreenMode;
550 else if ( rProp.Name == "DisplayPDFDocumentTitle" )
551 rProp.Value >>= mbDisplayPDFDocumentTitle;
552 else if ( rProp.Name == "InitialView" )
553 rProp.Value >>= mnPDFDocumentMode;
554 else if ( rProp.Name == "Magnification" )
555 rProp.Value >>= mnPDFDocumentAction;
556 else if ( rProp.Name == "Zoom" )
557 rProp.Value >>= mnZoom;
558 else if ( rProp.Name == "InitialPage" )
559 rProp.Value >>= mnInitialPage;
560 else if ( rProp.Name == "PageLayout" )
561 rProp.Value >>= mnPDFPageLayout;
562 else if ( rProp.Name == "FirstPageOnLeft" )
563 rProp.Value >>= aContext.FirstPageLeft;
564 else if ( rProp.Name == "IsAddStream" )
565 rProp.Value >>= mbAddStream;
566 else if ( rProp.Name == "Watermark" )
567 rProp.Value >>= msWatermark;
568 else if ( rProp.Name == "WatermarkColor" )
569 {
570 sal_Int32 nColor{};
571 if (rProp.Value >>= nColor)
572 {
574 }
575 }
576 else if (rProp.Name == "WatermarkFontHeight")
577 {
578 sal_Int32 nFontHeight{};
579 if (rProp.Value >>= nFontHeight)
580 {
581 moWatermarkFontHeight = nFontHeight;
582 }
583 }
584 else if (rProp.Name == "WatermarkRotateAngle")
585 {
586 sal_Int32 nRotateAngle{};
587 if (rProp.Value >>= nRotateAngle)
588 {
589 moWatermarkRotateAngle = Degree10(nRotateAngle);
590 }
591 }
592 else if (rProp.Name == "WatermarkFontName")
593 {
594 OUString aFontName{};
595 if (rProp.Value >>= aFontName)
596 {
597 maWatermarkFontName = aFontName;
598 }
599 }
600 else if ( rProp.Name == "TiledWatermark" )
601 rProp.Value >>= msTiledWatermark;
602 // now all the security related properties...
603 else if ( rProp.Name == "EncryptFile" )
604 rProp.Value >>= mbEncrypt;
605 else if ( rProp.Name == "DocumentOpenPassword" )
606 rProp.Value >>= aOpenPassword;
607 else if ( rProp.Name == "RestrictPermissions" )
608 rProp.Value >>= mbRestrictPermissions;
609 else if ( rProp.Name == "PermissionPassword" )
610 rProp.Value >>= aPermissionPassword;
611 else if ( rProp.Name == "PreparedPasswords" )
612 rProp.Value >>= xEnc;
613 else if ( rProp.Name == "PreparedPermissionPassword" )
614 rProp.Value >>= aPreparedPermissionPassword;
615 else if ( rProp.Name == "Printing" )
616 rProp.Value >>= mnPrintAllowed;
617 else if ( rProp.Name == "Changes" )
618 rProp.Value >>= mnChangesAllowed;
619 else if ( rProp.Name == "EnableCopyingOfContent" )
620 rProp.Value >>= mbCanCopyOrExtract;
621 else if ( rProp.Name == "EnableTextAccessForAccessibilityTools" )
622 rProp.Value >>= mbCanExtractForAccessibility;
623 // i56629 links extra (relative links and other related stuff)
624 else if ( rProp.Name == "ExportLinksRelativeFsys" )
625 rProp.Value >>= mbExportRelativeFsysLinks;
626 else if ( rProp.Name == "PDFViewSelection" )
627 rProp.Value >>= mnDefaultLinkAction;
628 else if ( rProp.Name == "ConvertOOoTargetToPDFTarget" )
629 rProp.Value >>= mbConvertOOoTargetToPDFTarget;
630 else if ( rProp.Name == "ExportBookmarksToPDFDestination" )
631 rProp.Value >>= mbExportBmkToDest;
632 else if ( rProp.Name == "ExportBookmarks" )
633 rProp.Value >>= mbExportBookmarks;
634 else if ( rProp.Name == "ExportHiddenSlides" )
635 rProp.Value >>= mbExportHiddenSlides;
636 else if ( rProp.Name == "SinglePageSheets" )
637 rProp.Value >>= mbSinglePageSheets;
638 else if ( rProp.Name == "OpenBookmarkLevels" )
639 rProp.Value >>= mnOpenBookmarkLevels;
640 else if ( rProp.Name == "SignPDF" )
641 rProp.Value >>= mbSignPDF;
642 else if ( rProp.Name == "SignatureLocation" )
643 rProp.Value >>= msSignLocation;
644 else if ( rProp.Name == "SignatureReason" )
645 rProp.Value >>= msSignReason;
646 else if ( rProp.Name == "SignatureContactInfo" )
647 rProp.Value >>= msSignContact;
648 else if ( rProp.Name == "SignaturePassword" )
649 rProp.Value >>= msSignPassword;
650 else if ( rProp.Name == "SignatureCertificate" )
651 rProp.Value >>= maSignCertificate;
652 else if (rProp.Name == "SignCertificateSubjectName")
653 rProp.Value >>= aSignCertificateSubjectName;
654 else if ( rProp.Name == "SignatureTSA" )
655 rProp.Value >>= msSignTSA;
656 else if ( rProp.Name == "ExportPlaceholders" )
657 rProp.Value >>= mbExportPlaceholders;
658 else if ( rProp.Name == "UseReferenceXObject" )
659 rProp.Value >>= mbUseReferenceXObject;
660 // Redaction & bitmap related stuff
661 else if ( rProp.Name == "IsRedactMode" )
662 rProp.Value >>= mbIsRedactMode;
663 }
664
665 if (!maSignCertificate.is() && !aSignCertificateSubjectName.isEmpty())
666 {
667 maSignCertificate = GetCertificateFromSubjectName(aSignCertificateSubjectName);
668 }
669
670 aContext.URL = aURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
671
672 // set the correct version, depending on user request
673 switch( mnPDFTypeSelection )
674 {
675 default:
676 case 0:
677 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_7;
678 break;
679 case 1:
680 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_1;
681 mbUseTaggedPDF = true; // force the tagged PDF as well
682 mbRemoveTransparencies = true; // does not allow transparencies
683 mbEncrypt = false; // no encryption
684 xEnc.clear();
685 break;
686 case 2:
687 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_2;
688 mbUseTaggedPDF = true; // force the tagged PDF as well
689 mbRemoveTransparencies = false; // does allow transparencies
690 mbEncrypt = false; // no encryption
691 xEnc.clear();
692 break;
693 case 3:
694 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_3;
695 mbUseTaggedPDF = true; // force the tagged PDF as well
696 mbRemoveTransparencies = false; // does allow transparencies
697 mbEncrypt = false; // no encryption
698 xEnc.clear();
699 break;
700 case 15:
701 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_5;
702 break;
703 case 16:
704 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_6;
705 break;
706 case 17:
707 aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_7;
708 break;
709 }
710
711 // PDF/UA support
714 {
715 // ISO 14289-1:2014, Clause: 7.1
716 mbUseTaggedPDF = true;
717 // ISO 14289-1:2014, Clause: 7.16
719 // ISO 14289-1:2014, Clause: 7.20
720 mbUseReferenceXObject = false;
721 }
722
723 // copy in context the values default in the constructor or set by the FilterData sequence of properties
724 aContext.Tagged = mbUseTaggedPDF;
725
726 // values used in viewer
730 aContext.FitWindow = mbFitWindow;
731 aContext.CenterWindow = mbCenterWindow;
734 aContext.InitialPage = mnInitialPage-1;
736
737 switch( mnPDFDocumentMode )
738 {
739 default:
740 case 0:
742 break;
743 case 1:
745 break;
746 case 2:
748 break;
749 }
750 switch( mnPDFDocumentAction )
751 {
752 default:
753 case 0:
755 break;
756 case 1:
758 break;
759 case 2:
761 break;
762 case 3:
764 break;
765 case 4:
767 aContext.Zoom = mnZoom;
768 break;
769 }
770
771 switch( mnPDFPageLayout )
772 {
773 default:
774 case 0:
776 break;
777 case 1:
779 break;
780 case 2:
782 break;
783 case 3:
785 break;
786 }
787
788 aContext.FirstPageLeft = false;
789
790 // check if PDF/A, which does not allow encryption
791 if( aContext.Version != vcl::PDFWriter::PDFVersion::PDF_A_1 )
792 {
793 // set check for permission change password
794 // if not enabled and no permission password, force permissions to default as if PDF where without encryption
795 if( mbRestrictPermissions && (xEnc.is() || !aPermissionPassword.isEmpty()) )
796 {
797 mbEncrypt = true; // permission set as desired, done after
798 }
799 else
800 {
801 // force permission to default
802 mnPrintAllowed = 2 ;
803 mnChangesAllowed = 4 ;
804 mbCanCopyOrExtract = true;
806 }
807
808 switch( mnPrintAllowed )
809 {
810 case 0: // initialized when aContext is build, means no printing
811 break;
812 default:
813 case 2:
814 aContext.Encryption.CanPrintFull = true;
815 [[fallthrough]];
816 case 1:
817 aContext.Encryption.CanPrintTheDocument = true;
818 break;
819 }
820
821 switch( mnChangesAllowed )
822 {
823 case 0: // already in struct PDFSecPermissions CTOR
824 break;
825 case 1:
826 aContext.Encryption.CanAssemble = true;
827 break;
828 case 2:
829 aContext.Encryption.CanFillInteractive = true;
830 break;
831 case 3:
832 aContext.Encryption.CanAddOrModify = true;
833 break;
834 default:
835 case 4:
838 aContext.Encryption.CanAddOrModify =
839 aContext.Encryption.CanFillInteractive = true;
840 break;
841 }
842
845 if( mbEncrypt && ! xEnc.is() )
846 xEnc = vcl::PDFWriter::InitEncryption( aPermissionPassword, aOpenPassword );
847 if( mbEncrypt && !aPermissionPassword.isEmpty() && ! aPreparedPermissionPassword.hasElements() )
848 aPreparedPermissionPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword );
849 }
850 // after this point we don't need the legacy clear passwords anymore
851 // however they are still inside the passed filter data sequence
852 // which is sadly out of our control
853 aPermissionPassword.clear();
854 aOpenPassword.clear();
855
856 /*
857 * FIXME: the entries are only implicitly defined by the resource file. Should there
858 * ever be an additional form submit format this could get invalid.
859 */
860 switch( mnFormsFormat )
861 {
862 case 1:
864 break;
865 case 2:
867 break;
868 case 3:
870 break;
871 default:
872 case 0:
874 break;
875 }
877
878 // get model
879 Reference< frame::XModel > xModel( mxSrcDoc, UNO_QUERY );
880 {
881 // #i56629: Relative link stuff
882 // set the base URL of the file: then base URL
883 aContext.BaseURL = xModel->getURL();
884 // relative link option is private to PDF Export filter and limited to local filesystem only
886 // determine the default action for PDF links
887 switch( mnDefaultLinkAction )
888 {
889 default:
890 // default: URI, without fragment conversion (the bookmark in PDF may not work)
891 case 0:
893 break;
894 case 1:
895 // view PDF through the reader application
896 aContext.ForcePDFAction = true;
898 break;
899 case 2:
900 // view PDF through an Internet browser
902 break;
903 }
905
906 // check for Link Launch action, not allowed on PDF/A-1
907 // this code chunk checks when the filter is called from scripting
908 if( aContext.Version == vcl::PDFWriter::PDFVersion::PDF_A_1 &&
910 {
911 // force the similar allowed URI action
913 // and remove the remote goto action forced on PDF file
914 aContext.ForcePDFAction = false;
915 }
916 }
917
918 aContext.SignPDF = mbSignPDF;
919 aContext.SignLocation = msSignLocation;
920 aContext.SignContact = msSignContact;
921 aContext.SignReason = msSignReason;
922 aContext.SignPassword = msSignPassword;
924 aContext.SignTSA = msSignTSA;
926
927 // all context data set, time to create the printing device
928 vcl::PDFWriter aPDFWriter( aContext, xEnc );
929 OutputDevice* pOut = aPDFWriter.GetReferenceDevice();
930
931 DBG_ASSERT( pOut, "PDFExport::Export: no reference device" );
932 xDevice->SetOutputDevice(pOut);
933
934 if( mbAddStream )
935 {
936 // export stream
937 // get mimetype
938 OUString aSrcMimetype = getMimetypeForDocument( mxContext, mxSrcDoc );
939 OUString aExt;
940 if (aSrcMimetype == "application/vnd.oasis.opendocument.text")
941 aExt = ".odt";
942 else if (aSrcMimetype == "application/vnd.oasis.opendocument.presentation")
943 aExt = ".odp";
944 else if (aSrcMimetype == "application/vnd.oasis.opendocument.spreadsheet")
945 aExt = ".ods";
946 else if (aSrcMimetype == "application/vnd.oasis.opendocument.graphics")
947 aExt = ".odg";
948 std::unique_ptr<vcl::PDFOutputStream> pStream(new PDFExportStreamDoc(mxSrcDoc, aPreparedPermissionPassword));
949 aPDFWriter.AddAttachedFile("Original" + aExt, aSrcMimetype, u"Embedded original document of this PDF file", std::move(pStream));
950 }
951
952 if ( pOut )
953 {
954 DBG_ASSERT( pOut->GetExtOutDevData() == nullptr, "PDFExport: ExtOutDevData already set!!!" );
955 vcl::PDFExtOutDevData aPDFExtOutDevData( *pOut );
956 pOut->SetExtOutDevData( &aPDFExtOutDevData );
957 aPDFExtOutDevData.SetIsExportNotes( mbExportNotes );
959 aPDFExtOutDevData.SetIsExportTaggedPDF( mbUseTaggedPDF );
961 aPDFExtOutDevData.SetIsExportFormFields( mbExportFormFields );
962 aPDFExtOutDevData.SetIsExportBookmarks( mbExportBookmarks );
964 aPDFExtOutDevData.SetIsSinglePageSheets( mbSinglePageSheets );
966 aPDFExtOutDevData.SetCompressionQuality( mnQuality );
969
970 Sequence< PropertyValue > aRenderOptions{
971 comphelper::makePropertyValue("RenderDevice", uno::Reference<awt::XDevice>(xDevice)),
972 comphelper::makePropertyValue("ExportNotesPages", false),
973 comphelper::makePropertyValue("IsFirstPage", true),
974 comphelper::makePropertyValue("IsLastPage", false),
976 comphelper::makePropertyValue("PageRange", aPageRange),
980 };
981 Any& rExportNotesValue = aRenderOptions.getArray()[ 1 ].Value;
982
983 if( !aPageRange.isEmpty() || !aSelection.hasValue() )
984 {
985 aSelection = Any();
986 aSelection <<= mxSrcDoc;
987 }
988 bool bExportNotesPages = false;
989 bool bReChangeToNormalView = false;
990 static constexpr OUStringLiteral sShowOnlineLayout( u"ShowOnlineLayout" );
991 bool bReHideWhitespace = false;
992 static constexpr OUStringLiteral sHideWhitespace(u"HideWhitespace");
993 uno::Reference< beans::XPropertySet > xViewProperties;
994
995 if ( aCreator == "Writer" )
996 {
997 // #i92835: if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
998 try
999 {
1000 Reference< view::XViewSettingsSupplier > xVSettingsSupplier( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
1001 xViewProperties = xVSettingsSupplier->getViewSettings();
1002 xViewProperties->getPropertyValue( sShowOnlineLayout ) >>= bReChangeToNormalView;
1003 if( bReChangeToNormalView )
1004 {
1005 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( false ) );
1006 }
1007
1008 // Also, disable hide-whitespace during export.
1009 xViewProperties->getPropertyValue(sHideWhitespace) >>= bReHideWhitespace;
1010 if (bReHideWhitespace)
1011 {
1012 xViewProperties->setPropertyValue(sHideWhitespace, uno::Any(false));
1013 }
1014 }
1015 catch( const uno::Exception& )
1016 {
1017 }
1018
1019 }
1020
1021 const sal_Int32 nPageCount = xRenderable->getRendererCount( aSelection, aRenderOptions );
1022
1023 if ( mbExportNotesPages && aCreator == "Impress" )
1024 {
1025 uno::Reference< drawing::XShapes > xShapes; // do not allow to export notes when exporting a selection
1026 if ( ! ( aSelection >>= xShapes ) )
1027 bExportNotesPages = true;
1028 }
1029 const bool bExportPages = !bExportNotesPages || !mbExportOnlyNotesPages;
1030
1031 if( aPageRange.isEmpty() || mbSinglePageSheets)
1032 {
1033 aPageRange = OUString::number( 1 ) + "-" + OUString::number(nPageCount );
1034 }
1035 StringRangeEnumerator aRangeEnum( aPageRange, 0, nPageCount-1 );
1036
1037 if ( mxStatusIndicator.is() )
1038 {
1039 sal_Int32 nTotalPageCount = aRangeEnum.size();
1040 if ( bExportPages && bExportNotesPages )
1041 nTotalPageCount *= 2;
1042 mxStatusIndicator->start(FilterResId(PDF_PROGRESS_BAR), nTotalPageCount);
1043 }
1044
1045 bRet = nPageCount > 0;
1046
1047 if ( bRet && bExportPages )
1048 bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
1049
1050 if ( bRet && bExportNotesPages )
1051 {
1052 rExportNotesValue <<= true;
1053 bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
1054 }
1055 if ( mxStatusIndicator.is() )
1056 mxStatusIndicator->end();
1057
1058 // if during the export the doc locale was set copy it to PDF writer
1059 const css::lang::Locale& rLoc( aPDFExtOutDevData.GetDocumentLocale() );
1060 if( !rLoc.Language.isEmpty() )
1061 aPDFWriter.SetDocumentLocale( rLoc );
1062
1063 if( bRet )
1064 {
1065 aPDFExtOutDevData.PlayGlobalActions( aPDFWriter );
1066 bRet = aPDFWriter.Emit();
1067 aErrors = aPDFWriter.GetErrors();
1068 }
1069 pOut->SetExtOutDevData( nullptr );
1070 if( bReChangeToNormalView )
1071 {
1072 try
1073 {
1074 xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( true ) );
1075 }
1076 catch( const uno::Exception& )
1077 {
1078 }
1079 }
1080 if( bReHideWhitespace )
1081 {
1082 try
1083 {
1084 xViewProperties->setPropertyValue( sHideWhitespace, uno::Any( true ) );
1085 }
1086 catch( const uno::Exception& )
1087 {
1088 }
1089 }
1090 }
1091 }
1092 }
1093
1094 // show eventual errors during export
1095 showErrors( aErrors );
1096
1097 return bRet;
1098}
1099
1100
1101namespace
1102{
1103
1105
1106class PDFErrorRequest : public PDFErrorRequestBase
1107{
1108 task::PDFExportException maExc;
1109public:
1110 explicit PDFErrorRequest( task::PDFExportException aExc );
1111
1112 // XInteractionRequest
1113 virtual uno::Any SAL_CALL getRequest() override;
1114 virtual uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL getContinuations() override;
1115};
1116
1117
1118PDFErrorRequest::PDFErrorRequest( task::PDFExportException aExc ) :
1119 maExc(std::move( aExc ))
1120{
1121}
1122
1123
1124uno::Any SAL_CALL PDFErrorRequest::getRequest()
1125{
1126 std::unique_lock guard( m_aMutex );
1127
1128 uno::Any aRet;
1129 aRet <<= maExc;
1130 return aRet;
1131}
1132
1133
1134uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL PDFErrorRequest::getContinuations()
1135{
1136 return uno::Sequence< uno::Reference< task::XInteractionContinuation > >();
1137}
1138
1139} // end anonymous namespace
1140
1141
1142void PDFExport::showErrors( const std::set< vcl::PDFWriter::ErrorCode >& rErrors )
1143{
1144 if( ! rErrors.empty() && mxIH.is() )
1145 {
1146 task::PDFExportException aExc;
1147 aExc.ErrorCodes = comphelper::containerToSequence<sal_Int32>( rErrors );
1148 Reference< task::XInteractionRequest > xReq( new PDFErrorRequest( std::move(aExc) ) );
1149 mxIH->handle( xReq );
1150 }
1151}
1152
1153
1154void PDFExport::ImplExportPage( vcl::PDFWriter& rWriter, vcl::PDFExtOutDevData& rPDFExtOutDevData, const GDIMetaFile& rMtf )
1155{
1156 //Rectangle(Point, Size) creates a rectangle off by 1, use Rectangle(long, long, long, long) instead
1158 basegfx::B2DPolygon aSizePDF(OutputDevice::LogicToLogic(aSize, rMtf.GetPrefMapMode(), MapMode(MapUnit::MapPoint)));
1159 basegfx::B2DRange aRangePDF(aSizePDF.getB2DRange());
1160 tools::Rectangle aPageRect( Point(), rMtf.GetPrefSize() );
1161
1162 rWriter.NewPage( aRangePDF.getWidth(), aRangePDF.getHeight() );
1163 rWriter.SetMapMode( rMtf.GetPrefMapMode() );
1164
1166 GDIMetaFile aMtf;
1168 {
1170 RemoveTransparenciesFromMetaFile( rMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
1171 false, true, mbReduceImageResolution );
1172 // tdf#134736 if the metafile was replaced then rPDFExtOutDevData's PageSyncData mActions
1173 // all still point to MetaAction indexes in the original metafile that are now invalid.
1174 // Throw them all away in the absence of a way to reposition them to new positions of
1175 // their replacements.
1177 rPDFExtOutDevData.ResetSyncData();
1178 }
1179 else
1180 {
1181 aMtf = rMtf;
1182 }
1186
1187
1190
1191 rWriter.PlayMetafile( aMtf, aCtx, &rPDFExtOutDevData );
1192
1193 rPDFExtOutDevData.ResetSyncData();
1194
1195 if (!msWatermark.isEmpty())
1196 {
1197 ImplWriteWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
1198 }
1199 else if (!msTiledWatermark.isEmpty())
1200 {
1201 ImplWriteTiledWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
1202 }
1203}
1204
1205
1206void PDFExport::ImplWriteWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize )
1207{
1209 aFont.SetItalic( ITALIC_NONE );
1210 aFont.SetWidthType( WIDTH_NORMAL );
1211 aFont.SetWeight( WEIGHT_NORMAL );
1212 aFont.SetAlignment( ALIGN_BOTTOM );
1213 tools::Long nTextWidth = rPageSize.Width();
1214 if( rPageSize.Width() < rPageSize.Height() )
1215 {
1216 nTextWidth = rPageSize.Height();
1217 aFont.SetOrientation( 2700_deg10 );
1218 }
1219
1221 {
1223 if (rPageSize.Width() < rPageSize.Height())
1224 {
1225 // Set text width based on the shorter side, so rotation can't push text outside the
1226 // page boundaries.
1227 nTextWidth = rPageSize.Width();
1228 }
1229 }
1230
1231 // adjust font height for text to fit
1232 OutputDevice* pDev = rWriter.GetReferenceDevice();
1233 pDev->Push();
1234 pDev->SetFont( aFont );
1235 pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
1236 int w = 0;
1238 {
1239 w = pDev->GetTextWidth(msWatermark);
1240 }
1241 else
1242 {
1243 while( ( w = pDev->GetTextWidth( msWatermark ) ) > nTextWidth )
1244 {
1245 if (w == 0)
1246 break;
1247 tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
1248 if( nNewHeight == aFont.GetFontHeight() )
1249 {
1250 nNewHeight--;
1251 if( nNewHeight <= 0 )
1252 break;
1253 }
1254 aFont.SetFontHeight( nNewHeight );
1255 pDev->SetFont( aFont );
1256 }
1257 }
1258 tools::Long nTextHeight = pDev->GetTextHeight();
1259 // leave some maneuvering room for rounding issues, also
1260 // some fonts go a little outside ascent/descent
1261 nTextHeight += nTextHeight/20;
1262 pDev->Pop();
1263
1264 rWriter.Push();
1265 // tdf#152235 tag around the reference to the XObject on the page
1266 sal_Int32 const id = rWriter.EnsureStructureElement();
1267 rWriter.InitStructureElement(id, vcl::PDFWriter::NonStructElement, ::std::u16string_view());
1268 rWriter.BeginStructureElement(id);
1271 // HACK: this should produce *nothing* itself but is necessary to output
1272 // the Artifact tag here, not inside the XObject
1273 rWriter.DrawPolyLine({});
1274 rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
1275 rWriter.SetFont( aFont );
1277 Point aTextPoint;
1278 tools::Rectangle aTextRect;
1279 if( rPageSize.Width() > rPageSize.Height() )
1280 {
1281 aTextPoint = Point( (rPageSize.Width()-w)/2,
1282 rPageSize.Height()-(rPageSize.Height()-nTextHeight)/2 );
1283 aTextRect = tools::Rectangle( Point( (rPageSize.Width()-w)/2,
1284 (rPageSize.Height()-nTextHeight)/2 ),
1285 Size( w, nTextHeight ) );
1286 }
1287 else
1288 {
1289 aTextPoint = Point( (rPageSize.Width()-nTextHeight)/2,
1290 (rPageSize.Height()-w)/2 );
1291 aTextRect = tools::Rectangle( aTextPoint, Size( nTextHeight, w ) );
1292 }
1293
1295 {
1296 // First set the text's starting point to the center of the page.
1297 tools::Rectangle aPageRectangle(Point(0, 0), rPageSize);
1298 aTextPoint = aPageRectangle.Center();
1299 // Then adjust it so that the text remains centered, based on the rotation angle.
1300 basegfx::B2DPolygon aTextPolygon
1302 basegfx::B2DHomMatrix aMatrix;
1303 aMatrix.rotate(-1 * toRadians(*moWatermarkRotateAngle));
1304 aTextPolygon.transform(aMatrix);
1305 basegfx::B2DPoint aPolygonCenter = aTextPolygon.getB2DRange().getCenter();
1306 aTextPoint.AdjustX(-aPolygonCenter.getX());
1307 aTextPoint.AdjustY(-aPolygonCenter.getY());
1308
1309 aTextRect = aPageRectangle;
1310 }
1311
1312 rWriter.SetClipRegion();
1313 rWriter.BeginTransparencyGroup();
1314 rWriter.DrawText( aTextPoint, msWatermark );
1315 rWriter.EndTransparencyGroup( aTextRect, 50 );
1316 rWriter.EndStructureElement();
1317 rWriter.Pop();
1318}
1319
1321{
1322 OUString watermark = msTiledWatermark;
1323 // Maximum number of characters in one line.
1324 // it is set to 21 to make it look like tiled watermarks as online in secure view
1325 const int lineLength = 21;
1326 vcl::Font aFont( "Liberation Sans", Size( 0, 40 ) );
1327 aFont.SetItalic( ITALIC_NONE );
1328 aFont.SetWidthType( WIDTH_NORMAL );
1329 aFont.SetWeight( WEIGHT_NORMAL );
1330 aFont.SetAlignment( ALIGN_BOTTOM );
1331 aFont.SetFontHeight(40);
1332 aFont.SetOrientation(450_deg10);
1333
1334 OutputDevice* pDev = rWriter.GetReferenceDevice();
1335 pDev->SetFont(aFont);
1336 pDev->Push();
1337 pDev->SetFont(aFont);
1338 pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
1339 int w = 0;
1340 int watermarkcount = ((rPageSize.Width()) / 200)+1;
1341 tools::Long nTextWidth = rPageSize.Width() / (watermarkcount*1.5);
1342 OUString oneLineText = watermark;
1343
1344 if(watermark.getLength() > lineLength)
1345 oneLineText = watermark.copy(0, lineLength);
1346
1347 while((w = pDev->GetTextWidth(oneLineText)) > nTextWidth)
1348 {
1349 if(w==0)
1350 break;
1351
1352 tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
1353 aFont.SetFontHeight(nNewHeight);
1354 pDev->SetFont( aFont );
1355 }
1356 // maximum number of watermark count for the width
1357 if(watermarkcount > 8)
1358 watermarkcount = 8;
1359
1360 pDev->Pop();
1361
1362 rWriter.Push();
1363 // tdf#152235 tag around the reference to the XObject on the page
1364 sal_Int32 const id = rWriter.EnsureStructureElement();
1365 rWriter.InitStructureElement(id, vcl::PDFWriter::NonStructElement, ::std::u16string_view());
1366 rWriter.BeginStructureElement(id);
1369 // HACK: this should produce *nothing* itself but is necessary to output
1370 // the Artifact tag here, not inside the XObject
1371 rWriter.DrawPolyLine({});
1372 rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
1373 rWriter.SetFont(aFont);
1374 rWriter.SetTextColor( Color(19,20,22) );
1375 // center watermarks horizontally
1376 Point aTextPoint( (rPageSize.Width()/2) - (((nTextWidth*watermarkcount)+(watermarkcount-1)*nTextWidth)/2),
1377 pDev->GetTextHeight());
1378
1379 for( int i = 0; i < watermarkcount; i ++)
1380 {
1381 while(aTextPoint.getY()+pDev->GetTextHeight()*3 <= rPageSize.Height())
1382 {
1383 tools::Rectangle aTextRect(aTextPoint, Size(nTextWidth*2,pDev->GetTextHeight()*4));
1384
1385 pDev->Push();
1386 rWriter.SetClipRegion();
1387 rWriter.BeginTransparencyGroup();
1388 rWriter.SetTextColor( Color(19,20,22) );
1389 rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
1390 rWriter.EndTransparencyGroup( aTextRect, 50 );
1391 pDev->Pop();
1392
1393 pDev->Push();
1394 rWriter.SetClipRegion();
1395 rWriter.BeginTransparencyGroup();
1396 rWriter.SetTextColor( Color(236,235,233) );
1397 rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
1398 rWriter.EndTransparencyGroup( aTextRect, 50 );
1399 pDev->Pop();
1400
1401 aTextPoint.Move(0, pDev->GetTextHeight()*3);
1402 }
1403 aTextPoint=Point( aTextPoint.getX(), pDev->GetTextHeight() );
1404 aTextPoint.Move( nTextWidth*1.5, 0 );
1405 }
1406
1407 rWriter.EndStructureElement();
1408 rWriter.Pop();
1409}
1410
1411/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator
size_t GetActionSize() const
void WindStart()
const Size & GetPrefSize() const
void SetPrefMapMode(const MapMode &rMapMode)
void Record(OutputDevice *pOutDev)
const MapMode & GetPrefMapMode() const
void SetPrefSize(const Size &rSize)
const GDIMetaFile & GetGDIMetaFile() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
void SetFont(const vcl::Font &rNewFont)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void SetMapMode()
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
tools::Long GetTextHeight() const
OUString msSignPassword
Definition: pdfexport.hxx:117
Color maWatermarkColor
Definition: pdfexport.hxx:77
bool mbRemoveTransparencies
Definition: pdfexport.hxx:72
void ImplExportPage(vcl::PDFWriter &rWriter, vcl::PDFExtOutDevData &rPDFExtOutDevData, const GDIMetaFile &rMtf)
Definition: pdfexport.cxx:1154
sal_Int32 mnFormsFormat
Definition: pdfexport.hxx:68
sal_Int32 mnPDFDocumentAction
Definition: pdfexport.hxx:93
css::uno::Reference< css::security::XCertificate > GetCertificateFromSubjectName(const std::u16string_view &rSubjectName) const
Definition: pdfexport.cxx:404
bool mbExportNotesPages
Definition: pdfexport.hxx:54
bool mbExportNotesInMargin
Definition: pdfexport.hxx:51
bool mbExportPlaceholders
Definition: pdfexport.hxx:52
sal_Int32 mnZoom
Definition: pdfexport.hxx:94
bool mbDisplayPDFDocumentTitle
Definition: pdfexport.hxx:91
css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator
Definition: pdfexport.hxx:44
bool mbUseLosslessCompression
Definition: pdfexport.hxx:62
bool mbFitWindow
Definition: pdfexport.hxx:88
sal_Int32 mnMaxImageResolution
Definition: pdfexport.hxx:66
OUString msSignLocation
Definition: pdfexport.hxx:114
OUString msSignReason
Definition: pdfexport.hxx:116
void showErrors(const std::set< vcl::PDFWriter::ErrorCode > &)
Definition: pdfexport.cxx:1142
css::uno::Reference< css::security::XCertificate > maSignCertificate
Definition: pdfexport.hxx:118
bool mbUseTransitionEffects
Definition: pdfexport.hxx:56
css::uno::Reference< css::lang::XComponent > mxSrcDoc
Definition: pdfexport.hxx:42
bool mbSkipEmptyPages
Definition: pdfexport.hxx:64
void ImplWriteTiledWatermark(vcl::PDFWriter &rWriter, const Size &rPageSize)
Definition: pdfexport.cxx:1320
sal_Int32 mnInitialPage
Definition: pdfexport.hxx:95
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: pdfexport.hxx:43
void ImplWriteWatermark(vcl::PDFWriter &rWriter, const Size &rPageSize)
Definition: pdfexport.cxx:1206
bool mbExportBookmarks
Definition: pdfexport.hxx:57
std::optional< Degree10 > moWatermarkRotateAngle
Definition: pdfexport.hxx:80
bool mbOpenInFullScreenMode
Definition: pdfexport.hxx:90
bool mbEncrypt
Definition: pdfexport.hxx:98
bool mbRestrictPermissions
Definition: pdfexport.hxx:99
sal_Int32 mnQuality
Definition: pdfexport.hxx:67
bool mbSinglePageSheets
Definition: pdfexport.hxx:59
sal_Int32 mnChangesAllowed
Definition: pdfexport.hxx:101
bool mbAddStream
Definition: pdfexport.hxx:65
bool mbHideViewerToolbar
Definition: pdfexport.hxx:85
css::uno::Reference< css::task::XInteractionHandler > mxIH
Definition: pdfexport.hxx:45
bool mbCanCopyOrExtract
Definition: pdfexport.hxx:102
bool Export(const OUString &rFile, const css::uno::Sequence< css::beans::PropertyValue > &rFilterData)
Definition: pdfexport.cxx:423
sal_Int32 mnOpenBookmarkLevels
Definition: pdfexport.hxx:60
bool mbHideViewerWindowControls
Definition: pdfexport.hxx:87
PDFExport(const css::uno::Reference< css::lang::XComponent > &rxSrcDoc, const css::uno::Reference< css::task::XStatusIndicator > &xStatusIndicator, const css::uno::Reference< css::task::XInteractionHandler > &xIH, const css::uno::Reference< css::uno::XComponentContext > &xFact)
Definition: pdfexport.cxx:77
OUString msWatermark
Definition: pdfexport.hxx:76
bool mbExportOnlyNotesPages
Definition: pdfexport.hxx:55
bool mbAllowDuplicateFieldNames
Definition: pdfexport.hxx:70
bool mbSignPDF
Definition: pdfexport.hxx:113
sal_Int32 mnPDFPageLayout
Definition: pdfexport.hxx:96
OUString msTiledWatermark
Definition: pdfexport.hxx:81
OUString msSignContact
Definition: pdfexport.hxx:115
bool mbExportNotes
Definition: pdfexport.hxx:50
std::optional< sal_Int32 > moWatermarkFontHeight
Definition: pdfexport.hxx:78
bool mbExportFormFields
Definition: pdfexport.hxx:69
sal_Int32 mnPDFTypeSelection
Definition: pdfexport.hxx:48
bool mbUseReferenceXObject
Definition: pdfexport.hxx:53
sal_Int32 mnPrintAllowed
Definition: pdfexport.hxx:100
bool mbPDFUACompliance
Definition: pdfexport.hxx:49
bool mbExportBmkToDest
Definition: pdfexport.hxx:109
bool mbCanExtractForAccessibility
Definition: pdfexport.hxx:103
bool ExportSelection(vcl::PDFWriter &rPDFWriter, css::uno::Reference< css::view::XRenderable > const &rRenderable, const css::uno::Any &rSelection, const StringRangeEnumerator &rRangeEnum, css::uno::Sequence< css::beans::PropertyValue > &rRenderOptions, sal_Int32 nPageCount)
Definition: pdfexport.cxx:150
bool mbExportHiddenSlides
Definition: pdfexport.hxx:58
sal_Int32 mnProgressValue
Definition: pdfexport.hxx:71
bool mbExportRelativeFsysLinks
Definition: pdfexport.hxx:106
bool mbConvertOOoTargetToPDFTarget
Definition: pdfexport.hxx:108
sal_Int32 mnDefaultLinkAction
Definition: pdfexport.hxx:107
bool mbUseTaggedPDF
Definition: pdfexport.hxx:47
sal_Int32 mnPDFDocumentMode
Definition: pdfexport.hxx:92
bool mbReduceImageResolution
Definition: pdfexport.hxx:63
OUString msSignTSA
Definition: pdfexport.hxx:119
bool mbCenterWindow
Definition: pdfexport.hxx:89
OUString maWatermarkFontName
Definition: pdfexport.hxx:79
bool mbIsRedactMode
Definition: pdfexport.hxx:74
bool mbHideViewerMenubar
Definition: pdfexport.hxx:86
void Move(tools::Long nHorzMove, tools::Long nVertMove)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long getX() const
constexpr tools::Long getY() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
sal_Int32 size() const
Iterator end(const o3tl::sorted_vector< sal_Int32 > *i_pPossibleValues=nullptr) const
Iterator begin(const o3tl::sorted_vector< sal_Int32 > *i_pPossibleValues=nullptr) const
void rotate(double fRadiant)
void transform(const basegfx::B2DHomMatrix &rMatrix)
B2DRange const & getB2DRange() const
B2DPoint getCenter() const
TYPE getWidth() const
TYPE getHeight() const
TYPE getX() const
TYPE getY() const
static css::uno::Sequence< css::beans::NamedValue > CreatePackageEncryptionData(std::u16string_view aPassword)
::basegfx::B2DPolygon getB2DPolygon() const
constexpr Point Center() const
static OUString getProductVersion()
static OUString getProductName()
static bool IsFuzzing()
tools::Long GetFontHeight() const
void SetOrientation(Degree10 nLineOrientation)
void SetWidthType(FontWidth)
void SetItalic(FontItalic)
void SetWeight(FontWeight)
void SetFontHeight(tools::Long nHeight)
void SetAlignment(TextAlign)
void SetIsExportNamedDestinations(const bool bExportNDests)
void SetIsExportNotes(const bool bExportNotes)
void SetIsExportTaggedPDF(const bool bTaggedPDF)
void SetIsExportNotesPages(const bool bExportNotesPages)
void PlayGlobalActions(PDFWriter &rWriter)
void SetIsLosslessCompression(const bool bLosslessCompression)
void SetIsReduceImageResolution(const bool bReduceImageResolution)
void SetCurrentPageNumber(const sal_Int32 nPage)
void SetIsExportBookmarks(const bool bExportBookmarks)
void SetIsExportHiddenSlides(const bool bExportHiddenSlides)
void SetIsSinglePageSheets(const bool bSinglePageSheets)
void SetIsExportTransitionEffects(const bool bTransitionalEffects)
void SetIsExportFormFields(const bool bExportFormFields)
const css::lang::Locale & GetDocumentLocale() const
void SetCompressionQuality(const sal_Int32 nQuality)
void SetIsExportNotesInMargin(const bool bExportNotesInMargin)
virtual void write(const css::uno::Reference< css::io::XOutputStream > &xStream)=0
void SetFont(const vcl::Font &rNewFont)
void SetTextColor(const Color &rColor)
void InitStructureElement(sal_Int32 id, PDFWriter::StructElement eType, std::u16string_view rAlias)
static css::uno::Reference< css::beans::XMaterialHolder > InitEncryption(const OUString &i_rOwnerPassword, const OUString &i_rUserPassword)
void Push(PushFlags nFlags=PushFlags::ALL)
void DrawPolyLine(const tools::Polygon &rPoly)
void NewPage(double nPageWidth, double nPageHeight, Orientation eOrientation=Orientation::Inherit)
void BeginTransparencyGroup()
void PlayMetafile(const GDIMetaFile &, const PlayMetafileContext &, vcl::PDFExtOutDevData *pDevDat=nullptr)
void SetClipRegion()
void DrawText(const Point &rPos, const OUString &rText)
std::set< ErrorCode > const & GetErrors() const
void AddAttachedFile(OUString const &rFileName, OUString const &rMimeType, OUString const &rDescription, std::unique_ptr< PDFOutputStream > pStream)
void SetDocumentLocale(const css::lang::Locale &rDocLocale)
OutputDevice * GetReferenceDevice()
void SetMapMode(const MapMode &rNewMapMode)
void EndTransparencyGroup(const tools::Rectangle &rBoundRect, sal_uInt16 nTransparencePercent)
void BeginStructureElement(sal_Int32 id)
void EndStructureElement()
void SetStructureAttribute(enum StructAttribute eAttr, enum StructAttributeValue eVal)
sal_Int32 EnsureStructureElement()
ColorTransparency
constexpr ::Color COL_LIGHTGREEN(0x00, 0xFF, 0x00)
#define DBG_ASSERT(sCon, aError)
double toRadians(D x)
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
uno::Reference< uno::XComponentContext > mxContext
float u
ITALIC_NONE
WIDTH_NORMAL
ALIGN_BOTTOM
WEIGHT_NORMAL
void getContinuations(css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > const &rContinuations, css::uno::Reference< t1 > *pContinuation1, css::uno::Reference< t2 > *pContinuation2)
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
@ Exception
Shape IDs per cluster in DGG atom.
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
int i
Definition: gentoken.py:48
long Long
basegfx::B2DRange b2DRectangleFromRectangle(const ::tools::Rectangle &rRect)
sal_Int32 w
static OUString getMimetypeForDocument(const Reference< XComponentContext > &xContext, const Reference< XComponent > &xDoc) noexcept
Definition: pdfexport.cxx:332
PDFWriter::PDFLinkDefaultAction DefaultLinkAction
PDFWriter::ExportDataFormat SubmitFormat
css::uno::Reference< css::security::XCertificate > SignCertificate
PDFWriter::PDFViewerPageMode PDFDocumentMode
PDFWriter::PDFViewerAction PDFDocumentAction
PDFWriter::PDFEncryptionProperties Encryption
PDFWriter::PDFDocInfo DocumentInfo
Reference< XModel > xModel
OUString Name
oslFileHandle & pOut