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