LibreOffice Module vcl (master) 1
pdfwriter_impl2.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
21
23#include <vcl/virdev.hxx>
24#include <vcl/gdimtf.hxx>
25#include <vcl/metaact.hxx>
27#include <vcl/graph.hxx>
28
30
31#include <tools/helpers.hxx>
32#include <tools/fract.hxx>
33#include <tools/stream.hxx>
34
36#include <comphelper/hash.hxx>
39
40#include <com/sun/star/beans/PropertyValue.hpp>
41#include <com/sun/star/io/XSeekable.hpp>
42#include <com/sun/star/graphic/GraphicProvider.hpp>
43#include <com/sun/star/graphic/XGraphicProvider.hpp>
44#include <com/sun/star/beans/XMaterialHolder.hpp>
45
49
50#include <sal/log.hxx>
51#include <memory>
52
53using namespace vcl;
54using namespace com::sun::star;
55using namespace com::sun::star::uno;
56using namespace com::sun::star::beans;
57
58static bool lcl_canUsePDFAxialShading(const Gradient& rGradient);
59
60void PDFWriterImpl::implWriteGradient( const tools::PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient,
61 VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
62{
63 GDIMetaFile aTmpMtf;
64 Gradient aGradient(i_rGradient);
65
66 aGradient.AddGradientActions( i_rPolyPoly.GetBoundRect(), aTmpMtf );
67
70 playMetafile( aTmpMtf, nullptr, i_rContext, i_pDummyVDev );
72}
73
74void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSize, const BitmapEx& i_rBitmapEx, const Graphic& i_Graphic,
75 VirtualDevice const * i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
76{
77 if ( i_rBitmapEx.IsEmpty() || !i_rSize.Width() || !i_rSize.Height() )
78 return;
79
80 BitmapEx aBitmapEx( i_rBitmapEx );
81 Point aPoint( i_rPoint );
82 Size aSize( i_rSize );
83
84 // #i19065# Negative sizes have mirror semantics on
85 // OutputDevice. BitmapEx and co. have no idea about that, so
86 // perform that _before_ doing anything with aBitmapEx.
88 if( aSize.Width() < 0 )
89 {
90 aSize.setWidth( aSize.Width() * -1 );
91 aPoint.AdjustX( -(aSize.Width()) );
92 nMirrorFlags |= BmpMirrorFlags::Horizontal;
93 }
94 if( aSize.Height() < 0 )
95 {
96 aSize.setHeight( aSize.Height() * -1 );
97 aPoint.AdjustY( -(aSize.Height()) );
98 nMirrorFlags |= BmpMirrorFlags::Vertical;
99 }
100
101 if( nMirrorFlags != BmpMirrorFlags::NONE )
102 {
103 aBitmapEx.Mirror( nMirrorFlags );
104 }
105
106 bool bIsJpeg = false, bIsPng = false;
107 if( i_Graphic.GetType() != GraphicType::NONE && i_Graphic.GetBitmapEx() == aBitmapEx )
108 {
109 GfxLinkType eType = i_Graphic.GetGfxLink().GetType();
110 bIsJpeg = (eType == GfxLinkType::NativeJpg);
111 bIsPng = (eType == GfxLinkType::NativePng);
112 }
113
114 // Do not downsample images smaller than 50x50px.
115 const Size aBmpSize(aBitmapEx.GetSizePixel());
116 if (i_rContext.m_nMaxImageResolution > 50 && aBmpSize.getWidth() > 50
117 && aBmpSize.getHeight() > 50)
118 {
119 // do downsampling if necessary
120 const Size aDstSizeTwip( i_pDummyVDev->PixelToLogic(i_pDummyVDev->LogicToPixel(aSize), MapMode(MapUnit::MapTwip)) );
121 const double fBmpPixelX = aBmpSize.Width();
122 const double fBmpPixelY = aBmpSize.Height();
123 const double fMaxPixelX
124 = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in)
125 * i_rContext.m_nMaxImageResolution;
126 const double fMaxPixelY
127 = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in)
128 * i_rContext.m_nMaxImageResolution;
129
130 // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
131 if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
132 ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
133 ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
134 {
135 // do scaling
136 Size aNewBmpSize;
137 const double fBmpWH = fBmpPixelX / fBmpPixelY;
138 const double fMaxWH = fMaxPixelX / fMaxPixelY;
139
140 if( fBmpWH < fMaxWH )
141 {
142 aNewBmpSize.setWidth( FRound( fMaxPixelY * fBmpWH ) );
143 aNewBmpSize.setHeight( FRound( fMaxPixelY ) );
144 }
145 else if( fBmpWH > 0.0 )
146 {
147 aNewBmpSize.setWidth( FRound( fMaxPixelX ) );
148 aNewBmpSize.setHeight( FRound( fMaxPixelX / fBmpWH) );
149 }
150
151 if( aNewBmpSize.Width() && aNewBmpSize.Height() )
152 {
153 // #i121233# Use best quality for PDF exports
154 aBitmapEx.Scale( aNewBmpSize, BmpScaleFlag::BestQuality );
155 }
156 else
157 {
158 aBitmapEx.SetEmpty();
159 }
160 }
161 }
162
163 const Size aSizePixel( aBitmapEx.GetSizePixel() );
164 if ( !(aSizePixel.Width() && aSizePixel.Height()) )
165 return;
166
169 bool bUseJPGCompression = !i_rContext.m_bOnlyLosslessCompression;
170 if ( bIsPng || ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
171 bUseJPGCompression = false;
172
173 auto pStrm=std::make_shared<SvMemoryStream>();
174 AlphaMask aAlphaMask;
175
176 bool bTrueColorJPG = true;
177 if ( bUseJPGCompression )
178 {
179 // TODO this checks could be done much earlier, saving us
180 // from trying conversion & stores before...
181 if ( !aBitmapEx.IsAlpha() )
182 {
183 const auto& rCacheEntry=m_aPDFBmpCache.find(
184 aBitmapEx.GetChecksum());
185 if ( rCacheEntry != m_aPDFBmpCache.end() )
186 {
187 m_rOuterFace.DrawJPGBitmap( *rCacheEntry->second, true, aSizePixel,
188 tools::Rectangle( aPoint, aSize ), aAlphaMask, i_Graphic );
189 return;
190 }
191 }
192 sal_uInt32 nZippedFileSize = 0; // sj: we will calculate the filesize of a zipped bitmap
193 if ( !bIsJpeg ) // to determine if jpeg compression is useful
194 {
195 SvMemoryStream aTemp;
196 aTemp.SetCompressMode( aTemp.GetCompressMode() | SvStreamCompressFlags::ZBITMAP );
197 aTemp.SetVersion( SOFFICE_FILEFORMAT_40 ); // sj: up from version 40 our bitmap stream operator
198 WriteDIBBitmapEx(aBitmapEx, aTemp); // is capable of zlib stream compression
199 nZippedFileSize = aTemp.TellEnd();
200 }
201 if ( aBitmapEx.IsAlpha() )
202 aAlphaMask = aBitmapEx.GetAlphaMask();
203 Graphic aGraphic(BitmapEx(aBitmapEx.GetBitmap()));
204
205 Sequence< PropertyValue > aFilterData{
206 comphelper::makePropertyValue("Quality", sal_Int32(i_rContext.m_nJPEGQuality)),
207 comphelper::makePropertyValue("ColorMode", sal_Int32(0))
208 };
209
210 try
211 {
212 uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( *pStrm );
213 uno::Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
214 uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
215 uno::Reference< graphic::XGraphicProvider > xGraphicProvider( graphic::GraphicProvider::create(xContext) );
216 uno::Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
217 uno::Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
218 uno::Sequence< beans::PropertyValue > aOutMediaProperties{
219 comphelper::makePropertyValue("OutputStream", xOut),
220 comphelper::makePropertyValue("MimeType", OUString("image/jpeg")),
221 comphelper::makePropertyValue("FilterData", aFilterData)
222 };
223 xGraphicProvider->storeGraphic( xGraphic, aOutMediaProperties );
224 xOut->flush();
225 if ( !bIsJpeg && xSeekable->getLength() > nZippedFileSize )
226 {
227 bUseJPGCompression = false;
228 }
229 else
230 {
231 pStrm->Seek( STREAM_SEEK_TO_END );
232
233 xSeekable->seek( 0 );
235 xStream) };
236 uno::Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
237 if ( xPropSet.is() )
238 {
239 sal_Int16 nBitsPerPixel = 24;
240 if ( xPropSet->getPropertyValue("BitsPerPixel") >>= nBitsPerPixel )
241 {
242 bTrueColorJPG = nBitsPerPixel != 8;
243 }
244 }
245 }
246 }
247 catch( uno::Exception& )
248 {
249 bUseJPGCompression = false;
250 }
251 }
252 if ( bUseJPGCompression )
253 {
254 m_rOuterFace.DrawJPGBitmap( *pStrm, bTrueColorJPG, aSizePixel, tools::Rectangle( aPoint, aSize ), aAlphaMask, i_Graphic );
255 if (!aBitmapEx.IsAlpha() && bTrueColorJPG)
256 {
257 // Cache last jpeg export
259 {aBitmapEx.GetChecksum(), pStrm});
260 }
261 }
262 else if ( aBitmapEx.IsAlpha() )
263 m_rOuterFace.DrawBitmapEx( aPoint, aSize, aBitmapEx );
264 else
265 m_rOuterFace.DrawBitmap( aPoint, aSize, aBitmapEx.GetBitmap(), i_Graphic );
266
267}
268
269void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevData* i_pOutDevData, const vcl::PDFWriter::PlayMetafileContext& i_rContext, VirtualDevice* pDummyVDev )
270{
271 bool bAssertionFired( false );
272
273 ScopedVclPtr<VirtualDevice> xPrivateDevice;
274 if( ! pDummyVDev )
275 {
277 pDummyVDev = xPrivateDevice.get();
278 pDummyVDev->EnableOutput( false );
279 pDummyVDev->SetMapMode( i_rMtf.GetPrefMapMode() );
280 }
281 const GDIMetaFile& aMtf( i_rMtf );
282
283 for( sal_uInt32 i = 0, nCount = aMtf.GetActionSize(); i < nCount; )
284 {
285 if ( !i_pOutDevData || !i_pOutDevData->PlaySyncPageAct( m_rOuterFace, i, aMtf ) )
286 {
287 const MetaAction* pAction = aMtf.GetAction( i );
288 const MetaActionType nType = pAction->GetType();
289
290 switch( nType )
291 {
293 {
294 const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
295 m_rOuterFace.DrawPixel( pA->GetPoint(), pA->GetColor() );
296 }
297 break;
298
300 {
301 const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
303 }
304 break;
305
307 {
308 const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
309 if ( pA->GetLineInfo().IsDefault() )
311 else
313 }
314 break;
315
317 {
318 const MetaRectAction* pA = static_cast<const MetaRectAction*>(pAction);
320 }
321 break;
322
324 {
325 const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
327 }
328 break;
329
331 {
332 const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
334 }
335 break;
336
338 {
339 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
341 }
342 break;
343
345 {
346 const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
348 }
349 break;
350
352 {
353 const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
355 }
356 break;
357
359 {
360 const MetaPolygonAction* pA = static_cast<const MetaPolygonAction*>(pAction);
362 }
363 break;
364
366 {
367 const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
368 if ( pA->GetLineInfo().IsDefault() )
370 else
372 }
373 break;
374
376 {
377 const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pAction);
379 }
380 break;
381
383 {
384 const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
385 const Gradient& rGradient = pA->GetGradient();
386 if (lcl_canUsePDFAxialShading(rGradient))
387 {
388 m_rOuterFace.DrawGradient( pA->GetRect(), rGradient );
389 }
390 else
391 {
392 const tools::PolyPolygon aPolyPoly( pA->GetRect() );
393 implWriteGradient( aPolyPoly, rGradient, pDummyVDev, i_rContext );
394 }
395 }
396 break;
397
399 {
400 const MetaGradientExAction* pA = static_cast<const MetaGradientExAction*>(pAction);
401 const Gradient& rGradient = pA->GetGradient();
402
403 if (lcl_canUsePDFAxialShading(rGradient))
404 m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), rGradient );
405 else
406 implWriteGradient( pA->GetPolyPolygon(), rGradient, pDummyVDev, i_rContext );
407 }
408 break;
409
411 {
412 const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
414 }
415 break;
416
418 {
419 const MetaTransparentAction* pA = static_cast<const MetaTransparentAction*>(pAction);
421 }
422 break;
423
425 {
426 const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
427
428 GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
429 const Point& rPos = pA->GetPoint();
430 const Size& rSize= pA->GetSize();
431 const Gradient& rTransparenceGradient = pA->GetGradient();
432
433 // special case constant alpha value
434 if( rTransparenceGradient.GetStartColor() == rTransparenceGradient.GetEndColor() )
435 {
436 const Color aTransCol( rTransparenceGradient.GetStartColor() );
437 const sal_uInt16 nTransPercent = aTransCol.GetLuminance() * 100 / 255;
439
440 // tdf#138826 adjust the aTmpMtf to start at rPos (see also #i112076#)
441 Point aMtfOrigin(aTmpMtf.GetPrefMapMode().GetOrigin());
442 if (rPos != aMtfOrigin)
443 aTmpMtf.Move(rPos.X() - aMtfOrigin.X(), rPos.Y() - aMtfOrigin.Y());
444
445 playMetafile( aTmpMtf, nullptr, i_rContext, pDummyVDev );
446 m_rOuterFace.EndTransparencyGroup( tools::Rectangle( rPos, rSize ), nTransPercent );
447 }
448 else
449 {
450 const Size aDstSizeTwip( pDummyVDev->PixelToLogic(pDummyVDev->LogicToPixel(rSize), MapMode(MapUnit::MapTwip)) );
451
452 // i#115962# Always use at least 300 DPI for bitmap conversion of transparence gradients,
453 // else the quality is not acceptable (see bugdoc as example)
454 sal_Int32 nMaxBmpDPI(300);
455
456 if( i_rContext.m_nMaxImageResolution > 50 )
457 {
458 if ( nMaxBmpDPI > i_rContext.m_nMaxImageResolution )
459 nMaxBmpDPI = i_rContext.m_nMaxImageResolution;
460 }
461 const sal_Int32 nPixelX = o3tl::convert<double>(aDstSizeTwip.Width(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI;
462 const sal_Int32 nPixelY = o3tl::convert<double>(aDstSizeTwip.Height(), o3tl::Length::twip, o3tl::Length::in) * nMaxBmpDPI;
463 if ( nPixelX && nPixelY )
464 {
465 Size aDstSizePixel( nPixelX, nPixelY );
467 if( xVDev->SetOutputSizePixel( aDstSizePixel, true, true ) )
468 {
469 Point aPoint;
470
471 MapMode aMapMode( pDummyVDev->GetMapMode() );
472 aMapMode.SetOrigin( aPoint );
473 xVDev->SetMapMode( aMapMode );
474 const bool bVDevOldMap = xVDev->IsMapModeEnabled();
475 Size aDstSize( xVDev->PixelToLogic( aDstSizePixel ) );
476
477 Point aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
478 if ( aMtfOrigin.X() || aMtfOrigin.Y() )
479 aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
480 double fScaleX = static_cast<double>(aDstSize.Width()) / static_cast<double>(aTmpMtf.GetPrefSize().Width());
481 double fScaleY = static_cast<double>(aDstSize.Height()) / static_cast<double>(aTmpMtf.GetPrefSize().Height());
482 if( fScaleX != 1.0 || fScaleY != 1.0 )
483 aTmpMtf.Scale( fScaleX, fScaleY );
484 aTmpMtf.SetPrefMapMode( aMapMode );
485
486 // create paint bitmap
487 aTmpMtf.WindStart();
488 aTmpMtf.Play(*xVDev, aPoint, aDstSize);
489 aTmpMtf.WindStart();
490 xVDev->EnableMapMode( false );
491 BitmapEx aPaint = xVDev->GetBitmapEx(aPoint, xVDev->GetOutputSizePixel());
492 xVDev->EnableMapMode( bVDevOldMap ); // #i35331#: MUST NOT use EnableMapMode( sal_True ) here!
493
494 // create alpha mask from gradient
495 xVDev->SetDrawMode( DrawModeFlags::GrayGradient );
496 xVDev->DrawGradient( tools::Rectangle( aPoint, aDstSize ), rTransparenceGradient );
497 xVDev->SetDrawMode( DrawModeFlags::Default );
498 xVDev->EnableMapMode( false );
499
500 AlphaMask aAlpha(xVDev->GetBitmap(Point(), xVDev->GetOutputSizePixel()));
501 AlphaMask aPaintAlpha(aPaint.GetAlphaMask());
502#if HAVE_FEATURE_SKIA
503 // One of the alpha masks is inverted from what
504 // is expected so invert it again
506 {
507 aAlpha.Invert(); // convert to alpha
508 }
509 else
510#endif
511 {
512 aPaintAlpha.Invert(); // convert to alpha
513 }
514 aAlpha.BlendWith(aPaintAlpha);
515#if HAVE_FEATURE_SKIA
517#endif
518 {
519 aAlpha.Invert(); // convert to alpha
520 }
521
522 xVDev.disposeAndClear();
523
524 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
525 implWriteBitmapEx( rPos, rSize, BitmapEx( aPaint.GetBitmap(), aAlpha ), aGraphic, pDummyVDev, i_rContext );
526 }
527 }
528 }
529 }
530 break;
531
533 {
534 const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pAction);
535 const GDIMetaFile& aSubstitute( pA->GetSubstitute() );
536
538 pDummyVDev->Push();
539
540 MapMode aMapMode( aSubstitute.GetPrefMapMode() );
541 Size aOutSize( OutputDevice::LogicToLogic( pA->GetSize(), pDummyVDev->GetMapMode(), aMapMode ) );
542 aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
543 aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
544 aMapMode.SetOrigin( OutputDevice::LogicToLogic( pA->GetPoint(), pDummyVDev->GetMapMode(), aMapMode ) );
545
546 m_rOuterFace.SetMapMode( aMapMode );
547 pDummyVDev->SetMapMode( aMapMode );
548 playMetafile( aSubstitute, nullptr, i_rContext, pDummyVDev );
549 pDummyVDev->Pop();
551 }
552 break;
553
555 if( ! i_rContext.m_bTransparenciesWereRemoved )
556 {
557 const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
558
559 if( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
560 {
561 const MetaGradientExAction* pGradAction = nullptr;
562 bool bDone = false;
563
564 while( !bDone && ( ++i < nCount ) )
565 {
566 pAction = aMtf.GetAction( i );
567
568 if( pAction->GetType() == MetaActionType::GRADIENTEX )
569 pGradAction = static_cast<const MetaGradientExAction*>(pAction);
570 else if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
571 ( static_cast<const MetaCommentAction*>(pAction)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END")) )
572 {
573 bDone = true;
574 }
575 }
576
577 if( pGradAction )
578 {
579 if (lcl_canUsePDFAxialShading(pGradAction->GetGradient()))
580 {
581 m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() );
582 }
583 else
584 {
585 implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext );
586 }
587 }
588 }
589 else
590 {
591 const sal_uInt8* pData = pA->GetData();
592 if ( pData )
593 {
594 SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pData), pA->GetDataSize(), StreamMode::READ );
595 bool bSkipSequence = false;
596 OString sSeqEnd;
597
598 if( pA->GetComment() == "XPATHSTROKE_SEQ_BEGIN" )
599 {
600 sSeqEnd = OString("XPATHSTROKE_SEQ_END");
601 SvtGraphicStroke aStroke;
602 ReadSvtGraphicStroke( aMemStm, aStroke );
603
604 tools::Polygon aPath;
605 aStroke.getPath( aPath );
606
607 tools::PolyPolygon aStartArrow;
608 tools::PolyPolygon aEndArrow;
609 double fTransparency( aStroke.getTransparency() );
610 double fStrokeWidth( aStroke.getStrokeWidth() );
612
613 aStroke.getStartArrow( aStartArrow );
614 aStroke.getEndArrow( aEndArrow );
615 aStroke.getDashArray( aDashArray );
616
617 bSkipSequence = true;
618 if ( aStartArrow.Count() || aEndArrow.Count() )
619 bSkipSequence = false;
620 if ( !aDashArray.empty() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
621 bSkipSequence = false;
622 if ( bSkipSequence )
623 {
625 aInfo.m_fLineWidth = fStrokeWidth;
626 aInfo.m_fTransparency = fTransparency;
627 aInfo.m_fMiterLimit = aStroke.getMiterLimit();
628 switch( aStroke.getCapType() )
629 {
630 default:
634 }
635 switch( aStroke.getJoinType() )
636 {
637 default:
643 aInfo.m_fMiterLimit = 0.0;
644 break;
645 }
646 aInfo.m_aDashArray = aDashArray;
647
649 && fStrokeWidth > 0.0)
650 {
651 // emulate no edge rounding by handling single edges
652 const sal_uInt16 nPoints(aPath.GetSize());
653 const bool bCurve(aPath.HasFlags());
654
655 for(sal_uInt16 a(0); a + 1 < nPoints; a++)
656 {
657 if(bCurve
658 && PolyFlags::Normal != aPath.GetFlags(a + 1)
659 && a + 2 < nPoints
660 && PolyFlags::Normal != aPath.GetFlags(a + 2)
661 && a + 3 < nPoints)
662 {
663 const tools::Polygon aSnippet(4,
664 aPath.GetConstPointAry() + a,
665 aPath.GetConstFlagAry() + a);
666 m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
667 a += 2;
668 }
669 else
670 {
671 const tools::Polygon aSnippet(2,
672 aPath.GetConstPointAry() + a);
673 m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
674 }
675 }
676 }
677 else
678 {
679 m_rOuterFace.DrawPolyLine( aPath, aInfo );
680 }
681 }
682 }
683 else if ( pA->GetComment() == "XPATHFILL_SEQ_BEGIN" )
684 {
685 sSeqEnd = OString("XPATHFILL_SEQ_END");
686 SvtGraphicFill aFill;
687 ReadSvtGraphicFill( aMemStm, aFill );
688
690 {
691 double fTransparency = aFill.getTransparency();
692 if ( fTransparency == 0.0 )
693 {
694 tools::PolyPolygon aPath;
695 aFill.getPath( aPath );
696
697 bSkipSequence = true;
699 }
700 else if ( fTransparency == 1.0 )
701 bSkipSequence = true;
702 }
703 }
704 if ( bSkipSequence )
705 {
706 while( ++i < nCount )
707 {
708 pAction = aMtf.GetAction( i );
709 if ( pAction->GetType() == MetaActionType::COMMENT )
710 {
711 OString sComment( static_cast<const MetaCommentAction*>(pAction)->GetComment() );
712 if (sComment == sSeqEnd)
713 break;
714 }
715 // #i44496#
716 // the replacement action for stroke is a filled rectangle
717 // the set fillcolor of the replacement is part of the graphics
718 // state and must not be skipped
719 else if( pAction->GetType() == MetaActionType::FILLCOLOR )
720 {
721 const MetaFillColorAction* pMA = static_cast<const MetaFillColorAction*>(pAction);
722 if( pMA->IsSetting() )
724 else
726 }
727 }
728 }
729 }
730 }
731 }
732 break;
733
735 {
736 const MetaBmpAction* pA = static_cast<const MetaBmpAction*>(pAction);
737 BitmapEx aBitmapEx( pA->GetBitmap() );
738 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
739 aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
740 if( ! ( aSize.Width() && aSize.Height() ) )
741 aSize = pDummyVDev->PixelToLogic( aBitmapEx.GetSizePixel() );
742
743 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
744 implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, aGraphic, pDummyVDev, i_rContext );
745 }
746 break;
747
749 {
750 const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
751 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
752 implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), BitmapEx( pA->GetBitmap() ), aGraphic, pDummyVDev, i_rContext );
753 }
754 break;
755
757 {
758 const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pAction);
759 BitmapEx aBitmapEx( pA->GetBitmap() );
760 aBitmapEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
761 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
762 implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, aGraphic, pDummyVDev, i_rContext );
763 }
764 break;
765
767 {
768 const MetaBmpExAction* pA = static_cast<const MetaBmpExAction*>(pAction);
769
770 // When rendering an image with an alpha mask during PDF
771 // export, the alpha mask needs to be inverted
772 BitmapEx aBitmapEx( pA->GetBitmapEx() );
773 if ( aBitmapEx.IsAlpha())
774 {
775 AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
776 aAlpha.Invert();
777 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
778 }
779
780 Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
781 aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
782 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
783 implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, aGraphic, pDummyVDev, i_rContext );
784 }
785 break;
786
788 {
789 const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
790
791 // When rendering an image with an alpha mask during PDF
792 // export, the alpha mask needs to be inverted
793 BitmapEx aBitmapEx( pA->GetBitmapEx() );
794 if ( aBitmapEx.IsAlpha())
795 {
796 AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
797 aAlpha.Invert();
798 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
799 }
800
801 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
802 implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), aBitmapEx, aGraphic, pDummyVDev, i_rContext );
803 }
804 break;
805
807 {
808 const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
809
810 // When rendering an image with an alpha mask during PDF
811 // export, the alpha mask needs to be inverted
812 BitmapEx aBitmapEx( pA->GetBitmapEx() );
813 if ( aBitmapEx.IsAlpha())
814 {
815 AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
816 aAlpha.Invert();
817 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
818 }
819
820 aBitmapEx.Crop( tools::Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
821 Graphic aGraphic = i_pOutDevData ? i_pOutDevData->GetCurrentGraphic() : Graphic();
822 implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, aGraphic, pDummyVDev, i_rContext );
823 }
824 break;
825
829 {
830 SAL_WARN( "vcl", "MetaMask...Action not supported yet" );
831 }
832 break;
833
835 {
836 const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
837 m_rOuterFace.DrawText( pA->GetPoint(), pA->GetText().copy( pA->GetIndex(), std::min<sal_Int32>(pA->GetText().getLength() - pA->GetIndex(), pA->GetLen()) ) );
838 }
839 break;
840
842 {
843 const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
844 m_rOuterFace.DrawText( pA->GetRect(), pA->GetText(), pA->GetStyle() );
845 }
846 break;
847
849 {
850 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
851 m_rOuterFace.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetKashidaArray(), pA->GetIndex(), pA->GetLen() );
852 }
853 break;
854
856 {
857 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
858 m_rOuterFace.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
859 }
860 break;
861
863 {
864 const MetaTextLineAction* pA = static_cast<const MetaTextLineAction*>(pAction);
866
867 }
868 break;
869
871 {
872 const MetaClipRegionAction* pA = static_cast<const MetaClipRegionAction*>(pAction);
873
874 if( pA->IsClipping() )
875 {
876 if( pA->GetRegion().IsEmpty() )
878 else
879 {
880 const vcl::Region& aReg( pA->GetRegion() );
882 }
883 }
884 else
886 }
887 break;
888
890 {
891 const MetaISectRectClipRegionAction* pA = static_cast<const MetaISectRectClipRegionAction*>(pAction);
893 }
894 break;
895
897 {
898 const MetaISectRegionClipRegionAction* pA = static_cast<const MetaISectRegionClipRegionAction*>(pAction);
899 const vcl::Region& aReg( pA->GetRegion() );
901 }
902 break;
903
905 {
906 const MetaMoveClipRegionAction* pA = static_cast<const MetaMoveClipRegionAction*>(pAction);
908 }
909 break;
910
912 {
913 const_cast< MetaAction* >( pAction )->Execute( pDummyVDev );
914 m_rOuterFace.SetMapMode( pDummyVDev->GetMapMode() );
915 }
916 break;
917
919 {
920 const MetaLineColorAction* pA = static_cast<const MetaLineColorAction*>(pAction);
921
922 if( pA->IsSetting() )
924 else
926 }
927 break;
928
930 {
931 const MetaFillColorAction* pA = static_cast<const MetaFillColorAction*>(pAction);
932
933 if( pA->IsSetting() )
935 else
937 }
938 break;
939
941 {
942 const MetaTextLineColorAction* pA = static_cast<const MetaTextLineColorAction*>(pAction);
943
944 if( pA->IsSetting() )
946 else
948 }
949 break;
950
952 {
953 const MetaOverlineColorAction* pA = static_cast<const MetaOverlineColorAction*>(pAction);
954
955 if( pA->IsSetting() )
957 else
959 }
960 break;
961
963 {
964 const MetaTextFillColorAction* pA = static_cast<const MetaTextFillColorAction*>(pAction);
965
966 if( pA->IsSetting() )
968 else
970 }
971 break;
972
974 {
975 const MetaTextColorAction* pA = static_cast<const MetaTextColorAction*>(pAction);
977 }
978 break;
979
981 {
982 const MetaTextAlignAction* pA = static_cast<const MetaTextAlignAction*>(pAction);
984 }
985 break;
986
988 {
989 const MetaFontAction* pA = static_cast<const MetaFontAction*>(pAction);
991 }
992 break;
993
995 {
996 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
997
998 pDummyVDev->Push( pA->GetFlags() );
999 m_rOuterFace.Push( pA->GetFlags() );
1000 }
1001 break;
1002
1004 {
1005 pDummyVDev->Pop();
1006 m_rOuterFace.Pop();
1007 }
1008 break;
1009
1011 {
1012 const MetaLayoutModeAction* pA = static_cast<const MetaLayoutModeAction*>(pAction);
1014 }
1015 break;
1016
1018 {
1019 const MetaTextLanguageAction* pA = static_cast<const MetaTextLanguageAction*>(pAction);
1021 }
1022 break;
1023
1025 {
1026 const MetaWallpaperAction* pA = static_cast<const MetaWallpaperAction*>(pAction);
1028 }
1029 break;
1030
1032 {
1033 // !!! >>> we don't want to support this actions
1034 }
1035 break;
1036
1038 {
1039 // !!! >>> we don't want to support this actions
1040 }
1041 break;
1042
1043 default:
1044 // #i24604# Made assertion fire only once per
1045 // metafile. The asserted actions here are all
1046 // deprecated
1047 if( !bAssertionFired )
1048 {
1049 bAssertionFired = true;
1050 SAL_WARN( "vcl", "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered " << static_cast<int>(nType) );
1051 }
1052 break;
1053 }
1054 i++;
1055 }
1056 }
1057}
1058
1059// Encryption methods
1060
1061/* a crutch to transport a ::comphelper::Hash safely though UNO API
1062 this is needed for the PDF export dialog, which otherwise would have to pass
1063 clear text passwords down till they can be used in PDFWriter. Unfortunately
1064 the MD5 sum of the password (which is needed to create the PDF encryption key)
1065 is not sufficient, since an MD5 digest cannot be created in an arbitrary state
1066 which would be needed in PDFWriterImpl::computeEncryptionKey.
1067*/
1068class EncHashTransporter : public cppu::WeakImplHelper < css::beans::XMaterialHolder >
1069{
1070 ::std::unique_ptr<::comphelper::Hash> m_pDigest;
1071 sal_IntPtr maID;
1072 std::vector< sal_uInt8 > maOValue;
1073
1074 static std::map< sal_IntPtr, EncHashTransporter* > sTransporters;
1075public:
1077 : m_pDigest(new ::comphelper::Hash(::comphelper::HashType::MD5))
1078 {
1079 maID = reinterpret_cast< sal_IntPtr >(this);
1080 while( sTransporters.find( maID ) != sTransporters.end() ) // paranoia mode
1081 maID++;
1082 sTransporters[ maID ] = this;
1083 }
1084
1085 virtual ~EncHashTransporter() override
1086 {
1087 sTransporters.erase( maID );
1088 SAL_INFO( "vcl", "EncHashTransporter freed" );
1089 }
1090
1091 ::comphelper::Hash* getUDigest() { return m_pDigest.get(); };
1092 std::vector< sal_uInt8 >& getOValue() { return maOValue; }
1094 {
1095 m_pDigest.reset();
1096 }
1097
1098 // XMaterialHolder
1099 virtual uno::Any SAL_CALL getMaterial() override
1100 {
1101 return uno::Any( sal_Int64(maID) );
1102 }
1103
1104 static EncHashTransporter* getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& );
1105
1106};
1107
1108std::map< sal_IntPtr, EncHashTransporter* > EncHashTransporter::sTransporters;
1109
1110EncHashTransporter* EncHashTransporter::getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& xRef )
1111{
1112 EncHashTransporter* pResult = nullptr;
1113 if( xRef.is() )
1114 {
1115 uno::Any aMat( xRef->getMaterial() );
1116 sal_Int64 nMat = 0;
1117 if( aMat >>= nMat )
1118 {
1119 std::map< sal_IntPtr, EncHashTransporter* >::iterator it = sTransporters.find( static_cast<sal_IntPtr>(nMat) );
1120 if( it != sTransporters.end() )
1121 pResult = it->second;
1122 }
1123 }
1124 return pResult;
1125}
1126
1128{
1130 return;
1131
1132 m_bEncryptThisStream = true;
1133 sal_Int32 i = m_nKeyLength;
1134 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>(nObject);
1135 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject >> 8 );
1136 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject >> 16 );
1137 // the other location of m_nEncryptionKey is already set to 0, our fixed generation number
1138 // do the MD5 hash
1139 ::std::vector<unsigned char> const nMD5Sum(::comphelper::Hash::calculateHash(
1140 m_aContext.Encryption.EncryptionKey.data(), i+2, ::comphelper::HashType::MD5));
1141 // the i+2 to take into account the generation number, always zero
1142 // initialize the RC4 with the key
1143 // key length: see algorithm 3.1, step 4: (N+5) max 16
1144 rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_nRC4KeyLength, nullptr, 0 );
1145}
1146
1148{
1150 return;
1151
1152 sal_Int32 i = m_nKeyLength;
1153 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>(nObject);
1154 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject >> 8 );
1155 m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject >> 16 );
1156 // the other location of m_nEncryptionKey is already set to 0, our fixed generation number
1157 // do the MD5 hash
1158 // the i+2 to take into account the generation number, always zero
1159 ::std::vector<unsigned char> const nMD5Sum(::comphelper::Hash::calculateHash(
1160 m_aContext.Encryption.EncryptionKey.data(), i+2, ::comphelper::HashType::MD5));
1161 // initialize the RC4 with the key
1162 // key length: see algorithm 3.1, step 4: (N+5) max 16
1163 rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_nRC4KeyLength, nullptr, 0 );
1164}
1165
1166/* init the encryption engine
11671. init the document id, used both for building the document id and for building the encryption key(s)
11682. build the encryption key following algorithms described in the PDF specification
1169 */
1170uno::Reference< beans::XMaterialHolder > PDFWriterImpl::initEncryption( const OUString& i_rOwnerPassword,
1171 const OUString& i_rUserPassword
1172 )
1173{
1174 uno::Reference< beans::XMaterialHolder > xResult;
1175 if( !i_rOwnerPassword.isEmpty() || !i_rUserPassword.isEmpty() )
1176 {
1178 xResult = pTransporter;
1179
1180 // get padded passwords
1182 padPassword( i_rOwnerPassword.isEmpty() ? i_rUserPassword : i_rOwnerPassword, aPadOPW );
1183 padPassword( i_rUserPassword, aPadUPW );
1184
1185 if( computeODictionaryValue( aPadOPW, aPadUPW, pTransporter->getOValue(), SECUR_128BIT_KEY ) )
1186 {
1187 pTransporter->getUDigest()->update(aPadUPW, ENCRYPTED_PWD_SIZE);
1188 }
1189 else
1190 xResult.clear();
1191
1192 // trash temporary padded cleartext PWDs
1193 rtl_secureZeroMemory (aPadOPW, sizeof(aPadOPW));
1194 rtl_secureZeroMemory (aPadUPW, sizeof(aPadUPW));
1195 }
1196 return xResult;
1197}
1198
1199bool PDFWriterImpl::prepareEncryption( const uno::Reference< beans::XMaterialHolder >& xEnc )
1200{
1201 bool bSuccess = false;
1203 if( pTransporter )
1204 {
1205 sal_Int32 nKeyLength = 0, nRC4KeyLength = 0;
1206 sal_Int32 nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, nKeyLength, nRC4KeyLength );
1207 m_aContext.Encryption.OValue = pTransporter->getOValue();
1208 bSuccess = computeUDictionaryValue( pTransporter, m_aContext.Encryption, nKeyLength, nAccessPermissions );
1209 }
1210 if( ! bSuccess )
1211 {
1215 }
1216 return bSuccess;
1217}
1218
1220 sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength )
1221{
1222 /*
1223 2) compute the access permissions, in numerical form
1224
1225 the default value depends on the revision 2 (40 bit) or 3 (128 bit security):
1226 - for 40 bit security the unused bit must be set to 1, since they are not used
1227 - for 128 bit security the same bit must be preset to 0 and set later if needed
1228 according to the table 3.15, pdf v 1.4 */
1229 sal_Int32 nAccessPermissions = 0xfffff0c0;
1230
1231 o_rKeyLength = SECUR_128BIT_KEY;
1232 o_rRC4KeyLength = 16; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 16,
1233 // thus maximum permitted value is 16
1234
1235 nAccessPermissions |= ( i_rProperties.CanPrintTheDocument ) ? 1 << 2 : 0;
1236 nAccessPermissions |= ( i_rProperties.CanModifyTheContent ) ? 1 << 3 : 0;
1237 nAccessPermissions |= ( i_rProperties.CanCopyOrExtract ) ? 1 << 4 : 0;
1238 nAccessPermissions |= ( i_rProperties.CanAddOrModify ) ? 1 << 5 : 0;
1239 nAccessPermissions |= ( i_rProperties.CanFillInteractive ) ? 1 << 8 : 0;
1240 nAccessPermissions |= ( i_rProperties.CanExtractForAccessibility ) ? 1 << 9 : 0;
1241 nAccessPermissions |= ( i_rProperties.CanAssemble ) ? 1 << 10 : 0;
1242 nAccessPermissions |= ( i_rProperties.CanPrintFull ) ? 1 << 11 : 0;
1243 return nAccessPermissions;
1244}
1245
1246/*************************************************************
1247begin i12626 methods
1248
1249Implements Algorithm 3.2, step 1 only
1250*/
1251void PDFWriterImpl::padPassword( std::u16string_view i_rPassword, sal_uInt8* o_pPaddedPW )
1252{
1253 // get ansi-1252 version of the password string CHECKIT ! i12626
1254 OString aString( OUStringToOString( i_rPassword, RTL_TEXTENCODING_MS_1252 ) );
1255
1256 //copy the string to the target
1257 sal_Int32 nToCopy = ( aString.getLength() < ENCRYPTED_PWD_SIZE ) ? aString.getLength() : ENCRYPTED_PWD_SIZE;
1258 sal_Int32 nCurrentChar;
1259
1260 for( nCurrentChar = 0; nCurrentChar < nToCopy; nCurrentChar++ )
1261 o_pPaddedPW[nCurrentChar] = static_cast<sal_uInt8>( aString[nCurrentChar] );
1262
1263 //pad it with standard byte string
1264 sal_Int32 i,y;
1265 for( i = nCurrentChar, y = 0 ; i < ENCRYPTED_PWD_SIZE; i++, y++ )
1266 o_pPaddedPW[i] = s_nPadString[y];
1267}
1268
1269/**********************************
1270Algorithm 3.2 Compute the encryption key used
1271
1272step 1 should already be done before calling, the paThePaddedPassword parameter should contain
1273the padded password and must be 32 byte long, the encryption key is returned into the paEncryptionKey parameter,
1274it will be 16 byte long for 128 bit security; for 40 bit security only the first 5 bytes are used
1275
1276TODO: in pdf ver 1.5 and 1.6 the step 6 is different, should be implemented. See spec.
1277
1278*/
1279bool PDFWriterImpl::computeEncryptionKey( EncHashTransporter* i_pTransporter, vcl::PDFWriter::PDFEncryptionProperties& io_rProperties, sal_Int32 i_nAccessPermissions )
1280{
1281 bool bSuccess = true;
1282 ::std::vector<unsigned char> nMD5Sum;
1283
1284 // transporter contains an MD5 digest with the padded user password already
1285 ::comphelper::Hash *const pDigest = i_pTransporter->getUDigest();
1286 if (pDigest)
1287 {
1288 //step 3
1289 if( ! io_rProperties.OValue.empty() )
1290 pDigest->update(io_rProperties.OValue.data(), io_rProperties.OValue.size());
1291 else
1292 bSuccess = false;
1293 //Step 4
1294 sal_uInt8 nPerm[4];
1295
1296 nPerm[0] = static_cast<sal_uInt8>(i_nAccessPermissions);
1297 nPerm[1] = static_cast<sal_uInt8>( i_nAccessPermissions >> 8 );
1298 nPerm[2] = static_cast<sal_uInt8>( i_nAccessPermissions >> 16 );
1299 nPerm[3] = static_cast<sal_uInt8>( i_nAccessPermissions >> 24 );
1300
1301 pDigest->update(nPerm, sizeof(nPerm));
1302
1303 //step 5, get the document ID, binary form
1304 pDigest->update(io_rProperties.DocumentIdentifier.data(), io_rProperties.DocumentIdentifier.size());
1305 //get the digest
1306 nMD5Sum = pDigest->finalize();
1307
1308 //step 6, only if 128 bit
1309 for (sal_Int32 i = 0; i < 50; i++)
1310 {
1311 nMD5Sum = ::comphelper::Hash::calculateHash(nMD5Sum.data(), nMD5Sum.size(), ::comphelper::HashType::MD5);
1312 }
1313 }
1314 else
1315 bSuccess = false;
1316
1317 i_pTransporter->invalidate();
1318
1319 //Step 7
1320 if( bSuccess )
1321 {
1322 io_rProperties.EncryptionKey.resize( MAXIMUM_RC4_KEY_LENGTH );
1323 for( sal_Int32 i = 0; i < MD5_DIGEST_SIZE; i++ )
1324 io_rProperties.EncryptionKey[i] = nMD5Sum[i];
1325 }
1326 else
1327 io_rProperties.EncryptionKey.clear();
1328
1329 return bSuccess;
1330}
1331
1332/**********************************
1333Algorithm 3.3 Compute the encryption dictionary /O value, save into the class data member
1334the step numbers down here correspond to the ones in PDF v.1.4 specification
1335*/
1336bool PDFWriterImpl::computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword,
1337 const sal_uInt8* i_pPaddedUserPassword,
1338 std::vector< sal_uInt8 >& io_rOValue,
1339 sal_Int32 i_nKeyLength
1340 )
1341{
1342 bool bSuccess = true;
1343
1344 io_rOValue.resize( ENCRYPTED_PWD_SIZE );
1345
1346 rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1347 if (aCipher)
1348 {
1349 //step 1 already done, data is in i_pPaddedOwnerPassword
1350 //step 2
1351
1352 ::std::vector<unsigned char> nMD5Sum(::comphelper::Hash::calculateHash(
1353 i_pPaddedOwnerPassword, ENCRYPTED_PWD_SIZE, ::comphelper::HashType::MD5));
1354 //step 3, only if 128 bit
1355 if (i_nKeyLength == SECUR_128BIT_KEY)
1356 {
1357 sal_Int32 i;
1358 for (i = 0; i < 50; i++)
1359 {
1360 nMD5Sum = ::comphelper::Hash::calculateHash(nMD5Sum.data(), nMD5Sum.size(), ::comphelper::HashType::MD5);
1361 }
1362 }
1363 //Step 4, the key is in nMD5Sum
1364 //step 5 already done, data is in i_pPaddedUserPassword
1365 //step 6
1366 if (rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
1367 nMD5Sum.data(), i_nKeyLength , nullptr, 0 )
1368 == rtl_Cipher_E_None)
1369 {
1370 // encrypt the user password using the key set above
1371 rtl_cipher_encodeARCFOUR( aCipher, i_pPaddedUserPassword, ENCRYPTED_PWD_SIZE, // the data to be encrypted
1372 io_rOValue.data(), sal_Int32(io_rOValue.size()) ); //encrypted data
1373 //Step 7, only if 128 bit
1374 if( i_nKeyLength == SECUR_128BIT_KEY )
1375 {
1376 sal_uInt32 i;
1377 size_t y;
1378 sal_uInt8 nLocalKey[ SECUR_128BIT_KEY ]; // 16 = 128 bit key
1379
1380 for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
1381 {
1382 for( y = 0; y < sizeof( nLocalKey ); y++ )
1383 nLocalKey[y] = static_cast<sal_uInt8>( nMD5Sum[y] ^ i );
1384
1385 if (rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
1386 nLocalKey, SECUR_128BIT_KEY, nullptr, 0 ) //destination data area, on init can be NULL
1387 != rtl_Cipher_E_None)
1388 {
1389 bSuccess = false;
1390 break;
1391 }
1392 rtl_cipher_encodeARCFOUR( aCipher, io_rOValue.data(), sal_Int32(io_rOValue.size()), // the data to be encrypted
1393 io_rOValue.data(), sal_Int32(io_rOValue.size()) ); // encrypted data, can be the same as the input, encrypt "in place"
1394 //step 8, store in class data member
1395 }
1396 }
1397 }
1398 else
1399 bSuccess = false;
1400 }
1401 else
1402 bSuccess = false;
1403
1404 if( aCipher )
1405 rtl_cipher_destroyARCFOUR( aCipher );
1406
1407 if( ! bSuccess )
1408 io_rOValue.clear();
1409 return bSuccess;
1410}
1411
1412/**********************************
1413Algorithms 3.4 and 3.5 Compute the encryption dictionary /U value, save into the class data member, revision 2 (40 bit) or 3 (128 bit)
1414*/
1417 sal_Int32 i_nKeyLength,
1418 sal_Int32 i_nAccessPermissions
1419 )
1420{
1421 bool bSuccess = true;
1422
1423 io_rProperties.UValue.resize( ENCRYPTED_PWD_SIZE );
1424
1425 ::comphelper::Hash aDigest(::comphelper::HashType::MD5);
1426 rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
1427 if (aCipher)
1428 {
1429 //step 1, common to both 3.4 and 3.5
1430 if( computeEncryptionKey( i_pTransporter, io_rProperties, i_nAccessPermissions ) )
1431 {
1432 // prepare encryption key for object
1433 for( sal_Int32 i = i_nKeyLength, y = 0; y < 5 ; y++ )
1434 io_rProperties.EncryptionKey[i++] = 0;
1435
1436 //or 3.5, for 128 bit security
1437 //step6, initialize the last 16 bytes of the encrypted user password to 0
1438 for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sal_uInt32(io_rProperties.UValue.size()); i++)
1439 io_rProperties.UValue[i] = 0;
1440 //steps 2 and 3
1441 aDigest.update(s_nPadString, sizeof(s_nPadString));
1442 aDigest.update(io_rProperties.DocumentIdentifier.data(), io_rProperties.DocumentIdentifier.size());
1443
1444 ::std::vector<unsigned char> const nMD5Sum(aDigest.finalize());
1445 //Step 4
1446 rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
1447 io_rProperties.EncryptionKey.data(), SECUR_128BIT_KEY, nullptr, 0 ); //destination data area
1448 rtl_cipher_encodeARCFOUR( aCipher, nMD5Sum.data(), nMD5Sum.size(), // the data to be encrypted
1449 io_rProperties.UValue.data(), SECUR_128BIT_KEY ); //encrypted data, stored in class data member
1450 //step 5
1451 sal_uInt32 i;
1452 size_t y;
1453 sal_uInt8 nLocalKey[SECUR_128BIT_KEY];
1454
1455 for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
1456 {
1457 for( y = 0; y < sizeof( nLocalKey ) ; y++ )
1458 nLocalKey[y] = static_cast<sal_uInt8>( io_rProperties.EncryptionKey[y] ^ i );
1459
1460 rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
1461 nLocalKey, SECUR_128BIT_KEY, // key and key length
1462 nullptr, 0 ); //destination data area, on init can be NULL
1463 rtl_cipher_encodeARCFOUR( aCipher, io_rProperties.UValue.data(), SECUR_128BIT_KEY, // the data to be encrypted
1464 io_rProperties.UValue.data(), SECUR_128BIT_KEY ); // encrypted data, can be the same as the input, encrypt "in place"
1465 }
1466 }
1467 else
1468 bSuccess = false;
1469 }
1470 else
1471 bSuccess = false;
1472
1473 if( aCipher )
1474 rtl_cipher_destroyARCFOUR( aCipher );
1475
1476 if( ! bSuccess )
1477 io_rProperties.UValue.clear();
1478 return bSuccess;
1479}
1480
1481/* end i12626 methods */
1482
1484{
1485 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
1486 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
1487 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
1488 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
1489 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
1490 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
1491 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
1492 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
1493 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
1494 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
1495 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
1496 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
1497 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
1498 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
1499 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
1500 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
1501};
1502
1504{
1505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
1506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
1507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
1508 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
1509 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
1510 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
1511 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
1512 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
1513 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
1514 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
1515 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
1516 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
1517 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
1518 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
1519 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
1520 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
1521};
1522
1523static bool isSet( const Scanline i_pLine, tools::Long i_nIndex )
1524{
1525 return (i_pLine[ i_nIndex/8 ] & (0x80 >> (i_nIndex&7))) != 0;
1526}
1527
1528static tools::Long findBitRunImpl( const Scanline i_pLine, tools::Long i_nStartIndex, tools::Long i_nW, bool i_bSet )
1529{
1530 tools::Long nIndex = i_nStartIndex;
1531 if( nIndex < i_nW )
1532 {
1533 const sal_uInt8 * pByte = i_pLine + (nIndex/8);
1534 sal_uInt8 nByte = *pByte;
1535
1536 // run up to byte boundary
1537 tools::Long nBitInByte = (nIndex & 7);
1538 if( nBitInByte )
1539 {
1540 sal_uInt8 nMask = 0x80 >> nBitInByte;
1541 while( nBitInByte != 8 )
1542 {
1543 if( (nByte & nMask) != (i_bSet ? nMask : 0) )
1544 return std::min(nIndex, i_nW);
1545 nMask = nMask >> 1;
1546 nBitInByte++;
1547 nIndex++;
1548 }
1549 if( nIndex < i_nW )
1550 {
1551 pByte++;
1552 nByte = *pByte;
1553 }
1554 }
1555
1556 sal_uInt8 nRunByte;
1557 const tools::Long* pRunTable;
1558 if( i_bSet )
1559 {
1560 nRunByte = 0xff;
1561 pRunTable = setRun;
1562 }
1563 else
1564 {
1565 nRunByte = 0;
1566 pRunTable = unsetRun;
1567 }
1568
1569 if( nIndex < i_nW )
1570 {
1571 while( nByte == nRunByte )
1572 {
1573 nIndex += 8;
1574
1575 if (nIndex >= i_nW)
1576 break;
1577
1578 pByte++;
1579 nByte = *pByte;
1580 }
1581 }
1582
1583 if( nIndex < i_nW )
1584 {
1585 nIndex += pRunTable[nByte];
1586 }
1587 }
1588 return std::min(nIndex, i_nW);
1589}
1590
1591static tools::Long findBitRun(const Scanline i_pLine, tools::Long i_nStartIndex, tools::Long i_nW, bool i_bSet)
1592{
1593 if (i_nStartIndex < 0)
1594 return i_nW;
1595
1596 return findBitRunImpl(i_pLine, i_nStartIndex, i_nW, i_bSet);
1597}
1598
1599static tools::Long findBitRun(const Scanline i_pLine, tools::Long i_nStartIndex, tools::Long i_nW)
1600{
1601 if (i_nStartIndex < 0)
1602 return i_nW;
1603
1604 const bool bSet = i_nStartIndex < i_nW && isSet(i_pLine, i_nStartIndex);
1605
1606 return findBitRunImpl(i_pLine, i_nStartIndex, i_nW, bSet);
1607}
1608
1610{
1612 sal_uInt32 mnNextBitPos;
1613
1615 : mnBuffer( 0 )
1616 , mnNextBitPos( 8 )
1617 {
1618 }
1619
1620 const sal_uInt8& getByte() const { return mnBuffer; }
1621 void flush() { mnNextBitPos = 8; mnBuffer = 0; }
1622};
1623
1624void PDFWriterImpl::putG4Bits( sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState& io_rState )
1625{
1626 while( i_nLength > io_rState.mnNextBitPos )
1627 {
1628 io_rState.mnBuffer |= static_cast<sal_uInt8>( i_nCode >> (i_nLength - io_rState.mnNextBitPos) );
1629 i_nLength -= io_rState.mnNextBitPos;
1630 writeBufferBytes( &io_rState.getByte(), 1 );
1631 io_rState.flush();
1632 }
1633 assert(i_nLength < 9);
1634 static const unsigned int msbmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
1635 io_rState.mnBuffer |= static_cast<sal_uInt8>( (i_nCode & msbmask[i_nLength]) << (io_rState.mnNextBitPos - i_nLength) );
1636 io_rState.mnNextBitPos -= i_nLength;
1637 if( io_rState.mnNextBitPos == 0 )
1638 {
1639 writeBufferBytes( &io_rState.getByte(), 1 );
1640 io_rState.flush();
1641 }
1642}
1643
1644namespace {
1645
1646struct PixelCode
1647{
1648 sal_uInt32 mnEncodedPixels;
1649 sal_uInt32 mnCodeBits;
1650 sal_uInt32 mnCode;
1651};
1652
1653}
1654
1655const PixelCode WhitePixelCodes[] =
1656{
1657 { 0, 8, 0x35 }, // 0011 0101
1658 { 1, 6, 0x7 }, // 0001 11
1659 { 2, 4, 0x7 }, // 0111
1660 { 3, 4, 0x8 }, // 1000
1661 { 4, 4, 0xB }, // 1011
1662 { 5, 4, 0xC }, // 1100
1663 { 6, 4, 0xE }, // 1110
1664 { 7, 4, 0xF }, // 1111
1665 { 8, 5, 0x13 }, // 1001 1
1666 { 9, 5, 0x14 }, // 1010 0
1667 { 10, 5, 0x7 }, // 0011 1
1668 { 11, 5, 0x8 }, // 0100 0
1669 { 12, 6, 0x8 }, // 0010 00
1670 { 13, 6, 0x3 }, // 0000 11
1671 { 14, 6, 0x34 }, // 1101 00
1672 { 15, 6, 0x35 }, // 1101 01
1673 { 16, 6, 0x2A }, // 1010 10
1674 { 17, 6, 0x2B }, // 1010 11
1675 { 18, 7, 0x27 }, // 0100 111
1676 { 19, 7, 0xC }, // 0001 100
1677 { 20, 7, 0x8 }, // 0001 000
1678 { 21, 7, 0x17 }, // 0010 111
1679 { 22, 7, 0x3 }, // 0000 011
1680 { 23, 7, 0x4 }, // 0000 100
1681 { 24, 7, 0x28 }, // 0101 000
1682 { 25, 7, 0x2B }, // 0101 011
1683 { 26, 7, 0x13 }, // 0010 011
1684 { 27, 7, 0x24 }, // 0100 100
1685 { 28, 7, 0x18 }, // 0011 000
1686 { 29, 8, 0x2 }, // 0000 0010
1687 { 30, 8, 0x3 }, // 0000 0011
1688 { 31, 8, 0x1A }, // 0001 1010
1689 { 32, 8, 0x1B }, // 0001 1011
1690 { 33, 8, 0x12 }, // 0001 0010
1691 { 34, 8, 0x13 }, // 0001 0011
1692 { 35, 8, 0x14 }, // 0001 0100
1693 { 36, 8, 0x15 }, // 0001 0101
1694 { 37, 8, 0x16 }, // 0001 0110
1695 { 38, 8, 0x17 }, // 0001 0111
1696 { 39, 8, 0x28 }, // 0010 1000
1697 { 40, 8, 0x29 }, // 0010 1001
1698 { 41, 8, 0x2A }, // 0010 1010
1699 { 42, 8, 0x2B }, // 0010 1011
1700 { 43, 8, 0x2C }, // 0010 1100
1701 { 44, 8, 0x2D }, // 0010 1101
1702 { 45, 8, 0x4 }, // 0000 0100
1703 { 46, 8, 0x5 }, // 0000 0101
1704 { 47, 8, 0xA }, // 0000 1010
1705 { 48, 8, 0xB }, // 0000 1011
1706 { 49, 8, 0x52 }, // 0101 0010
1707 { 50, 8, 0x53 }, // 0101 0011
1708 { 51, 8, 0x54 }, // 0101 0100
1709 { 52, 8, 0x55 }, // 0101 0101
1710 { 53, 8, 0x24 }, // 0010 0100
1711 { 54, 8, 0x25 }, // 0010 0101
1712 { 55, 8, 0x58 }, // 0101 1000
1713 { 56, 8, 0x59 }, // 0101 1001
1714 { 57, 8, 0x5A }, // 0101 1010
1715 { 58, 8, 0x5B }, // 0101 1011
1716 { 59, 8, 0x4A }, // 0100 1010
1717 { 60, 8, 0x4B }, // 0100 1011
1718 { 61, 8, 0x32 }, // 0011 0010
1719 { 62, 8, 0x33 }, // 0011 0011
1720 { 63, 8, 0x34 }, // 0011 0100
1721 { 64, 5, 0x1B }, // 1101 1
1722 { 128, 5, 0x12 }, // 1001 0
1723 { 192, 6, 0x17 }, // 0101 11
1724 { 256, 7, 0x37 }, // 0110 111
1725 { 320, 8, 0x36 }, // 0011 0110
1726 { 384, 8, 0x37 }, // 0011 0111
1727 { 448, 8, 0x64 }, // 0110 0100
1728 { 512, 8, 0x65 }, // 0110 0101
1729 { 576, 8, 0x68 }, // 0110 1000
1730 { 640, 8, 0x67 }, // 0110 0111
1731 { 704, 9, 0xCC }, // 0110 0110 0
1732 { 768, 9, 0xCD }, // 0110 0110 1
1733 { 832, 9, 0xD2 }, // 0110 1001 0
1734 { 896, 9, 0xD3 }, // 0110 1001 1
1735 { 960, 9, 0xD4 }, // 0110 1010 0
1736 { 1024, 9, 0xD5 }, // 0110 1010 1
1737 { 1088, 9, 0xD6 }, // 0110 1011 0
1738 { 1152, 9, 0xD7 }, // 0110 1011 1
1739 { 1216, 9, 0xD8 }, // 0110 1100 0
1740 { 1280, 9, 0xD9 }, // 0110 1100 1
1741 { 1344, 9, 0xDA }, // 0110 1101 0
1742 { 1408, 9, 0xDB }, // 0110 1101 1
1743 { 1472, 9, 0x98 }, // 0100 1100 0
1744 { 1536, 9, 0x99 }, // 0100 1100 1
1745 { 1600, 9, 0x9A }, // 0100 1101 0
1746 { 1664, 6, 0x18 }, // 0110 00
1747 { 1728, 9, 0x9B }, // 0100 1101 1
1748 { 1792, 11, 0x8 }, // 0000 0001 000
1749 { 1856, 11, 0xC }, // 0000 0001 100
1750 { 1920, 11, 0xD }, // 0000 0001 101
1751 { 1984, 12, 0x12 }, // 0000 0001 0010
1752 { 2048, 12, 0x13 }, // 0000 0001 0011
1753 { 2112, 12, 0x14 }, // 0000 0001 0100
1754 { 2176, 12, 0x15 }, // 0000 0001 0101
1755 { 2240, 12, 0x16 }, // 0000 0001 0110
1756 { 2304, 12, 0x17 }, // 0000 0001 0111
1757 { 2368, 12, 0x1C }, // 0000 0001 1100
1758 { 2432, 12, 0x1D }, // 0000 0001 1101
1759 { 2496, 12, 0x1E }, // 0000 0001 1110
1760 { 2560, 12, 0x1F } // 0000 0001 1111
1761};
1762
1763const PixelCode BlackPixelCodes[] =
1764{
1765 { 0, 10, 0x37 }, // 0000 1101 11
1766 { 1, 3, 0x2 }, // 010
1767 { 2, 2, 0x3 }, // 11
1768 { 3, 2, 0x2 }, // 10
1769 { 4, 3, 0x3 }, // 011
1770 { 5, 4, 0x3 }, // 0011
1771 { 6, 4, 0x2 }, // 0010
1772 { 7, 5, 0x3 }, // 0001 1
1773 { 8, 6, 0x5 }, // 0001 01
1774 { 9, 6, 0x4 }, // 0001 00
1775 { 10, 7, 0x4 }, // 0000 100
1776 { 11, 7, 0x5 }, // 0000 101
1777 { 12, 7, 0x7 }, // 0000 111
1778 { 13, 8, 0x4 }, // 0000 0100
1779 { 14, 8, 0x7 }, // 0000 0111
1780 { 15, 9, 0x18 }, // 0000 1100 0
1781 { 16, 10, 0x17 }, // 0000 0101 11
1782 { 17, 10, 0x18 }, // 0000 0110 00
1783 { 18, 10, 0x8 }, // 0000 0010 00
1784 { 19, 11, 0x67 }, // 0000 1100 111
1785 { 20, 11, 0x68 }, // 0000 1101 000
1786 { 21, 11, 0x6C }, // 0000 1101 100
1787 { 22, 11, 0x37 }, // 0000 0110 111
1788 { 23, 11, 0x28 }, // 0000 0101 000
1789 { 24, 11, 0x17 }, // 0000 0010 111
1790 { 25, 11, 0x18 }, // 0000 0011 000
1791 { 26, 12, 0xCA }, // 0000 1100 1010
1792 { 27, 12, 0xCB }, // 0000 1100 1011
1793 { 28, 12, 0xCC }, // 0000 1100 1100
1794 { 29, 12, 0xCD }, // 0000 1100 1101
1795 { 30, 12, 0x68 }, // 0000 0110 1000
1796 { 31, 12, 0x69 }, // 0000 0110 1001
1797 { 32, 12, 0x6A }, // 0000 0110 1010
1798 { 33, 12, 0x6B }, // 0000 0110 1011
1799 { 34, 12, 0xD2 }, // 0000 1101 0010
1800 { 35, 12, 0xD3 }, // 0000 1101 0011
1801 { 36, 12, 0xD4 }, // 0000 1101 0100
1802 { 37, 12, 0xD5 }, // 0000 1101 0101
1803 { 38, 12, 0xD6 }, // 0000 1101 0110
1804 { 39, 12, 0xD7 }, // 0000 1101 0111
1805 { 40, 12, 0x6C }, // 0000 0110 1100
1806 { 41, 12, 0x6D }, // 0000 0110 1101
1807 { 42, 12, 0xDA }, // 0000 1101 1010
1808 { 43, 12, 0xDB }, // 0000 1101 1011
1809 { 44, 12, 0x54 }, // 0000 0101 0100
1810 { 45, 12, 0x55 }, // 0000 0101 0101
1811 { 46, 12, 0x56 }, // 0000 0101 0110
1812 { 47, 12, 0x57 }, // 0000 0101 0111
1813 { 48, 12, 0x64 }, // 0000 0110 0100
1814 { 49, 12, 0x65 }, // 0000 0110 0101
1815 { 50, 12, 0x52 }, // 0000 0101 0010
1816 { 51, 12, 0x53 }, // 0000 0101 0011
1817 { 52, 12, 0x24 }, // 0000 0010 0100
1818 { 53, 12, 0x37 }, // 0000 0011 0111
1819 { 54, 12, 0x38 }, // 0000 0011 1000
1820 { 55, 12, 0x27 }, // 0000 0010 0111
1821 { 56, 12, 0x28 }, // 0000 0010 1000
1822 { 57, 12, 0x58 }, // 0000 0101 1000
1823 { 58, 12, 0x59 }, // 0000 0101 1001
1824 { 59, 12, 0x2B }, // 0000 0010 1011
1825 { 60, 12, 0x2C }, // 0000 0010 1100
1826 { 61, 12, 0x5A }, // 0000 0101 1010
1827 { 62, 12, 0x66 }, // 0000 0110 0110
1828 { 63, 12, 0x67 }, // 0000 0110 0111
1829 { 64, 10, 0xF }, // 0000 0011 11
1830 { 128, 12, 0xC8 }, // 0000 1100 1000
1831 { 192, 12, 0xC9 }, // 0000 1100 1001
1832 { 256, 12, 0x5B }, // 0000 0101 1011
1833 { 320, 12, 0x33 }, // 0000 0011 0011
1834 { 384, 12, 0x34 }, // 0000 0011 0100
1835 { 448, 12, 0x35 }, // 0000 0011 0101
1836 { 512, 13, 0x6C }, // 0000 0011 0110 0
1837 { 576, 13, 0x6D }, // 0000 0011 0110 1
1838 { 640, 13, 0x4A }, // 0000 0010 0101 0
1839 { 704, 13, 0x4B }, // 0000 0010 0101 1
1840 { 768, 13, 0x4C }, // 0000 0010 0110 0
1841 { 832, 13, 0x4D }, // 0000 0010 0110 1
1842 { 896, 13, 0x72 }, // 0000 0011 1001 0
1843 { 960, 13, 0x73 }, // 0000 0011 1001 1
1844 { 1024, 13, 0x74 }, // 0000 0011 1010 0
1845 { 1088, 13, 0x75 }, // 0000 0011 1010 1
1846 { 1152, 13, 0x76 }, // 0000 0011 1011 0
1847 { 1216, 13, 0x77 }, // 0000 0011 1011 1
1848 { 1280, 13, 0x52 }, // 0000 0010 1001 0
1849 { 1344, 13, 0x53 }, // 0000 0010 1001 1
1850 { 1408, 13, 0x54 }, // 0000 0010 1010 0
1851 { 1472, 13, 0x55 }, // 0000 0010 1010 1
1852 { 1536, 13, 0x5A }, // 0000 0010 1101 0
1853 { 1600, 13, 0x5B }, // 0000 0010 1101 1
1854 { 1664, 13, 0x64 }, // 0000 0011 0010 0
1855 { 1728, 13, 0x65 }, // 0000 0011 0010 1
1856 { 1792, 11, 0x8 }, // 0000 0001 000
1857 { 1856, 11, 0xC }, // 0000 0001 100
1858 { 1920, 11, 0xD }, // 0000 0001 101
1859 { 1984, 12, 0x12 }, // 0000 0001 0010
1860 { 2048, 12, 0x13 }, // 0000 0001 0011
1861 { 2112, 12, 0x14 }, // 0000 0001 0100
1862 { 2176, 12, 0x15 }, // 0000 0001 0101
1863 { 2240, 12, 0x16 }, // 0000 0001 0110
1864 { 2304, 12, 0x17 }, // 0000 0001 0111
1865 { 2368, 12, 0x1C }, // 0000 0001 1100
1866 { 2432, 12, 0x1D }, // 0000 0001 1101
1867 { 2496, 12, 0x1E }, // 0000 0001 1110
1868 { 2560, 12, 0x1F } // 0000 0001 1111
1869};
1870
1871void PDFWriterImpl::putG4Span( tools::Long i_nSpan, bool i_bWhitePixel, BitStreamState& io_rState )
1872{
1873 const PixelCode* pTable = i_bWhitePixel ? WhitePixelCodes : BlackPixelCodes;
1874 // maximum encoded span is 2560 consecutive pixels
1875 while( i_nSpan > 2623 )
1876 {
1877 // write 2560 bits, that is entry (63 + (2560 >> 6)) == 103 in the appropriate table
1878 putG4Bits( pTable[103].mnCodeBits, pTable[103].mnCode, io_rState );
1879 i_nSpan -= pTable[103].mnEncodedPixels;
1880 }
1881 // write multiples of 64 pixels up to 2560
1882 if( i_nSpan > 63 )
1883 {
1884 sal_uInt32 nTabIndex = 63 + (i_nSpan >> 6);
1885 OSL_ASSERT( pTable[nTabIndex].mnEncodedPixels == static_cast<sal_uInt32>(64*(i_nSpan >> 6)) );
1886 putG4Bits( pTable[nTabIndex].mnCodeBits, pTable[nTabIndex].mnCode, io_rState );
1887 i_nSpan -= pTable[nTabIndex].mnEncodedPixels;
1888 }
1889 putG4Bits( pTable[i_nSpan].mnCodeBits, pTable[i_nSpan].mnCode, io_rState );
1890}
1891
1893{
1894 tools::Long nW = i_pBitmap->Width();
1895 tools::Long nH = i_pBitmap->Height();
1896 if( nW <= 0 || nH <= 0 )
1897 return;
1898 if( i_pBitmap->GetBitCount() != 1 )
1899 return;
1900
1901 BitStreamState aBitState;
1902
1903 // the first reference line is virtual and completely empty
1904 std::unique_ptr<sal_uInt8[]> pFirstRefLine(new sal_uInt8[nW/8 + 1]);
1905 memset(pFirstRefLine.get(), 0, nW/8 + 1);
1906 Scanline pRefLine = pFirstRefLine.get();
1907 for( tools::Long nY = 0; nY < nH; nY++ )
1908 {
1909 const Scanline pCurLine = i_pBitmap->GetScanline( nY );
1910 tools::Long nLineIndex = 0;
1911 bool bRunSet = (*pCurLine & 0x80) != 0;
1912 bool bRefSet = (*pRefLine & 0x80) != 0;
1913 tools::Long nRunIndex1 = bRunSet ? 0 : findBitRun( pCurLine, 0, nW, bRunSet );
1914 tools::Long nRefIndex1 = bRefSet ? 0 : findBitRun( pRefLine, 0, nW, bRefSet );
1915 for( ; nLineIndex < nW; )
1916 {
1917 tools::Long nRefIndex2 = findBitRun( pRefLine, nRefIndex1, nW );
1918 if( nRefIndex2 >= nRunIndex1 )
1919 {
1920 tools::Long nDiff = nRefIndex1 - nRunIndex1;
1921 if( -3 <= nDiff && nDiff <= 3 )
1922 { // vertical coding
1923 static const struct
1924 {
1925 sal_uInt32 mnCodeBits;
1926 sal_uInt32 mnCode;
1927 } VerticalCodes[7] = {
1928 { 7, 0x03 }, // 0000 011
1929 { 6, 0x03 }, // 0000 11
1930 { 3, 0x03 }, // 011
1931 { 1, 0x1 }, // 1
1932 { 3, 0x2 }, // 010
1933 { 6, 0x02 }, // 0000 10
1934 { 7, 0x02 } // 0000 010
1935 };
1936 // convert to index
1937 nDiff += 3;
1938
1939 // emit diff code
1940 putG4Bits( VerticalCodes[nDiff].mnCodeBits, VerticalCodes[nDiff].mnCode, aBitState );
1941 nLineIndex = nRunIndex1;
1942 }
1943 else
1944 { // difference too large, horizontal coding
1945 // emit horz code 001
1946 putG4Bits( 3, 0x1, aBitState );
1947 tools::Long nRunIndex2 = findBitRun( pCurLine, nRunIndex1, nW );
1948 bool bWhiteFirst = ( nLineIndex + nRunIndex1 == 0 || ! isSet( pCurLine, nLineIndex ) );
1949 putG4Span( nRunIndex1 - nLineIndex, bWhiteFirst, aBitState );
1950 putG4Span( nRunIndex2 - nRunIndex1, ! bWhiteFirst, aBitState );
1951 nLineIndex = nRunIndex2;
1952 }
1953 }
1954 else
1955 { // emit pass code 0001
1956 putG4Bits( 4, 0x1, aBitState );
1957 nLineIndex = nRefIndex2;
1958 }
1959 if( nLineIndex < nW )
1960 {
1961 bool bSet = isSet( pCurLine, nLineIndex );
1962 nRunIndex1 = findBitRun( pCurLine, nLineIndex, nW, bSet );
1963 nRefIndex1 = findBitRun( pRefLine, nLineIndex, nW, ! bSet );
1964 nRefIndex1 = findBitRun( pRefLine, nRefIndex1, nW, bSet );
1965 }
1966 }
1967
1968 // the current line is the reference for the next line
1969 pRefLine = pCurLine;
1970 }
1971 // terminate strip with EOFB
1972 putG4Bits( 12, 1, aBitState );
1973 putG4Bits( 12, 1, aBitState );
1974 if( aBitState.mnNextBitPos != 8 )
1975 {
1976 writeBufferBytes( &aBitState.getByte(), 1 );
1977 aBitState.flush();
1978 }
1979}
1980
1981void PDFWriterImpl::DrawHatchLine_DrawLine(const Point& rStartPoint, const Point& rEndPoint)
1982{
1983 drawLine(rStartPoint, rEndPoint);
1984}
1985
1986static bool lcl_canUsePDFAxialShading(const Gradient& rGradient) {
1987 switch (rGradient.GetStyle())
1988 {
1989 case css::awt::GradientStyle_LINEAR:
1990 case css::awt::GradientStyle_AXIAL:
1991 break;
1992 default:
1993 return false;
1994 }
1995
1996 // TODO: handle step count
1997 return rGradient.GetSteps() <= 0;
1998}
1999
2000void PDFWriterImpl::ImplClearFontData(bool bNewFontLists)
2001{
2002 VirtualDevice::ImplClearFontData(bNewFontLists);
2003 if (bNewFontLists && AcquireGraphics())
2004 {
2007 }
2008}
2009
2011{
2012 if (bNewFontLists && AcquireGraphics())
2013 {
2016 }
2017}
2018
2020{
2021 return aRegion;
2022}
2023
2024
2025/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
Reference< XInputStream > xStream
void BlendWith(const AlphaMask &rOther)
Definition: alpha.cxx:88
const AlphaMask & GetAlphaMask() const
Definition: bitmapex.hxx:71
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:305
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: BitmapEx.cxx:383
bool IsAlpha() const
Definition: BitmapEx.cxx:207
BitmapChecksum GetChecksum() const
Definition: BitmapEx.cxx:239
bool IsEmpty() const
Definition: BitmapEx.cxx:186
bool Mirror(BmpMirrorFlags nMirrorFlags)
Mirror the bitmap.
Definition: BitmapEx.cxx:268
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:217
const MapMode & GetPrefMapMode() const
Definition: bitmapex.hxx:79
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:363
const Size & GetPrefSize() const
Definition: bitmapex.hxx:76
const Size & GetSizePixel() const
Definition: bitmapex.hxx:73
void SetEmpty()
Definition: BitmapEx.cxx:191
tools::Long Height() const
tools::Long Width() const
sal_uInt16 GetBitCount() const
Scanline GetScanline(tools::Long nY) const
bool Invert()
Perform the Invert operation on every pixel.
Definition: bitmappaint.cxx:61
sal_uInt8 GetLuminance() const
static std::map< sal_IntPtr, EncHashTransporter * > sTransporters
virtual uno::Any SAL_CALL getMaterial() override
std::vector< sal_uInt8 > maOValue
virtual ~EncHashTransporter() override
::std::unique_ptr<::comphelper::Hash > m_pDigest
static EncHashTransporter * getEncHashTransporter(const uno::Reference< beans::XMaterialHolder > &)
std::vector< sal_uInt8 > & getOValue()
::comphelper::Hash * getUDigest()
size_t GetActionSize() const
Definition: gdimtf.cxx:181
void Move(tools::Long nX, tools::Long nY)
Definition: gdimtf.cxx:653
void WindStart()
Definition: gdimtf.cxx:572
void Scale(double fScaleX, double fScaleY)
Definition: gdimtf.cxx:748
const Size & GetPrefSize() const
Definition: gdimtf.hxx:176
MetaAction * GetAction(size_t nAction) const
Definition: gdimtf.cxx:186
void Play(GDIMetaFile &rMtf)
Definition: gdimtf.cxx:325
void SetPrefMapMode(const MapMode &rMapMode)
Definition: gdimtf.hxx:180
const MapMode & GetPrefMapMode() const
Definition: gdimtf.hxx:179
void AddGradientActions(tools::Rectangle const &rRect, GDIMetaFile &rMetaFile)
const Color & GetEndColor() const
const Color & GetStartColor() const
css::awt::GradientStyle GetStyle() const
sal_uInt16 GetSteps() const
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
Definition: graph.cxx:350
GraphicType GetType() const
Definition: graph.cxx:294
GfxLink GetGfxLink() const
Definition: graph.cxx:510
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
void SetOrigin(const Point &rOrigin)
Definition: mapmod.cxx:138
void SetScaleY(const Fraction &rScaleY)
Definition: mapmod.cxx:150
const Point & GetOrigin() const
Definition: mapmod.cxx:183
void SetScaleX(const Fraction &rScaleX)
Definition: mapmod.cxx:144
MetaActionType GetType() const
Definition: metaact.hxx:96
const Point & GetStartPoint() const
Definition: metaact.hxx:308
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:307
const Point & GetEndPoint() const
Definition: metaact.hxx:309
const Bitmap & GetBitmap() const
Definition: metaact.hxx:693
const Point & GetPoint() const
Definition: metaact.hxx:694
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:798
const Point & GetPoint() const
Definition: metaact.hxx:799
const Size & GetSize() const
Definition: metaact.hxx:833
const Point & GetPoint() const
Definition: metaact.hxx:832
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:831
const Point & GetSrcPoint() const
Definition: metaact.hxx:872
const Size & GetDestSize() const
Definition: metaact.hxx:871
const Point & GetDestPoint() const
Definition: metaact.hxx:870
const Size & GetSrcSize() const
Definition: metaact.hxx:873
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:869
const Point & GetPoint() const
Definition: metaact.hxx:726
const Size & GetSize() const
Definition: metaact.hxx:727
const Bitmap & GetBitmap() const
Definition: metaact.hxx:725
const Bitmap & GetBitmap() const
Definition: metaact.hxx:762
const Point & GetDestPoint() const
Definition: metaact.hxx:763
const Point & GetSrcPoint() const
Definition: metaact.hxx:765
const Size & GetSrcSize() const
Definition: metaact.hxx:766
const Size & GetDestSize() const
Definition: metaact.hxx:764
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:375
const Point & GetStartPoint() const
Definition: metaact.hxx:376
const Point & GetEndPoint() const
Definition: metaact.hxx:377
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1142
bool IsClipping() const
Definition: metaact.hxx:1143
const sal_uInt8 * GetData() const
Definition: metaact.hxx:1712
const OString & GetComment() const
Definition: metaact.hxx:1709
sal_uInt32 GetDataSize() const
Definition: metaact.hxx:1711
const GDIMetaFile & GetSubstitute() const
Definition: metaact.hxx:1647
const Point & GetPoint() const
Definition: metaact.hxx:1648
const Size & GetSize() const
Definition: metaact.hxx:1649
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:277
const Color & GetColor() const
Definition: metaact.hxx:1279
bool IsSetting() const
Definition: metaact.hxx:1280
const Gradient & GetGradient() const
Definition: metaact.hxx:1606
const Size & GetSize() const
Definition: metaact.hxx:1605
const GDIMetaFile & GetGDIMetaFile() const
Definition: metaact.hxx:1603
const Point & GetPoint() const
Definition: metaact.hxx:1604
const vcl::Font & GetFont() const
Definition: metaact.hxx:1472
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1022
const Gradient & GetGradient() const
Definition: metaact.hxx:1023
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1052
const Gradient & GetGradient() const
Definition: metaact.hxx:1053
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1082
const Hatch & GetHatch() const
Definition: metaact.hxx:1083
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1171
const vcl::Region & GetRegion() const
Definition: metaact.hxx:1198
vcl::text::ComplexTextLayoutFlags GetLayoutMode() const
Definition: metaact.hxx:1739
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:187
const Point & GetEndPoint() const
Definition: metaact.hxx:186
const Point & GetStartPoint() const
Definition: metaact.hxx:185
bool IsSetting() const
Definition: metaact.hxx:1253
const Color & GetColor() const
Definition: metaact.hxx:1252
tools::Long GetVertMove() const
Definition: metaact.hxx:1226
tools::Long GetHorzMove() const
Definition: metaact.hxx:1225
const Color & GetColor() const
Definition: metaact.hxx:1386
bool IsSetting() const
Definition: metaact.hxx:1389
const Point & GetPoint() const
Definition: metaact.hxx:126
const Color & GetColor() const
Definition: metaact.hxx:127
const Point & GetPoint() const
Definition: metaact.hxx:154
const LineInfo & GetLineInfo() const
Definition: metaact.hxx:409
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:408
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:464
const tools::Polygon & GetPolygon() const
Definition: metaact.hxx:437
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1497
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:216
sal_uInt32 GetHorzRound() const
Definition: metaact.hxx:247
sal_uInt32 GetVertRound() const
Definition: metaact.hxx:248
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:246
sal_uInt32 GetWidth() const
Definition: metaact.hxx:584
sal_Int32 GetLen() const
Definition: metaact.hxx:586
sal_Int32 GetIndex() const
Definition: metaact.hxx:585
const OUString & GetText() const
Definition: metaact.hxx:583
const Point & GetPoint() const
Definition: metaact.hxx:582
const Point & GetPoint() const
Definition: metaact.hxx:495
sal_Int32 GetLen() const
Definition: metaact.hxx:498
const OUString & GetText() const
Definition: metaact.hxx:496
sal_Int32 GetIndex() const
Definition: metaact.hxx:497
TextAlign GetTextAlign() const
Definition: metaact.hxx:1412
sal_Int32 GetIndex() const
Definition: metaact.hxx:541
const KernArray & GetDXArray() const
Definition: metaact.hxx:543
sal_Int32 GetLen() const
Definition: metaact.hxx:542
const OUString & GetText() const
Definition: metaact.hxx:540
const Point & GetPoint() const
Definition: metaact.hxx:539
const std::vector< sal_Bool > & GetKashidaArray() const
Definition: metaact.hxx:544
const Color & GetColor() const
Definition: metaact.hxx:1306
bool IsSetting() const
Definition: metaact.hxx:1334
const Color & GetColor() const
Definition: metaact.hxx:1331
LanguageType GetTextLanguage() const
Definition: metaact.hxx:1763
const Point & GetStartPoint() const
Definition: metaact.hxx:657
tools::Long GetWidth() const
Definition: metaact.hxx:658
FontLineStyle GetUnderline() const
Definition: metaact.hxx:660
FontLineStyle GetOverline() const
Definition: metaact.hxx:661
FontStrikeout GetStrikeout() const
Definition: metaact.hxx:659
bool IsSetting() const
Definition: metaact.hxx:1362
const Color & GetColor() const
Definition: metaact.hxx:1359
DrawTextFlags GetStyle() const
Definition: metaact.hxx:622
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:620
const OUString & GetText() const
Definition: metaact.hxx:621
sal_uInt16 GetTransparence() const
Definition: metaact.hxx:1566
const tools::PolyPolygon & GetPolyPolygon() const
Definition: metaact.hxx:1565
const Wallpaper & GetWallpaper() const
Definition: metaact.hxx:1114
const tools::Rectangle & GetRect() const
Definition: metaact.hxx:1113
void EnableOutput(bool bEnable=true)
Definition: outdev.cxx:341
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1110
void ReleaseFontCollection()
void ResetNewFontCache()
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1580
void SetMapMode()
Definition: map.cxx:597
virtual void ImplClearFontData(bool bNewFontLists)
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:879
const MapMode & GetMapMode() const
Definition: outdev.hxx:1557
void ReleaseFontCache()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:32
void Pop()
Definition: stack.cxx:91
void SetFontCollectionFromSVData()
constexpr tools::Long Y() const
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
void disposeAndReset(reference_type *pBody)
Assignment that releases the last reference.
Definition: vclptr.hxx:316
constexpr tools::Long getHeight() const
constexpr tools::Long Height() const
constexpr tools::Long getWidth() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
virtual sal_uInt64 TellEnd() override
void SetCompressMode(SvStreamCompressFlags nNewMode)
SvStreamCompressFlags GetCompressMode() const
void SetVersion(sal_Int32 n)
Encapsulates geometry and associated attributes of a filled area.
FillRule getFillRule() const
Get fill rule used.
@ fillEvenOdd
Even-odd fill rule.
double getTransparency() const
Get stroke transparency.
FillType getFillType() const
Get fill type used.
void getPath(tools::PolyPolygon &) const
Query path to fill.
@ fillSolid
Fill with a specified solid color.
Encapsulates geometry and associated attributes of a graphical 'pen stroke'.
double getMiterLimit() const
Get the maximum length of mitered joins.
void getPath(tools::Polygon &) const
Query path to stroke.
void getStartArrow(tools::PolyPolygon &) const
Get the polygon that is put at the start of the line.
JoinType getJoinType() const
Get the style in which the stroke segments are joined.
void getEndArrow(tools::PolyPolygon &) const
Get the polygon that is put at the end of the line.
void getDashArray(DashArray &) const
Get an array of "on" and "off" lengths for stroke dashing.
@ capRound
Half-round cap at the line end, the center lying at the end point.
@ capButt
No additional cap.
@ capSquare
Half-square cap at the line end, the center lying at the end point.
double getTransparency() const
Get stroke transparency.
CapType getCapType() const
Get the style in which open stroke ends are drawn.
double getStrokeWidth() const
Get width of the stroke.
::std::vector< double > DashArray
@ joinBevel
Connect segments by a direct straight line.
@ joinNone
Perform no join, leads to visible gaps between thick line segments.
@ joinRound
Connect segments by a filled round arc.
@ joinMiter
Extend segment edges, until they cross.
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: vclptr.hxx:58
void disposeAndClear()
Definition: vclptr.hxx:200
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
virtual bool AcquireGraphics() const override
Acquire a graphics device that the output device uses to draw on.
Definition: virdev.cxx:47
std::vector< unsigned char > finalize()
static std::vector< unsigned char > calculateHash(const unsigned char *pInput, size_t length, HashType eType)
void update(const unsigned char *pInput, size_t length)
void insert(key_value_pair_t &rPair)
list_const_iterator_t end() const
list_const_iterator_t find(const Key &key)
sal_uInt16 Count() const
::basegfx::B2DPolyPolygon getB2DPolyPolygon() const
tools::Rectangle GetBoundRect() const
PolyFlags GetFlags(sal_uInt16 nPos) const
const Point * GetConstPointAry() const
bool HasFlags() const
sal_uInt16 GetSize() const
const PolyFlags * GetConstFlagAry() const
bool PlaySyncPageAct(PDFWriter &rWriter, sal_uInt32 &rCurGDIMtfAction, const GDIMetaFile &rMtf)
const Graphic & GetCurrentGraphic() const
static bool computeODictionaryValue(const sal_uInt8 *i_pPaddedOwnerPassword, const sal_uInt8 *i_pPaddedUserPassword, std::vector< sal_uInt8 > &io_rOValue, sal_Int32 i_nKeyLength)
void putG4Bits(sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState &io_rState)
void enableStringEncryption(sal_Int32 nObject)
void ImplRefreshFontData(bool bNewFontLists) override
static css::uno::Reference< css::beans::XMaterialHolder > initEncryption(const OUString &i_rOwnerPassword, const OUString &i_rUserPassword)
static void padPassword(std::u16string_view i_rPassword, sal_uInt8 *o_pPaddedPW)
static sal_Int32 computeAccessPermissions(const vcl::PDFWriter::PDFEncryptionProperties &i_rProperties, sal_Int32 &o_rKeyLength, sal_Int32 &o_rRC4KeyLength)
static bool computeEncryptionKey(EncHashTransporter *, vcl::PDFWriter::PDFEncryptionProperties &io_rProperties, sal_Int32 i_nAccessPermissions)
void DrawHatchLine_DrawLine(const Point &rStartPoint, const Point &rEndPoint) override
void writeG4Stream(BitmapReadAccess const *i_pBitmap)
PDFWriter::PDFWriterContext m_aContext
void checkAndEnableStreamEncryption(sal_Int32 nObject) override
void ImplClearFontData(bool bNewFontLists) override
bool writeBufferBytes(const void *pBuffer, sal_uInt64 nBytes) override
See vcl::PDFObjectContainer::writeBuffer().
o3tl::lru_map< BitmapChecksum, std::shared_ptr< SvMemoryStream > > m_aPDFBmpCache
Cache some most recent bitmaps we've exported, in case we encounter them again..
void playMetafile(const GDIMetaFile &, vcl::PDFExtOutDevData *, const vcl::PDFWriter::PlayMetafileContext &, VirtualDevice *pDummyDev=nullptr)
void implWriteGradient(const tools::PolyPolygon &rPolyPoly, const Gradient &rGradient, VirtualDevice *pDummyVDev, const vcl::PDFWriter::PlayMetafileContext &)
void drawLine(const Point &rStart, const Point &rStop)
void putG4Span(tools::Long i_nSpan, bool i_bWhitePixel, BitStreamState &io_rState)
bool prepareEncryption(const css::uno::Reference< css::beans::XMaterialHolder > &)
vcl::Region ClipToDeviceBounds(vcl::Region aRegion) const override
Perform actual rect clip against outdev dimensions, to generate empty clips whenever one of the value...
void implWriteBitmapEx(const Point &rPoint, const Size &rSize, const BitmapEx &rBitmapEx, const Graphic &i_pGraphic, VirtualDevice const *pDummyVDev, const vcl::PDFWriter::PlayMetafileContext &)
static bool computeUDictionaryValue(EncHashTransporter *i_pTransporter, vcl::PDFWriter::PDFEncryptionProperties &io_rProperties, sal_Int32 i_nKeyLength, sal_Int32 i_nAccessPermissions)
static const sal_uInt8 s_nPadString[ENCRYPTED_PWD_SIZE]
void DrawPolygon(const tools::Polygon &rPoly)
Definition: pdfwriter.cxx:120
void DrawEllipse(const tools::Rectangle &rRect)
Definition: pdfwriter.cxx:140
void SetFillColor(const Color &rColor)
Definition: pdfwriter.cxx:248
void DrawPie(const tools::Rectangle &rRect, const Point &rStartPt, const Point &rEndPt)
Definition: pdfwriter.cxx:150
void DrawChord(const tools::Rectangle &rRect, const Point &rStartPt, const Point &rEndPt)
Definition: pdfwriter.cxx:155
void SetFont(const vcl::Font &rNewFont)
Definition: pdfwriter.cxx:61
void DrawHatch(const tools::PolyPolygon &rPolyPoly, const Hatch &rHatch)
Definition: pdfwriter.cxx:190
void SetTextAlign(::TextAlign eAlign)
Definition: pdfwriter.cxx:323
void SetTextColor(const Color &rColor)
Definition: pdfwriter.cxx:288
void DrawTextLine(const Point &rPos, tools::Long nWidth, FontStrikeout eStrikeout, FontLineStyle eUnderline, FontLineStyle eOverline)
Definition: pdfwriter.cxx:71
void SetOverlineColor()
Definition: pdfwriter.cxx:313
void DrawStretchText(const Point &rStartPt, sal_Int32 nWidth, const OUString &rStr, sal_Int32 nIndex, sal_Int32 nLen)
Definition: pdfwriter.cxx:92
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: pdfwriter.cxx:228
void DrawPolyLine(const tools::Polygon &rPoly)
Definition: pdfwriter.cxx:125
void SetTextFillColor()
Definition: pdfwriter.cxx:293
void SetDigitLanguage(LanguageType eLang)
Definition: pdfwriter.cxx:283
void BeginTransparencyGroup()
Start a transparency group.
Definition: pdfwriter.cxx:218
void DrawTextArray(const Point &rStartPt, const OUString &rStr, KernArraySpan aKernArray, o3tl::span< const sal_Bool > pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen)
Definition: pdfwriter.cxx:81
void DrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
Definition: pdfwriter.cxx:213
void DrawJPGBitmap(SvStream &rJPGData, bool bIsTrueColor, const Size &rSrcSizePixel, const tools::Rectangle &rTargetArea, const AlphaMask &rAlphaMask, const Graphic &rGraphic)
Insert a JPG encoded image (optionally with mask)
Definition: pdfwriter.cxx:328
void SetClipRegion()
Definition: pdfwriter.cxx:253
void DrawText(const Point &rPos, const OUString &rText)
Definition: pdfwriter.cxx:66
void DrawLine(const Point &rStartPt, const Point &rEndPt)
Definition: pdfwriter.cxx:110
void IntersectClipRegion(const tools::Rectangle &rRect)
Definition: pdfwriter.cxx:273
void DrawPixel(const Point &rPt, const Color &rColor)
Definition: pdfwriter.cxx:175
void DrawBitmapEx(const Point &rDestPt, const Size &rDestSize, const BitmapEx &rBitmapEx)
Definition: pdfwriter.cxx:185
void SetMapMode(const MapMode &rNewMapMode)
Definition: pdfwriter.cxx:238
void DrawRect(const tools::Rectangle &rRect)
Definition: pdfwriter.cxx:130
void SetLineColor(const Color &rColor)
Definition: pdfwriter.cxx:243
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nMode)
Definition: pdfwriter.cxx:278
void EndTransparencyGroup(const tools::Rectangle &rBoundRect, sal_uInt16 nTransparencePercent)
End a transparency group with constant transparency factor.
Definition: pdfwriter.cxx:223
void DrawBitmap(const Point &rDestPt, const Size &rDestSize, const Bitmap &rBitmap, const Graphic &rGraphic)
Definition: pdfwriter.cxx:180
void SetTextLineColor()
Definition: pdfwriter.cxx:303
void DrawGradient(const tools::Rectangle &rRect, const Gradient &rGradient)
Definition: pdfwriter.cxx:195
void MoveClipRegion(tools::Long nHorzMove, tools::Long nVertMove)
Definition: pdfwriter.cxx:263
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Definition: pdfwriter.cxx:170
void DrawArc(const tools::Rectangle &rRect, const Point &rStartPt, const Point &rEndPt)
Definition: pdfwriter.cxx:145
void DrawWallpaper(const tools::Rectangle &rRect, const Wallpaper &rWallpaper)
Definition: pdfwriter.cxx:208
basegfx::B2DPolyPolygon GetAsB2DPolyPolygon() const
Definition: region.cxx:1294
bool IsEmpty() const
Definition: region.cxx:229
int nCount
bool WriteDIBBitmapEx(const BitmapEx &rSource, SvStream &rOStm)
Definition: dibtools.cxx:1742
float y
#define SOFFICE_FILEFORMAT_40
DocumentType eType
SvStream & ReadSvtGraphicStroke(SvStream &rIStm, SvtGraphicStroke &rClass)
SvStream & ReadSvtGraphicFill(SvStream &rIStm, SvtGraphicFill &rClass)
tools::Long FRound(double fVal)
BmpMirrorFlags
sal_Int32 nIndex
uno_Any a
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
MetaActionType
std::unique_ptr< sal_Int32[]> pData
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
Reference< XComponentContext > getProcessComponentContext()
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
HashType
int i
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
const ::avmedia::MediaItem * Execute(const SdrMarkView *pSdrView, SfxRequest const &rReq)
long Long
const PixelCode WhitePixelCodes[]
const PixelCode BlackPixelCodes[]
static bool lcl_canUsePDFAxialShading(const Gradient &rGradient)
static tools::Long findBitRun(const Scanline i_pLine, tools::Long i_nStartIndex, tools::Long i_nW, bool i_bSet)
static tools::Long findBitRunImpl(const Scanline i_pLine, tools::Long i_nStartIndex, tools::Long i_nW, bool i_bSet)
const tools::Long setRun[256]
const tools::Long unsetRun[256]
static bool isSet(const Scanline i_pLine, tools::Long i_nIndex)
constexpr sal_Int32 MAXIMUM_RC4_KEY_LENGTH
constexpr sal_Int32 MD5_DIGEST_SIZE
constexpr sal_Int32 ENCRYPTED_PWD_SIZE
constexpr sal_Int32 SECUR_128BIT_KEY
QPRO_FUNC_TYPE nType
#define STREAM_SEEK_TO_END
sal_uInt32 mnNextBitPos
const sal_uInt8 & getByte() const
std::vector< double > m_aDashArray
Definition: pdfwriter.hxx:100
std::vector< sal_uInt8 > UValue
Definition: pdfwriter.hxx:535
std::vector< sal_uInt8 > DocumentIdentifier
Definition: pdfwriter.hxx:537
std::vector< sal_uInt8 > EncryptionKey
Definition: pdfwriter.hxx:536
std::vector< sal_uInt8 > OValue
Definition: pdfwriter.hxx:534
PDFWriter::PDFEncryptionProperties Encryption
Definition: pdfwriter.hxx:628
PDFWriter::ColorMode ColorMode
Definition: pdfwriter.hxx:639
Play a metafile like an outputdevice would do.
Definition: pdfwriter.hxx:701
unsigned char sal_uInt8