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