LibreOffice Module vcl (master)  1
graphicfilter.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 <config_folders.h>
21 
22 #include <sal/log.hxx>
23 #include <osl/mutex.hxx>
26 #include <cppuhelper/implbase.hxx>
27 #include <tools/fract.hxx>
28 #include <unotools/configmgr.hxx>
29 #include <tools/stream.hxx>
30 #include <tools/urlobj.hxx>
31 #include <tools/zcodec.hxx>
32 #include <fltcall.hxx>
33 #include <vcl/salctype.hxx>
35 #include <vcl/pngwrite.hxx>
37 #include <vcl/virdev.hxx>
38 #include <impgraph.hxx>
39 #include <vcl/svapp.hxx>
40 #include <osl/file.hxx>
41 #include <vcl/graphicfilter.hxx>
42 #include <vcl/FilterConfigItem.hxx>
43 #include <vcl/wmf.hxx>
44 #include "igif/gifread.hxx"
45 #include <vcl/pdfread.hxx>
46 #include "jpeg/jpeg.hxx"
47 #include "png/png.hxx"
48 #include "ixbm/xbmread.hxx"
49 #include <filter/XpmReader.hxx>
50 #include <filter/TiffReader.hxx>
51 #include <filter/TiffWriter.hxx>
52 #include <filter/TgaReader.hxx>
53 #include <filter/PictReader.hxx>
54 #include <filter/MetReader.hxx>
55 #include <filter/RasReader.hxx>
56 #include <filter/PcxReader.hxx>
57 #include <filter/EpsReader.hxx>
58 #include <filter/EpsWriter.hxx>
59 #include <filter/PsdReader.hxx>
60 #include <filter/PcdReader.hxx>
61 #include <filter/PbmReader.hxx>
62 #include <filter/DxfReader.hxx>
63 #include <filter/GifWriter.hxx>
64 #include <filter/BmpReader.hxx>
65 #include <filter/BmpWriter.hxx>
66 #include <osl/module.hxx>
67 #include <com/sun/star/uno/Reference.h>
68 #include <com/sun/star/awt/Size.hpp>
69 #include <com/sun/star/uno/XInterface.hpp>
70 #include <com/sun/star/io/XActiveDataSource.hpp>
71 #include <com/sun/star/io/XOutputStream.hpp>
72 #include <com/sun/star/svg/XSVGWriter.hpp>
73 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
74 #include <com/sun/star/xml/sax/Writer.hpp>
76 #include <rtl/bootstrap.hxx>
77 #include <rtl/instance.hxx>
78 #include <tools/svlibrary.h>
79 #include <comphelper/string.hxx>
80 #include <unotools/ucbhelper.hxx>
81 #include <vector>
82 #include <memory>
83 #include <string_view>
84 #include <vcl/TypeSerializer.hxx>
85 
86 #include "FilterConfigCache.hxx"
88 
91 
92 typedef ::std::vector< GraphicFilter* > FilterList_impl;
93 static FilterList_impl* pFilterHdlList = nullptr;
94 
95 static ::osl::Mutex& getListMutex()
96 {
97  static ::osl::Mutex s_aListProtection;
98  return s_aListProtection;
99 }
100 
101 namespace {
102 
103 class ImpFilterOutputStream : public ::cppu::WeakImplHelper< css::io::XOutputStream >
104 {
105  SvStream& mrStm;
106 
107  virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& rData ) override
108  { mrStm.WriteBytes(rData.getConstArray(), rData.getLength()); }
109  virtual void SAL_CALL flush() override
110  { mrStm.Flush(); }
111  virtual void SAL_CALL closeOutput() override {}
112 
113 public:
114 
115  explicit ImpFilterOutputStream( SvStream& rStm ) : mrStm( rStm ) {}
116 };
117 
118 }
119 
120 // Helper functions
121 
122 sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize )
123 {
124  while ( nComp-- >= nSize )
125  {
126  sal_uLong i;
127  for ( i = 0; i < nSize; i++ )
128  {
129  if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
130  break;
131  }
132  if ( i == nSize )
133  return pSource;
134  pSource++;
135  }
136  return nullptr;
137 }
138 
139 static OUString ImpGetExtension( const OUString &rPath )
140 {
141  OUString aExt;
142  INetURLObject aURL( rPath );
143  aExt = aURL.GetFileExtension().toAsciiUpperCase();
144  return aExt;
145 }
146 
147 bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
148 {
149  sal_uInt8 sBuf[3];
150  // store number format
151  SvStreamEndian oldNumberFormat = rStream.GetEndian();
152  sal_uInt32 nOffset; // in MS documents the pict format is used without the first 512 bytes
153  for ( nOffset = 0; ( nOffset <= 512 ) && ( ( nStreamPos + nOffset + 14 ) <= nStreamLen ); nOffset += 512 )
154  {
155  short y1,x1,y2,x2;
156  bool bdBoxOk = true;
157 
158  rStream.Seek( nStreamPos + nOffset);
159  // size of the pict in version 1 pict ( 2bytes) : ignored
160  rStream.SeekRel(2);
161  // bounding box (bytes 2 -> 9)
162  rStream.SetEndian(SvStreamEndian::BIG);
163  rStream.ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 );
164  rStream.SetEndian(oldNumberFormat); // reset format
165 
166  if (x1 > x2 || y1 > y2 || // bad bdbox
167  (x1 == x2 && y1 == y2) || // 1 pixel picture
168  x2-x1 > 2048 || y2-y1 > 2048 ) // picture abnormally big
169  bdBoxOk = false;
170 
171  // read version op
172  rStream.ReadBytes(sBuf, 3);
173  // see http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Imaging_With_QuickDraw/Appendix_A.pdf
174  // normal version 2 - page A23 and A24
175  if ( sBuf[ 0 ] == 0x00 && sBuf[ 1 ] == 0x11 && sBuf[ 2 ] == 0x02)
176  return true;
177  // normal version 1 - page A25
178  else if (sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 && bdBoxOk)
179  return true;
180  }
181  return false;
182 }
183 
184 ErrCode GraphicFilter::ImpTestOrFindFormat( const OUString& rPath, SvStream& rStream, sal_uInt16& rFormat )
185 {
186  // determine or check the filter/format by reading into it
187  if( rFormat == GRFILTER_FORMAT_DONTKNOW )
188  {
189  OUString aFormatExt;
190  if (vcl::peekGraphicFormat(rStream, aFormatExt, false))
191  {
192  rFormat = pConfig->GetImportFormatNumberForExtension( aFormatExt );
193  if( rFormat != GRFILTER_FORMAT_DONTKNOW )
194  return ERRCODE_NONE;
195  }
196  // determine filter by file extension
197  if( !rPath.isEmpty() )
198  {
199  OUString aExt( ImpGetExtension( rPath ) );
200  rFormat = pConfig->GetImportFormatNumberForExtension( aExt );
201  if( rFormat != GRFILTER_FORMAT_DONTKNOW )
202  return ERRCODE_NONE;
203  }
205  }
206  else
207  {
208  OUString aTmpStr( pConfig->GetImportFormatExtension( rFormat ) );
209  aTmpStr = aTmpStr.toAsciiUpperCase();
210  if (!vcl::peekGraphicFormat(rStream, aTmpStr, true))
212  if ( pConfig->GetImportFormatExtension( rFormat ).equalsIgnoreAsciiCase( "pcd" ) )
213  {
214  sal_Int32 nBase = 2; // default Base0
215  if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base4" ) )
216  nBase = 1;
217  else if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base16" ) )
218  nBase = 0;
219  FilterConfigItem aFilterConfigItem( u"Office.Common/Filter/Graphic/Import/PCD" );
220  aFilterConfigItem.WriteInt32( "Resolution", nBase );
221  }
222  }
223 
224  return ERRCODE_NONE;
225 }
226 
227 static Graphic ImpGetScaledGraphic( const Graphic& rGraphic, FilterConfigItem& rConfigItem )
228 {
229  Graphic aGraphic;
230 
231  sal_Int32 nLogicalWidth = rConfigItem.ReadInt32( "LogicalWidth", 0 );
232  sal_Int32 nLogicalHeight = rConfigItem.ReadInt32( "LogicalHeight", 0 );
233 
234  if ( rGraphic.GetType() != GraphicType::NONE )
235  {
236  sal_Int32 nMode = rConfigItem.ReadInt32( "ExportMode", -1 );
237 
238  if ( nMode == -1 ) // the property is not there, this is possible, if the graphic filter
239  { // is called via UnoGraphicExporter and not from a graphic export Dialog
240  nMode = 0; // then we are defaulting this mode to 0
241  if ( nLogicalWidth || nLogicalHeight )
242  nMode = 2;
243  }
244 
245  Size aOriginalSize;
246  Size aPrefSize( rGraphic.GetPrefSize() );
247  MapMode aPrefMapMode( rGraphic.GetPrefMapMode() );
248  if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
249  aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MapMode(MapUnit::Map100thMM));
250  else
251  aOriginalSize = OutputDevice::LogicToLogic(aPrefSize, aPrefMapMode, MapMode(MapUnit::Map100thMM));
252  if ( !nLogicalWidth )
253  nLogicalWidth = aOriginalSize.Width();
254  if ( !nLogicalHeight )
255  nLogicalHeight = aOriginalSize.Height();
256  if( rGraphic.GetType() == GraphicType::Bitmap )
257  {
258 
259  // Resolution is set
260  if( nMode == 1 )
261  {
262  BitmapEx aBitmap( rGraphic.GetBitmapEx() );
263  MapMode aMap( MapUnit::Map100thInch );
264 
265  sal_Int32 nDPI = rConfigItem.ReadInt32( "Resolution", 75 );
266  Fraction aFrac( 1, std::clamp( nDPI, sal_Int32(75), sal_Int32(600) ) );
267 
268  aMap.SetScaleX( aFrac );
269  aMap.SetScaleY( aFrac );
270 
271  Size aOldSize = aBitmap.GetSizePixel();
272  aGraphic = rGraphic;
273  aGraphic.SetPrefMapMode( aMap );
274  aGraphic.SetPrefSize( Size( aOldSize.Width() * 100,
275  aOldSize.Height() * 100 ) );
276  }
277  // Size is set
278  else if( nMode == 2 )
279  {
280  aGraphic = rGraphic;
281  aGraphic.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
282  aGraphic.SetPrefSize( Size( nLogicalWidth, nLogicalHeight ) );
283  }
284  else
285  aGraphic = rGraphic;
286 
287  sal_Int32 nColors = rConfigItem.ReadInt32( "Color", 0 );
288  if ( nColors ) // graphic conversion necessary ?
289  {
290  BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
291  aBmpEx.Convert( static_cast<BmpConversion>(nColors) ); // the entries in the xml section have the same meaning as
292  aGraphic = aBmpEx; // they have in the BmpConversion enum, so it should be
293  } // allowed to cast them
294  }
295  else
296  {
297  if( ( nMode == 1 ) || ( nMode == 2 ) )
298  {
299  GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
300  Size aNewSize( OutputDevice::LogicToLogic(Size(nLogicalWidth, nLogicalHeight), MapMode(MapUnit::Map100thMM), aMtf.GetPrefMapMode()) );
301 
302  if( aNewSize.Width() && aNewSize.Height() )
303  {
304  const Size aPreferredSize( aMtf.GetPrefSize() );
305  aMtf.Scale( Fraction( aNewSize.Width(), aPreferredSize.Width() ),
306  Fraction( aNewSize.Height(), aPreferredSize.Height() ) );
307  }
308  aGraphic = Graphic( aMtf );
309  }
310  else
311  aGraphic = rGraphic;
312  }
313 
314  }
315  else
316  aGraphic = rGraphic;
317 
318  return aGraphic;
319 }
320 
322  : bUseConfig(bConfig)
323 {
324  ImplInit();
325 }
326 
328 {
329  {
330  ::osl::MutexGuard aGuard( getListMutex() );
331  auto it = std::find(pFilterHdlList->begin(), pFilterHdlList->end(), this);
332  if( it != pFilterHdlList->end() )
333  pFilterHdlList->erase( it );
334 
335  if( pFilterHdlList->empty() )
336  {
337  delete pFilterHdlList;
338  pFilterHdlList = nullptr;
339  delete pConfig;
340  }
341  }
342 
343  pErrorEx.reset();
344 }
345 
347 {
348  {
349  ::osl::MutexGuard aGuard( getListMutex() );
350 
351  if ( !pFilterHdlList )
352  {
355  }
356  else
357  pConfig = pFilterHdlList->front()->pConfig;
358 
359  pFilterHdlList->push_back( this );
360  }
361 
362  if( bUseConfig )
363  {
364  OUString url("$BRAND_BASE_DIR/" LIBO_LIB_FOLDER);
365  rtl::Bootstrap::expandMacros(url); //TODO: detect failure
366  osl::FileBase::getSystemPathFromFileURL(url, aFilterPath);
367  }
368 
369  pErrorEx.reset( new FilterErrorEx );
370 }
371 
373 {
374  pErrorEx->nStreamError = pStm ? pStm->GetError() : ERRCODE_NONE;
375  return nError;
376 }
377 
379 {
380  return pConfig->GetImportFormatCount();
381 }
382 
383 sal_uInt16 GraphicFilter::GetImportFormatNumber( std::u16string_view rFormatName )
384 {
385  return pConfig->GetImportFormatNumber( rFormatName );
386 }
387 
388 sal_uInt16 GraphicFilter::GetImportFormatNumberForShortName( std::u16string_view rShortName )
389 {
390  return pConfig->GetImportFormatNumberForShortName( rShortName );
391 }
392 
393 sal_uInt16 GraphicFilter::GetImportFormatNumberForTypeName( std::u16string_view rType )
394 {
395  return pConfig->GetImportFormatNumberForTypeName( rType );
396 }
397 
398 OUString GraphicFilter::GetImportFormatName( sal_uInt16 nFormat )
399 {
400  return pConfig->GetImportFormatName( nFormat );
401 }
402 
403 OUString GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat )
404 {
405  return pConfig->GetImportFilterTypeName( nFormat );
406 }
407 
408 #ifdef _WIN32
409 OUString GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat )
410 {
411  return pConfig->GetImportFormatMediaType( nFormat );
412 }
413 #endif
414 
415 OUString GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat )
416 {
417  return pConfig->GetImportFormatShortName( nFormat );
418 }
419 
420 OUString GraphicFilter::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
421 {
422  return pConfig->GetImportWildcard( nFormat, nEntry );
423 }
424 
426 {
427  return pConfig->GetExportFormatCount();
428 }
429 
430 sal_uInt16 GraphicFilter::GetExportFormatNumber( std::u16string_view rFormatName )
431 {
432  return pConfig->GetExportFormatNumber( rFormatName );
433 }
434 
435 sal_uInt16 GraphicFilter::GetExportFormatNumberForMediaType( std::u16string_view rMediaType )
436 {
437  return pConfig->GetExportFormatNumberForMediaType( rMediaType );
438 }
439 
440 sal_uInt16 GraphicFilter::GetExportFormatNumberForShortName( std::u16string_view rShortName )
441 {
442  return pConfig->GetExportFormatNumberForShortName( rShortName );
443 }
444 
445 OUString GraphicFilter::GetExportInternalFilterName( sal_uInt16 nFormat )
446 {
447  return pConfig->GetExportInternalFilterName( nFormat );
448 }
449 
450 sal_uInt16 GraphicFilter::GetExportFormatNumberForTypeName( std::u16string_view rType )
451 {
452  return pConfig->GetExportFormatNumberForTypeName( rType );
453 }
454 
455 OUString GraphicFilter::GetExportFormatName( sal_uInt16 nFormat )
456 {
457  return pConfig->GetExportFormatName( nFormat );
458 }
459 
460 OUString GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat )
461 {
462  return pConfig->GetExportFormatMediaType( nFormat );
463 }
464 
465 OUString GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat )
466 {
467  return pConfig->GetExportFormatShortName( nFormat );
468 }
469 
470 OUString GraphicFilter::GetExportWildcard( sal_uInt16 nFormat )
471 {
472  return pConfig->GetExportWildcard( nFormat, 0 );
473 }
474 
475 bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat )
476 {
477  return pConfig->IsExportPixelFormat( nFormat );
478 }
479 
481  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
482 {
484  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::CanImportGraphic() : ProtType == INetProtocol::NotValid" );
485 
486  OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
487  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
488  if (xStream)
489  {
490  nRetValue = CanImportGraphic( aMainUrl, *xStream, nFormat, pDeterminedFormat );
491  }
492  return nRetValue;
493 }
494 
495 ErrCode GraphicFilter::CanImportGraphic( const OUString& rMainUrl, SvStream& rIStream,
496  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
497 {
498  sal_uLong nStreamPos = rIStream.Tell();
499  ErrCode nRes = ImpTestOrFindFormat( rMainUrl, rIStream, nFormat );
500 
501  rIStream.Seek(nStreamPos);
502 
503  if( nRes==ERRCODE_NONE && pDeterminedFormat!=nullptr )
504  *pDeterminedFormat = nFormat;
505 
506  return ImplSetError( nRes, &rIStream );
507 }
508 
509 //SJ: TODO, we need to create a GraphicImporter component
511  sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, GraphicFilterImportFlags nImportFlags )
512 {
514  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ImportGraphic() : ProtType == INetProtocol::NotValid" );
515 
516  OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
517  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
518  if (xStream)
519  {
520  nRetValue = ImportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pDeterminedFormat, nImportFlags );
521  }
522  return nRetValue;
523 }
524 
526  Graphic& rGraphic,
527  const OUString& rPath,
528  SvStream& rIStream,
529  sal_uInt16 nFormat,
530  sal_uInt16* pDeterminedFormat,
531  GraphicFilterImportFlags nImportFlags,
532  WmfExternal const *pExtHeader)
533 {
534  return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, nullptr, pExtHeader );
535 }
536 
537 namespace {
538 
541 struct GraphicImportContext
542 {
544  std::unique_ptr<SvStream> m_pStream;
546  std::shared_ptr<Graphic> m_pGraphic;
548  std::unique_ptr<BitmapScopedWriteAccess> m_pAccess;
549  std::unique_ptr<AlphaScopedWriteAccess> m_pAlphaAccess;
550  // Need to have an AlphaMask instance to keep its lifetime.
551  AlphaMask mAlphaMask;
555  GfxLinkType m_eLinkType = GfxLinkType::NONE;
557  sal_uInt64 m_nStreamBegin = 0;
560 };
561 
563 class GraphicImportTask : public comphelper::ThreadTask
564 {
565  GraphicImportContext& m_rContext;
566 public:
567  GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext);
568  void doWork() override;
570  static void doImport(GraphicImportContext& rContext);
571 };
572 
573 }
574 
575 GraphicImportTask::GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext)
576  : comphelper::ThreadTask(pTag),
577  m_rContext(rContext)
578 {
579 }
580 
581 void GraphicImportTask::doWork()
582 {
583  GraphicImportTask::doImport(m_rContext);
584 }
585 
586 void GraphicImportTask::doImport(GraphicImportContext& rContext)
587 {
588  if(rContext.m_eLinkType == GfxLinkType::NativeJpg)
589  {
590  if (!ImportJPEG(*rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, rContext.m_pAccess.get()))
591  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
592  }
593  else if(rContext.m_eLinkType == GfxLinkType::NativePng)
594  {
595  if (!vcl::ImportPNG(*rContext.m_pStream, *rContext.m_pGraphic,
596  rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap,
597  rContext.m_pAccess.get(), rContext.m_pAlphaAccess.get()))
598  {
599  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
600  }
601  }
602 }
603 
604 void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, std::vector< std::unique_ptr<SvStream> > vStreams)
605 {
606  static bool bThreads = !getenv("VCL_NO_THREAD_IMPORT");
607  std::vector<GraphicImportContext> aContexts;
608  aContexts.reserve(vStreams.size());
610  std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
611 
612  for (auto& pStream : vStreams)
613  {
614  aContexts.emplace_back();
615  GraphicImportContext& rContext = aContexts.back();
616 
617  if (pStream)
618  {
619  rContext.m_pStream = std::move(pStream);
620  rContext.m_pGraphic = std::make_shared<Graphic>();
621  rContext.m_nStatus = ERRCODE_NONE;
622 
623  // Detect the format.
624  ResetLastError();
625  rContext.m_nStreamBegin = rContext.m_pStream->Tell();
626  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
627  rContext.m_nStatus = ImpTestOrFindFormat(OUString(), *rContext.m_pStream, nFormat);
628  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
629 
630  // Import the graphic.
631  if (rContext.m_nStatus == ERRCODE_NONE && !rContext.m_pStream->GetError())
632  {
633  OUString aFilterName = pConfig->GetImportFilterName(nFormat);
634 
635  if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
636  {
637  rContext.m_eLinkType = GfxLinkType::NativeJpg;
638  rContext.m_nImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
639 
640  if (ImportJPEG( *rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
641  {
642  Bitmap& rBitmap = const_cast<Bitmap&>(rContext.m_pGraphic->GetBitmapExRef().GetBitmap());
643  rContext.m_pAccess = std::make_unique<BitmapScopedWriteAccess>(rBitmap);
644  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
645  if (bThreads)
646  rSharedPool.pushTask(std::make_unique<GraphicImportTask>(pTag, rContext));
647  else
648  GraphicImportTask::doImport(rContext);
649  }
650  else
651  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
652  }
653  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
654  {
655  rContext.m_eLinkType = GfxLinkType::NativePng;
656 
657  if (vcl::ImportPNG( *rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr, nullptr))
658  {
659  const BitmapEx& rBitmapEx = rContext.m_pGraphic->GetBitmapExRef();
660  Bitmap& rBitmap = const_cast<Bitmap&>(rBitmapEx.GetBitmap());
661  rContext.m_pAccess = std::make_unique<BitmapScopedWriteAccess>(rBitmap);
662  if(rBitmapEx.IsAlpha())
663  {
664  // The separate alpha bitmap causes a number of complications. Not only
665  // we need to have an extra bitmap access for it, but we also need
666  // to keep an AlphaMask instance in the context. This is because
667  // BitmapEx internally keeps Bitmap and not AlphaMask (because the Bitmap
668  // may be also a mask, not alpha). So BitmapEx::GetAlpha() returns
669  // a temporary, and direct access to the Bitmap wouldn't work
670  // with AlphaScopedBitmapAccess. *sigh*
671  rContext.mAlphaMask = rBitmapEx.GetAlpha();
672  rContext.m_pAlphaAccess = std::make_unique<AlphaScopedWriteAccess>(rContext.mAlphaMask);
673  }
674  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
675  if (bThreads)
676  rSharedPool.pushTask(std::make_unique<GraphicImportTask>(pTag, rContext));
677  else
678  GraphicImportTask::doImport(rContext);
679  }
680  else
681  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
682  }
683  else
684  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
685  }
686  }
687  }
688 
689  rSharedPool.waitUntilDone(pTag);
690 
691  // Process data after import.
692  for (auto& rContext : aContexts)
693  {
694  if(rContext.m_pAlphaAccess) // Need to move the AlphaMask back to the BitmapEx.
695  *rContext.m_pGraphic = BitmapEx( rContext.m_pGraphic->GetBitmapExRef().GetBitmap(), rContext.mAlphaMask );
696  rContext.m_pAccess.reset();
697  rContext.m_pAlphaAccess.reset();
698 
699  if (rContext.m_nStatus == ERRCODE_NONE && (rContext.m_eLinkType != GfxLinkType::NONE) && !rContext.m_pGraphic->GetReaderContext())
700  {
701  std::unique_ptr<sal_uInt8[]> pGraphicContent;
702 
703  const sal_uInt64 nStreamEnd = rContext.m_pStream->Tell();
704  sal_Int32 nGraphicContentSize = nStreamEnd - rContext.m_nStreamBegin;
705 
706  if (nGraphicContentSize > 0)
707  {
708  try
709  {
710  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
711  }
712  catch (const std::bad_alloc&)
713  {
714  rContext.m_nStatus = ERRCODE_GRFILTER_TOOBIG;
715  }
716 
717  if (rContext.m_nStatus == ERRCODE_NONE)
718  {
719  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
720  rContext.m_pStream->ReadBytes(pGraphicContent.get(), nGraphicContentSize);
721  }
722  }
723 
724  if (rContext.m_nStatus == ERRCODE_NONE)
725  rContext.m_pGraphic->SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, rContext.m_eLinkType));
726  }
727 
728  if (rContext.m_nStatus != ERRCODE_NONE)
729  rContext.m_pGraphic = nullptr;
730 
731  rGraphics.push_back(rContext.m_pGraphic);
732  }
733 }
734 
735 void GraphicFilter::MakeGraphicsAvailableThreaded(std::vector<Graphic*>& graphics)
736 {
737  // Graphic::makeAvailable() is not thread-safe. Only the jpeg and png loaders are, so here
738  // we process only jpeg and png images that also have their stream data, load new Graphic's
739  // from them and then update the passed objects using them.
740  std::vector< Graphic* > toLoad;
741  for(auto graphic : graphics)
742  {
743  // Need to use GetSharedGfxLink, to access the pointer without copying.
744  if(!graphic->isAvailable() && graphic->IsGfxLink()
745  && graphic->GetSharedGfxLink()->GetDataSize() != 0
746  && (graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativeJpg
747  || graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativePng))
748  {
749  // Graphic objects share internal ImpGraphic, do not process any of those twice.
750  const auto predicate = [graphic](Graphic* item) { return item->ImplGetImpGraphic() == graphic->ImplGetImpGraphic(); };
751  if( std::find_if(toLoad.begin(), toLoad.end(), predicate ) == toLoad.end())
752  toLoad.push_back( graphic );
753  }
754  }
755  if( toLoad.empty())
756  return;
757  std::vector< std::unique_ptr<SvStream>> streams;
758  for( auto graphic : toLoad )
759  {
760  streams.push_back( std::make_unique<SvMemoryStream>( const_cast<sal_uInt8*>(graphic->GetSharedGfxLink()->GetData()),
761  graphic->GetSharedGfxLink()->GetDataSize(), StreamMode::READ | StreamMode::WRITE));
762  }
763  std::vector< std::shared_ptr<Graphic>> loadedGraphics;
764  ImportGraphics(loadedGraphics, std::move(streams));
765  assert(loadedGraphics.size() == toLoad.size());
766  for( size_t i = 0; i < toLoad.size(); ++i )
767  {
768  if(loadedGraphics[ i ] != nullptr)
769  toLoad[ i ]->ImplGetImpGraphic()->updateFromLoadedGraphic(loadedGraphics[ i ]->ImplGetImpGraphic());
770  }
771 }
772 
773 Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit,
774  const Size* pSizeHint)
775 {
776  Graphic aGraphic;
777  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
778  GfxLinkType eLinkType = GfxLinkType::NONE;
779 
780  ResetLastError();
781 
782  const sal_uLong nStreamBegin = rIStream.Tell();
783 
784  rIStream.Seek(nStreamBegin);
785 
786  ErrCode nStatus = ImpTestOrFindFormat("", rIStream, nFormat);
787 
788  rIStream.Seek(nStreamBegin);
789  sal_uInt32 nStreamLength(rIStream.remainingSize());
790  if (sizeLimit && sizeLimit < nStreamLength)
791  nStreamLength = sizeLimit;
792 
793  OUString aFilterName = pConfig->GetImportFilterName(nFormat);
794 
795  std::unique_ptr<sal_uInt8[]> pGraphicContent;
796  sal_Int32 nGraphicContentSize = 0;
797 
798  // read graphic
799  {
800  if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
801  {
802  eLinkType = GfxLinkType::NativeGif;
803  }
804  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
805  {
806  // check if this PNG contains a GIF chunk!
807  pGraphicContent = vcl::PngImageReader::getMicrosoftGifChunk(rIStream, &nGraphicContentSize);
808  if( pGraphicContent )
809  eLinkType = GfxLinkType::NativeGif;
810  else
811  eLinkType = GfxLinkType::NativePng;
812  }
813  else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
814  {
815  eLinkType = GfxLinkType::NativeJpg;
816  }
817  else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
818  {
819  bool bOkay(false);
820 
821  if (nStreamLength > 0)
822  {
823  std::vector<sal_uInt8> aTwoBytes(2);
824  rIStream.ReadBytes(aTwoBytes.data(), 2);
825  rIStream.Seek(nStreamBegin);
826 
827  if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
828  {
829  SvMemoryStream aMemStream;
830  ZCodec aCodec;
831  tools::Long nMemoryLength;
832 
833  aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
834  nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
835  aCodec.EndCompression();
836 
837  if (!rIStream.GetError() && nMemoryLength >= 0)
838  {
839  nGraphicContentSize = nMemoryLength;
840  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
841 
842  aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
843  aMemStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
844 
845  bOkay = true;
846  }
847  }
848  else
849  {
850  nGraphicContentSize = nStreamLength;
851  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
852  rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
853 
854  bOkay = true;
855  }
856  }
857 
858  if (bOkay)
859  {
860  eLinkType = GfxLinkType::NativeSvg;
861  }
862  else
863  {
865  }
866  }
867  else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
868  {
869  eLinkType = GfxLinkType::NativeBmp;
870  }
871  else if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
872  {
873  eLinkType = GfxLinkType::NativeMov;
874  }
875  else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) ||
876  aFilterName.equalsIgnoreAsciiCase(IMP_EMF))
877  {
878  nGraphicContentSize = nStreamLength;
879  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
880 
881  rIStream.Seek(nStreamBegin);
882  rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
883 
884  if (!rIStream.GetError())
885  {
886  eLinkType = GfxLinkType::NativeWmf;
887  }
888  else
889  {
891  }
892  }
893  else if (aFilterName == IMP_PDF)
894  {
895  eLinkType = GfxLinkType::NativePdf;
896  }
897  else if (aFilterName == IMP_TIFF)
898  {
899  eLinkType = GfxLinkType::NativeTif;
900  }
901  else if (aFilterName == IMP_PICT)
902  {
903  eLinkType = GfxLinkType::NativePct;
904  }
905  else if (aFilterName == IMP_MET)
906  {
907  eLinkType = GfxLinkType::NativeMet;
908  }
909  else
910  {
912  }
913  }
914 
915  if (nStatus == ERRCODE_NONE && eLinkType != GfxLinkType::NONE)
916  {
917  if (!pGraphicContent)
918  {
919  nGraphicContentSize = nStreamLength;
920 
921  if (nGraphicContentSize > 0)
922  {
923  try
924  {
925  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
926  }
927  catch (const std::bad_alloc&)
928  {
929  nStatus = ERRCODE_GRFILTER_TOOBIG;
930  }
931 
932  if (nStatus == ERRCODE_NONE)
933  {
934  rIStream.Seek(nStreamBegin);
935  rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
936  }
937  }
938  }
939 
940  if( nStatus == ERRCODE_NONE )
941  {
942  bool bAnimated = false;
943  Size aLogicSize;
944  if (eLinkType == GfxLinkType::NativeGif)
945  {
946  SvMemoryStream aMemoryStream(pGraphicContent.get(), nGraphicContentSize, StreamMode::READ);
947  bAnimated = IsGIFAnimated(aMemoryStream, aLogicSize);
948  if (!pSizeHint && aLogicSize.getWidth() && aLogicSize.getHeight())
949  {
950  pSizeHint = &aLogicSize;
951  }
952  }
953  aGraphic.SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
954  aGraphic.ImplGetImpGraphic()->setPrepared(bAnimated, pSizeHint);
955  }
956  }
957 
958  // Set error code or try to set native buffer
959  if (nStatus != ERRCODE_NONE)
960  ImplSetError(nStatus, &rIStream);
961  if (nStatus != ERRCODE_NONE || eLinkType == GfxLinkType::NONE)
962  rIStream.Seek(nStreamBegin);
963 
964  return aGraphic;
965 }
966 
967 ErrCode GraphicFilter::readGIF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
968 {
969  if (ImportGIF(rStream, rGraphic))
970  {
971  rLinkType = GfxLinkType::NativeGif;
972  return ERRCODE_NONE;
973  }
974  else
976 }
977 
978 ErrCode GraphicFilter::readPNG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, std::unique_ptr<sal_uInt8[]> & rpGraphicContent,
979  sal_Int32& rGraphicContentSize)
980 {
981  ErrCode aReturnCode = ERRCODE_NONE;
982 
983  // check if this PNG contains a GIF chunk!
984  rpGraphicContent = vcl::PngImageReader::getMicrosoftGifChunk(rStream, &rGraphicContentSize);
985  if( rpGraphicContent )
986  {
987  SvMemoryStream aIStrm(rpGraphicContent.get(), rGraphicContentSize, StreamMode::READ);
988  ImportGIF(aIStrm, rGraphic);
989  rLinkType = GfxLinkType::NativeGif;
990  return aReturnCode;
991  }
992 
993  // PNG has no GIF chunk
994  vcl::PngImageReader aPNGReader(rStream);
995  BitmapEx aBitmapEx(aPNGReader.read());
996  if (!aBitmapEx.IsEmpty())
997  {
998  rGraphic = aBitmapEx;
999  rLinkType = GfxLinkType::NativePng;
1000  }
1001  else
1002  aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1003 
1004  return aReturnCode;
1005 }
1006 
1007 ErrCode GraphicFilter::readJPEG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, GraphicFilterImportFlags nImportFlags)
1008 {
1009  ErrCode aReturnCode = ERRCODE_NONE;
1010 
1011  // set LOGSIZE flag always, if not explicitly disabled
1012  // (see #90508 and #106763)
1014  {
1016  }
1017 
1018  sal_uInt64 nPosition = rStream.Tell();
1019  if (!ImportJPEG(rStream, rGraphic, nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
1020  aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1021  else
1022  {
1023  Bitmap& rBitmap = const_cast<Bitmap&>(rGraphic.GetBitmapExRef().GetBitmap());
1024  BitmapScopedWriteAccess pWriteAccess(rBitmap);
1025  rStream.Seek(nPosition);
1026  if (!ImportJPEG(rStream, rGraphic, nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, &pWriteAccess))
1027  aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1028  else
1029  rLinkType = GfxLinkType::NativeJpg;
1030  }
1031 
1032  return aReturnCode;
1033 }
1034 
1035 ErrCode GraphicFilter::readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, std::unique_ptr<sal_uInt8[]> & rpGraphicContent,
1036  sal_Int32& rGraphicContentSize)
1037 {
1038  ErrCode aReturnCode = ERRCODE_NONE;
1039 
1040  const sal_uInt32 nStreamPosition(rStream.Tell());
1041  const sal_uInt32 nStreamLength(rStream.remainingSize());
1042 
1043  bool bOkay(false);
1044 
1045  if (nStreamLength > 0)
1046  {
1047  std::vector<sal_uInt8> aTwoBytes(2);
1048  rStream.ReadBytes(aTwoBytes.data(), 2);
1049  rStream.Seek(nStreamPosition);
1050 
1051  if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
1052  {
1053  SvMemoryStream aMemStream;
1054  ZCodec aCodec;
1055  tools::Long nMemoryLength;
1056 
1057  aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
1058  nMemoryLength = aCodec.Decompress(rStream, aMemStream);
1059  aCodec.EndCompression();
1060 
1061  if (!rStream.GetError() && nMemoryLength >= 0)
1062  {
1063  VectorGraphicDataArray aNewData(nMemoryLength);
1064  aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
1065  aMemStream.ReadBytes(aNewData.begin(), nMemoryLength);
1066 
1067  // Make a uncompressed copy for GfxLink
1068  rGraphicContentSize = nMemoryLength;
1069  rpGraphicContent.reset(new sal_uInt8[rGraphicContentSize]);
1070  std::copy(aNewData.begin(), aNewData.end(), rpGraphicContent.get());
1071 
1072  if (!aMemStream.GetError())
1073  {
1074  BinaryDataContainer aDataContainer(reinterpret_cast<const sal_uInt8*>(aNewData.getConstArray()), aNewData.getLength());
1075  auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aDataContainer, VectorGraphicDataType::Svg);
1076  rGraphic = Graphic(aVectorGraphicDataPtr);
1077  bOkay = true;
1078  }
1079  }
1080  }
1081  else
1082  {
1083  VectorGraphicDataArray aNewData(nStreamLength);
1084  rStream.ReadBytes(aNewData.begin(), nStreamLength);
1085 
1086  if (!rStream.GetError())
1087  {
1088  BinaryDataContainer aDataContainer(reinterpret_cast<const sal_uInt8*>(aNewData.getConstArray()), aNewData.getLength());
1089  auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aDataContainer, VectorGraphicDataType::Svg);
1090  rGraphic = Graphic(aVectorGraphicDataPtr);
1091  bOkay = true;
1092  }
1093  }
1094  }
1095 
1096  if (bOkay)
1097  {
1098  rLinkType = GfxLinkType::NativeSvg;
1099  }
1100  else
1101  {
1102  aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1103  }
1104 
1105  return aReturnCode;
1106 }
1107 
1109 {
1110  if (ImportXBM(rStream, rGraphic))
1111  return ERRCODE_NONE;
1112  else
1114 }
1115 
1117 {
1118  if (ImportXPM(rStream, rGraphic))
1119  return ERRCODE_NONE;
1120  else
1122 }
1123 
1125  WmfExternal const *pExtHeader, VectorGraphicDataType eType)
1126 {
1127  // use new UNO API service, do not directly import but create a
1128  // Graphic that contains the original data and decomposes to
1129  // primitives on demand
1130 
1131  ErrCode aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1132 
1133  const sal_uInt32 nStreamLength(rStream.remainingSize());
1134  VectorGraphicDataArray aNewData(nStreamLength);
1135 
1136  rStream.ReadBytes(aNewData.begin(), nStreamLength);
1137 
1138  if (!rStream.GetError())
1139  {
1140  const VectorGraphicDataType aDataType(eType);
1141  BinaryDataContainer aDataContainer(reinterpret_cast<const sal_uInt8*>(aNewData.getConstArray()), aNewData.getLength());
1142 
1143  auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aDataContainer, aDataType);
1144 
1145  if (pExtHeader)
1146  {
1147  aVectorGraphicDataPtr->setWmfExternalHeader(*pExtHeader);
1148  }
1149 
1150  rGraphic = Graphic(aVectorGraphicDataPtr);
1151  rLinkType = GfxLinkType::NativeWmf;
1152  aReturnCode = ERRCODE_NONE;
1153  }
1154 
1155  return aReturnCode;
1156 }
1157 
1158 ErrCode GraphicFilter::readWMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, WmfExternal const* pExtHeader)
1159 {
1160  return readWMF_EMF(rStream, rGraphic, rLinkType, pExtHeader, VectorGraphicDataType::Wmf);
1161 }
1162 
1163 ErrCode GraphicFilter::readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, WmfExternal const* pExtHeader)
1164 {
1165  return readWMF_EMF(rStream, rGraphic, rLinkType, pExtHeader, VectorGraphicDataType::Emf);
1166 }
1167 
1168 ErrCode GraphicFilter::readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1169 {
1170  if (vcl::ImportPDF(rStream, rGraphic))
1171  {
1172  rLinkType = GfxLinkType::NativePdf;
1173  return ERRCODE_NONE;
1174  }
1175  else
1177 }
1178 
1179 ErrCode GraphicFilter::readTIFF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1180 {
1181  if (ImportTiffGraphicImport(rStream, rGraphic))
1182  {
1183  rLinkType = GfxLinkType::NativeTif;
1184  return ERRCODE_NONE;
1185  }
1186  else
1188 }
1189 
1190 ErrCode GraphicFilter::readWithTypeSerializer(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, OUString aFilterName)
1191 {
1192  ErrCode aReturnCode = ERRCODE_GRFILTER_FILTERERROR;
1193 
1194  // SV internal filters for import bitmaps and MetaFiles
1195  TypeSerializer aSerializer(rStream);
1196  aSerializer.readGraphic(rGraphic);
1197 
1198  if (!rStream.GetError())
1199  {
1200  if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
1201  {
1202  rGraphic.SetDefaultType();
1203  rStream.Seek(STREAM_SEEK_TO_END);
1204  rLinkType = GfxLinkType::NativeMov;
1205  }
1206  aReturnCode = ERRCODE_NONE;
1207  }
1208  return aReturnCode;
1209 }
1210 
1211 ErrCode GraphicFilter::readBMP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1212 {
1213  if (BmpReader(rStream, rGraphic))
1214  {
1215  rLinkType = GfxLinkType::NativeBmp;
1216  return ERRCODE_NONE;
1217  }
1218  else
1220 }
1221 
1223 {
1224  if (ImportTgaGraphic(rStream, rGraphic))
1225  return ERRCODE_NONE;
1226  else
1228 }
1229 
1230 ErrCode GraphicFilter::readPICT(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1231 {
1232  if (ImportPictGraphic(rStream, rGraphic))
1233  {
1234  rLinkType = GfxLinkType::NativePct;
1235  return ERRCODE_NONE;
1236  }
1237  else
1239 }
1240 
1241 ErrCode GraphicFilter::readMET(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
1242 {
1243  if (ImportMetGraphic(rStream, rGraphic))
1244  {
1245  rLinkType = GfxLinkType::NativeMet;
1246  return ERRCODE_NONE;
1247  }
1248  else
1250 }
1251 
1253 {
1254  if (ImportRasGraphic(rStream, rGraphic))
1255  return ERRCODE_NONE;
1256  else
1258 }
1259 
1261 {
1262  if (ImportPcxGraphic(rStream, rGraphic))
1263  return ERRCODE_NONE;
1264  else
1266 }
1267 
1269 {
1270  if (ImportEpsGraphic(rStream, rGraphic))
1271  return ERRCODE_NONE;
1272  else
1274 }
1275 
1277 {
1278  if (ImportPsdGraphic(rStream, rGraphic))
1279  return ERRCODE_NONE;
1280  else
1282 }
1283 
1285 {
1286  std::unique_ptr<FilterConfigItem> pFilterConfigItem;
1288  {
1289  OUString aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
1290  pFilterConfigItem = std::make_unique<FilterConfigItem>(aFilterConfigPath);
1291  }
1292 
1293  if (ImportPcdGraphic(rStream, rGraphic, pFilterConfigItem.get()))
1294  return ERRCODE_NONE;
1295  else
1297 }
1298 
1300 {
1301  if (ImportPbmGraphic(rStream, rGraphic))
1302  return ERRCODE_NONE;
1303  else
1305 }
1306 
1308 {
1309  if (ImportDxfGraphic(rStream, rGraphic))
1310  return ERRCODE_NONE;
1311  else
1313 }
1314 
1315 ErrCode GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath, SvStream& rIStream,
1316  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
1317  const css::uno::Sequence< css::beans::PropertyValue >* /*pFilterData*/,
1318  WmfExternal const *pExtHeader )
1319 {
1320  OUString aFilterName;
1321  sal_uLong nStreamBegin;
1322  ErrCode nStatus;
1323  GfxLinkType eLinkType = GfxLinkType::NONE;
1324  const bool bLinkSet = rGraphic.IsGfxLink();
1325 
1326  std::unique_ptr<sal_uInt8[]> pGraphicContent;
1327  sal_Int32 nGraphicContentSize = 0;
1328 
1329  ResetLastError();
1330 
1331  std::shared_ptr<GraphicReader> pContext = rGraphic.GetReaderContext();
1332  bool bDummyContext = rGraphic.IsDummyContext();
1333  if( !pContext || bDummyContext )
1334  {
1335  if( bDummyContext )
1336  {
1337  rGraphic.SetDummyContext( false );
1338  nStreamBegin = 0;
1339  }
1340  else
1341  nStreamBegin = rIStream.Tell();
1342 
1343  nStatus = ImpTestOrFindFormat( rPath, rIStream, nFormat );
1344  // if pending, return ERRCODE_NONE in order to request more bytes
1345  if( rIStream.GetError() == ERRCODE_IO_PENDING )
1346  {
1347  rGraphic.SetDummyContext(true);
1348  rIStream.ResetError();
1349  rIStream.Seek( nStreamBegin );
1350  return ImplSetError( ERRCODE_NONE );
1351  }
1352 
1353  rIStream.Seek( nStreamBegin );
1354 
1355  if( ( nStatus != ERRCODE_NONE ) || rIStream.GetError() )
1356  return ImplSetError( ( nStatus != ERRCODE_NONE ) ? nStatus : ERRCODE_GRFILTER_OPENERROR, &rIStream );
1357 
1358  if( pDeterminedFormat )
1359  *pDeterminedFormat = nFormat;
1360 
1361  aFilterName = pConfig->GetImportFilterName( nFormat );
1362  }
1363  else
1364  {
1365  aFilterName = pContext->GetUpperFilterName();
1366 
1367  nStreamBegin = 0;
1368  nStatus = ERRCODE_NONE;
1369  }
1370 
1371  // read graphic
1372  {
1373  if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
1374  {
1375  nStatus = readGIF(rIStream, rGraphic, eLinkType);
1376  }
1377  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
1378  {
1379  nStatus = readPNG(rIStream, rGraphic, eLinkType, pGraphicContent, nGraphicContentSize);
1380  }
1381  else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
1382  {
1383  nStatus = readJPEG(rIStream, rGraphic, eLinkType, nImportFlags);
1384  }
1385  else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
1386  {
1387  nStatus = readSVG(rIStream, rGraphic, eLinkType, pGraphicContent, nGraphicContentSize);
1388  }
1389  else if( aFilterName.equalsIgnoreAsciiCase( IMP_XBM ) )
1390  {
1391  nStatus = readXBM(rIStream, rGraphic);
1392  }
1393  else if( aFilterName.equalsIgnoreAsciiCase( IMP_XPM ) )
1394  {
1395  nStatus = readXPM(rIStream, rGraphic);
1396  }
1397  else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
1398  {
1399  nStatus = readBMP(rIStream, rGraphic, eLinkType);
1400  }
1401  else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVMETAFILE))
1402  {
1403  nStatus = readWithTypeSerializer(rIStream, rGraphic, eLinkType, aFilterName);
1404  }
1405  else if( aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
1406  {
1407  nStatus = readWithTypeSerializer(rIStream, rGraphic, eLinkType, aFilterName);
1408  }
1409  else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF))
1410  {
1411  nStatus = readWMF(rIStream, rGraphic, eLinkType, pExtHeader);
1412  }
1413  else if (aFilterName.equalsIgnoreAsciiCase(IMP_EMF))
1414  {
1415  nStatus = readEMF(rIStream, rGraphic, eLinkType, pExtHeader);
1416  }
1417  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PDF))
1418  {
1419  nStatus = readPDF(rIStream, rGraphic, eLinkType);
1420  }
1421  else if (aFilterName.equalsIgnoreAsciiCase(IMP_TIFF) )
1422  {
1423  nStatus = readTIFF(rIStream, rGraphic, eLinkType);
1424  }
1425  else if (aFilterName.equalsIgnoreAsciiCase(IMP_TGA) )
1426  {
1427  nStatus = readTGA(rIStream, rGraphic);
1428  }
1429  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PICT))
1430  {
1431  nStatus = readPICT(rIStream, rGraphic, eLinkType);
1432  }
1433  else if (aFilterName.equalsIgnoreAsciiCase(IMP_MET))
1434  {
1435  nStatus = readMET(rIStream, rGraphic, eLinkType);
1436  }
1437  else if (aFilterName.equalsIgnoreAsciiCase(IMP_RAS))
1438  {
1439  nStatus = readRAS(rIStream, rGraphic);
1440  }
1441  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PCX))
1442  {
1443  nStatus = readPCX(rIStream, rGraphic);
1444  }
1445  else if (aFilterName.equalsIgnoreAsciiCase(IMP_EPS))
1446  {
1447  nStatus = readEPS(rIStream, rGraphic);
1448  }
1449  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PSD))
1450  {
1451  nStatus = readPSD(rIStream, rGraphic);
1452  }
1453  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PCD))
1454  {
1455  nStatus = readPCD(rIStream, rGraphic);
1456  }
1457  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PBM))
1458  {
1459  nStatus = readPBM(rIStream, rGraphic);
1460  }
1461  else if (aFilterName.equalsIgnoreAsciiCase(IMP_DXF))
1462  {
1463  nStatus = readDXF(rIStream, rGraphic);
1464  }
1465  else
1466  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1467  }
1468 
1469  if( nStatus == ERRCODE_NONE && ( eLinkType != GfxLinkType::NONE ) && !rGraphic.GetReaderContext() && !bLinkSet )
1470  {
1471  if (!pGraphicContent)
1472  {
1473  const sal_uLong nStreamEnd = rIStream.Tell();
1474  nGraphicContentSize = nStreamEnd - nStreamBegin;
1475 
1476  if (nGraphicContentSize > 0)
1477  {
1478  try
1479  {
1480  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1481  }
1482  catch (const std::bad_alloc&)
1483  {
1484  nStatus = ERRCODE_GRFILTER_TOOBIG;
1485  }
1486 
1487  if( nStatus == ERRCODE_NONE )
1488  {
1489  rIStream.Seek(nStreamBegin);
1490  rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1491  }
1492  }
1493  }
1494  if( nStatus == ERRCODE_NONE )
1495  {
1496  rGraphic.SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
1497  }
1498  }
1499 
1500  // Set error code or try to set native buffer
1501  if( nStatus != ERRCODE_NONE )
1502  {
1503  ImplSetError( nStatus, &rIStream );
1504  rIStream.Seek( nStreamBegin );
1505  rGraphic.Clear();
1506  }
1507 
1508  return nStatus;
1509 }
1510 
1512  sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1513 {
1514  SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1516  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ExportGraphic() : ProtType == INetProtocol::NotValid" );
1517 
1518  OUString aMainUrl(rPath.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1519  bool bAlreadyExists = utl::UCBContentHelper::IsDocument(aMainUrl);
1520 
1521  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::WRITE | StreamMode::TRUNC ));
1522  if (xStream)
1523  {
1524  nRetValue = ExportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pFilterData );
1525  xStream.reset();
1526 
1527  if( ( ERRCODE_NONE != nRetValue ) && !bAlreadyExists )
1528  utl::UCBContentHelper::Kill(aMainUrl);
1529  }
1530  return nRetValue;
1531 }
1532 
1533 ErrCode GraphicFilter::ExportGraphic( const Graphic& rGraphic, const OUString& rPath,
1534  SvStream& rOStm, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1535 {
1536  SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1537  sal_uInt16 nFormatCount = GetExportFormatCount();
1538 
1539  ResetLastError();
1540 
1541  if( nFormat == GRFILTER_FORMAT_DONTKNOW )
1542  {
1543  INetURLObject aURL( rPath );
1544  OUString aExt( aURL.GetFileExtension().toAsciiUpperCase() );
1545 
1546  for( sal_uInt16 i = 0; i < nFormatCount; i++ )
1547  {
1548  if ( pConfig->GetExportFormatExtension( i ).equalsIgnoreAsciiCase( aExt ) )
1549  {
1550  nFormat=i;
1551  break;
1552  }
1553  }
1554  }
1555  if( nFormat >= nFormatCount )
1557 
1558  FilterConfigItem aConfigItem( pFilterData );
1559  OUString aFilterName( pConfig->GetExportFilterName( nFormat ) );
1560  ErrCode nStatus = ERRCODE_NONE;
1562  Graphic aGraphic = ImpGetScaledGraphic( rGraphic, aConfigItem );
1563  eType = aGraphic.GetType();
1564 
1565  if( pConfig->IsExportPixelFormat( nFormat ) )
1566  {
1567  if( eType != GraphicType::Bitmap )
1568  {
1569  Size aSizePixel;
1570  sal_uLong nBitsPerPixel,nNeededMem,nMaxMem;
1572 
1573  nMaxMem = 1024;
1574  nMaxMem *= 1024; // In Bytes
1575 
1576  // Calculate how big the image would normally be:
1577  aSizePixel=aVirDev->LogicToPixel(aGraphic.GetPrefSize(),aGraphic.GetPrefMapMode());
1578 
1579  // Calculate how much memory the image will take up
1580  nBitsPerPixel=aVirDev->GetBitCount();
1581  nNeededMem=(static_cast<sal_uLong>(aSizePixel.Width())*static_cast<sal_uLong>(aSizePixel.Height())*nBitsPerPixel+7)/8;
1582 
1583  // is the image larger than available memory?
1584  if (nMaxMem<nNeededMem)
1585  {
1586  double fFak=sqrt(static_cast<double>(nMaxMem)/static_cast<double>(nNeededMem));
1587  aSizePixel.setWidth(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Width())*fFak) );
1588  aSizePixel.setHeight(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Height())*fFak) );
1589  }
1590 
1591  aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1592  aVirDev->SetOutputSizePixel(aSizePixel);
1593  Graphic aGraphic2=aGraphic;
1594  aGraphic2.Draw(aVirDev.get(),Point(0,0),aSizePixel); // this changes the MapMode
1595  aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1596  aGraphic=Graphic(aVirDev->GetBitmapEx(Point(0,0),aSizePixel));
1597  }
1598  }
1599  if( rOStm.GetError() )
1600  nStatus = ERRCODE_GRFILTER_IOERROR;
1601  if( ERRCODE_NONE == nStatus )
1602  {
1603  if( aFilterName.equalsIgnoreAsciiCase( EXP_BMP ) )
1604  {
1605  if (!BmpWriter(rOStm, aGraphic, &aConfigItem))
1606  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1607  if (rOStm.GetError())
1608  nStatus = ERRCODE_GRFILTER_IOERROR;
1609  }
1610  else if (aFilterName.equalsIgnoreAsciiCase(EXP_TIFF))
1611  {
1612  if (!ExportTiffGraphicImport(rOStm, aGraphic, &aConfigItem))
1613  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1614 
1615  if( rOStm.GetError() )
1616  nStatus = ERRCODE_GRFILTER_IOERROR;
1617  }
1618  else if (aFilterName.equalsIgnoreAsciiCase(EXP_GIF))
1619  {
1620  if (!ExportGifGraphic(rOStm, aGraphic, &aConfigItem))
1621  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1622 
1623  if( rOStm.GetError() )
1624  nStatus = ERRCODE_GRFILTER_IOERROR;
1625  }
1626  else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVMETAFILE ) )
1627  {
1628  sal_Int32 nVersion = aConfigItem.ReadInt32( "Version", 0 ) ;
1629  if ( nVersion )
1630  rOStm.SetVersion( nVersion );
1631 
1632  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1633  GDIMetaFile aMTF(aGraphic.GetGDIMetaFile());
1634 
1635  aMTF.Write( rOStm );
1636 
1637  if( rOStm.GetError() )
1638  nStatus = ERRCODE_GRFILTER_IOERROR;
1639  }
1640  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_WMF ) )
1641  {
1642  bool bDone(false);
1643 
1644  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1645  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1646 
1647  bool bIsEMF = rGraphic.GetGfxLink().IsEMF();
1648 
1649  // VectorGraphicDataType::Wmf means WMF or EMF, allow direct write in the WMF case
1650  // only.
1651  if (rVectorGraphicDataPtr
1652  && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Wmf
1653  && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty()
1654  && !bIsEMF)
1655  {
1656  auto & aDataContainer = rVectorGraphicDataPtr->getBinaryDataContainer();
1657  rOStm.WriteBytes(aDataContainer.getData(), aDataContainer.getSize());
1658 
1659  if (rOStm.GetError())
1660  {
1661  nStatus = ERRCODE_GRFILTER_IOERROR;
1662  }
1663  else
1664  {
1665  bDone = true;
1666  }
1667  }
1668 
1669  if (!bDone)
1670  {
1671  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1672  if (!ConvertGraphicToWMF(aGraphic, rOStm, &aConfigItem))
1673  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1674 
1675  if (rOStm.GetError())
1676  nStatus = ERRCODE_GRFILTER_IOERROR;
1677  }
1678  }
1679  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_EMF ) )
1680  {
1681  bool bDone(false);
1682 
1683  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1684  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1685 
1686  if (rVectorGraphicDataPtr
1687  && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Emf
1688  && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty())
1689  {
1690  auto & aDataContainer = rVectorGraphicDataPtr->getBinaryDataContainer();
1691  rOStm.WriteBytes(aDataContainer.getData(), aDataContainer.getSize());
1692 
1693  if (rOStm.GetError())
1694  {
1695  nStatus = ERRCODE_GRFILTER_IOERROR;
1696  }
1697  else
1698  {
1699  bDone = true;
1700  }
1701  }
1702 
1703  if (!bDone)
1704  {
1705  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1706  if (!ConvertGDIMetaFileToEMF(aGraphic.GetGDIMetaFile(), rOStm))
1707  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1708 
1709  if (rOStm.GetError())
1710  nStatus = ERRCODE_GRFILTER_IOERROR;
1711  }
1712  }
1713  else if( aFilterName.equalsIgnoreAsciiCase( EXP_JPEG ) )
1714  {
1715  bool bExportedGrayJPEG = false;
1716  if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) )
1717  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1718 
1719  if( rOStm.GetError() )
1720  nStatus = ERRCODE_GRFILTER_IOERROR;
1721  }
1722  else if (aFilterName.equalsIgnoreAsciiCase(EXP_EPS))
1723  {
1724  if (!ExportEpsGraphic(rOStm, aGraphic, &aConfigItem))
1725  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1726 
1727  if (rOStm.GetError())
1728  nStatus = ERRCODE_GRFILTER_IOERROR;
1729  }
1730  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_PNG ) )
1731  {
1732  vcl::PNGWriter aPNGWriter( aGraphic.GetBitmapEx(), pFilterData );
1733  if ( pFilterData )
1734  {
1735  for ( const auto& rPropVal : *pFilterData )
1736  {
1737  if ( rPropVal.Name == "AdditionalChunks" )
1738  {
1739  css::uno::Sequence< css::beans::PropertyValue > aAdditionalChunkSequence;
1740  if ( rPropVal.Value >>= aAdditionalChunkSequence )
1741  {
1742  for ( const auto& rAdditionalChunk : std::as_const(aAdditionalChunkSequence) )
1743  {
1744  if ( rAdditionalChunk.Name.getLength() == 4 )
1745  {
1746  sal_uInt32 nChunkType = 0;
1747  for ( sal_Int32 k = 0; k < 4; k++ )
1748  {
1749  nChunkType <<= 8;
1750  nChunkType |= static_cast<sal_uInt8>(rAdditionalChunk.Name[ k ]);
1751  }
1752  css::uno::Sequence< sal_Int8 > aByteSeq;
1753  if ( rAdditionalChunk.Value >>= aByteSeq )
1754  {
1755  std::vector< vcl::PNGWriter::ChunkData >& rChunkData = aPNGWriter.GetChunks();
1756  if ( !rChunkData.empty() )
1757  {
1758  sal_uInt32 nChunkLen = aByteSeq.getLength();
1759 
1760  vcl::PNGWriter::ChunkData aChunkData;
1761  aChunkData.nType = nChunkType;
1762  if ( nChunkLen )
1763  {
1764  aChunkData.aData.resize( nChunkLen );
1765  memcpy( aChunkData.aData.data(), aByteSeq.getConstArray(), nChunkLen );
1766  }
1767  std::vector< vcl::PNGWriter::ChunkData >::iterator aIter = rChunkData.end() - 1;
1768  rChunkData.insert( aIter, aChunkData );
1769  }
1770  }
1771  }
1772  }
1773  }
1774  }
1775  }
1776  }
1777  aPNGWriter.Write( rOStm );
1778 
1779  if( rOStm.GetError() )
1780  nStatus = ERRCODE_GRFILTER_IOERROR;
1781  }
1782  else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVG ) )
1783  {
1784  bool bDone(false);
1785 
1786  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1787  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1788 
1789  if (rVectorGraphicDataPtr
1790  && rVectorGraphicDataPtr->getType() == VectorGraphicDataType::Svg
1791  && !rVectorGraphicDataPtr->getBinaryDataContainer().isEmpty())
1792  {
1793  auto & aDataContainer = rVectorGraphicDataPtr->getBinaryDataContainer();
1794  rOStm.WriteBytes(aDataContainer.getData(), aDataContainer.getSize());
1795 
1796  if( rOStm.GetError() )
1797  {
1798  nStatus = ERRCODE_GRFILTER_IOERROR;
1799  }
1800  else
1801  {
1802  bDone = true;
1803  }
1804  }
1805 
1806  if( !bDone )
1807  {
1808  // do the normal GDIMetaFile export instead
1809  try
1810  {
1811  css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1812 
1813  css::uno::Reference< css::xml::sax::XDocumentHandler > xSaxWriter(
1814  css::xml::sax::Writer::create( xContext ), css::uno::UNO_QUERY_THROW);
1815  css::uno::Sequence< css::uno::Any > aArguments( 1 );
1816  aArguments[ 0 ] <<= aConfigItem.GetFilterData();
1817  css::uno::Reference< css::svg::XSVGWriter > xSVGWriter(
1818  xContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.svg.SVGWriter", aArguments, xContext),
1819  css::uno::UNO_QUERY );
1820  if( xSaxWriter.is() && xSVGWriter.is() )
1821  {
1822  css::uno::Reference< css::io::XActiveDataSource > xActiveDataSource(
1823  xSaxWriter, css::uno::UNO_QUERY );
1824 
1825  if( xActiveDataSource.is() )
1826  {
1827  const css::uno::Reference< css::uno::XInterface > xStmIf(
1828  static_cast< ::cppu::OWeakObject* >( new ImpFilterOutputStream( rOStm ) ) );
1829 
1830  SvMemoryStream aMemStm( 65535, 65535 );
1831 
1832  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1833  const_cast<GDIMetaFile&>( aGraphic.GetGDIMetaFile() ).Write( aMemStm );
1834 
1835  xActiveDataSource->setOutputStream( css::uno::Reference< css::io::XOutputStream >(
1836  xStmIf, css::uno::UNO_QUERY ) );
1837  css::uno::Sequence< sal_Int8 > aMtfSeq( static_cast<sal_Int8 const *>(aMemStm.GetData()), aMemStm.Tell() );
1838  xSVGWriter->write( xSaxWriter, aMtfSeq );
1839  }
1840  }
1841  }
1842  catch(const css::uno::Exception&)
1843  {
1844  nStatus = ERRCODE_GRFILTER_IOERROR;
1845  }
1846  }
1847  }
1848  else
1849  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1850  }
1851  if( nStatus != ERRCODE_NONE )
1852  {
1853  ImplSetError( nStatus, &rOStm );
1854  }
1855  return nStatus;
1856 }
1857 
1858 
1860 {
1861  pErrorEx->nStreamError = ERRCODE_NONE;
1862 }
1863 
1865 {
1866  Link<ConvertData&,bool> aLink( LINK( const_cast<GraphicFilter*>(this), GraphicFilter, FilterCallback ) );
1867  return aLink;
1868 }
1869 
1870 IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
1871 {
1872  bool bRet = false;
1873 
1874  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
1875  OUString aShortName;
1876  css::uno::Sequence< css::beans::PropertyValue > aFilterData;
1877  switch( rData.mnFormat )
1878  {
1879  case ConvertDataFormat::BMP: aShortName = BMP_SHORTNAME; break;
1880  case ConvertDataFormat::GIF: aShortName = GIF_SHORTNAME; break;
1881  case ConvertDataFormat::JPG: aShortName = JPG_SHORTNAME; break;
1882  case ConvertDataFormat::MET: aShortName = MET_SHORTNAME; break;
1883  case ConvertDataFormat::PCT: aShortName = PCT_SHORTNAME; break;
1884  case ConvertDataFormat::PNG: aShortName = PNG_SHORTNAME; break;
1885  case ConvertDataFormat::SVM: aShortName = SVM_SHORTNAME; break;
1886  case ConvertDataFormat::TIF: aShortName = TIF_SHORTNAME; break;
1887  case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
1888  case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
1889  case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
1890 
1891  default:
1892  break;
1893  }
1894  if( GraphicType::NONE == rData.maGraphic.GetType() || rData.maGraphic.GetReaderContext() ) // Import
1895  {
1896  // Import
1897  nFormat = GetImportFormatNumberForShortName( aShortName );
1898  bRet = ImportGraphic( rData.maGraphic, OUString(), rData.mrStm, nFormat ) == ERRCODE_NONE;
1899  }
1900  else if( !aShortName.isEmpty() )
1901  {
1902  // Export
1903 #if defined(IOS) || defined(ANDROID)
1904  if (aShortName == PNG_SHORTNAME)
1905  {
1906  aFilterData.realloc(aFilterData.getLength() + 1);
1907  aFilterData[aFilterData.getLength() - 1].Name = "Compression";
1908  // We "know" that this gets passed to zlib's deflateInit2_(). 1 means best speed.
1909  aFilterData[aFilterData.getLength() - 1].Value <<= static_cast<sal_Int32>(1);
1910  }
1911 #endif
1912  nFormat = GetExportFormatNumberForShortName( aShortName );
1913  bRet = ExportGraphic( rData.maGraphic, OUString(), rData.mrStm, nFormat, &aFilterData ) == ERRCODE_NONE;
1914  }
1915 
1916  return bRet;
1917 }
1918 
1919 namespace
1920 {
1921  class StandardGraphicFilter
1922  {
1923  public:
1924  StandardGraphicFilter()
1925  {
1926  m_aFilter.GetImportFormatCount();
1927  }
1928  GraphicFilter m_aFilter;
1929  };
1930 
1931  class theGraphicFilter : public rtl::Static<StandardGraphicFilter, theGraphicFilter> {};
1932 }
1933 
1935 {
1936  return theGraphicFilter::get().m_aFilter;
1937 }
1938 
1939 ErrCode GraphicFilter::LoadGraphic( const OUString &rPath, const OUString &rFilterName,
1940  Graphic& rGraphic, GraphicFilter* pFilter,
1941  sal_uInt16* pDeterminedFormat )
1942 {
1943  if ( !pFilter )
1944  pFilter = &GetGraphicFilter();
1945 
1946  const sal_uInt16 nFilter = !rFilterName.isEmpty() && pFilter->GetImportFormatCount()
1947  ? pFilter->GetImportFormatNumber( rFilterName )
1949 
1950  INetURLObject aURL( rPath );
1951  if ( aURL.HasError() )
1952  {
1953  aURL.SetSmartProtocol( INetProtocol::File );
1954  aURL.SetSmartURL( rPath );
1955  }
1956 
1957  std::unique_ptr<SvStream> pStream;
1958  if ( INetProtocol::File != aURL.GetProtocol() )
1959  pStream = ::utl::UcbStreamHelper::CreateStream( rPath, StreamMode::READ );
1960 
1961  ErrCode nRes = ERRCODE_NONE;
1962  if ( !pStream )
1963  nRes = pFilter->ImportGraphic( rGraphic, aURL, nFilter, pDeterminedFormat );
1964  else
1965  nRes = pFilter->ImportGraphic( rGraphic, rPath, *pStream, nFilter, pDeterminedFormat );
1966 
1967 #ifdef DBG_UTIL
1968  OUString aReturnString;
1969 
1970  if (nRes == ERRCODE_GRFILTER_OPENERROR)
1971  aReturnString="open error";
1972  else if (nRes == ERRCODE_GRFILTER_IOERROR)
1973  aReturnString="IO error";
1974  else if (nRes == ERRCODE_GRFILTER_FORMATERROR)
1975  aReturnString="format error";
1976  else if (nRes == ERRCODE_GRFILTER_VERSIONERROR)
1977  aReturnString="version error";
1978  else if (nRes == ERRCODE_GRFILTER_FILTERERROR)
1979  aReturnString="filter error";
1980  else if (nRes == ERRCODE_GRFILTER_TOOBIG)
1981  aReturnString="graphic is too big";
1982 
1983  SAL_INFO_IF( nRes, "vcl.filter", "Problem importing graphic " << rPath << ". Reason: " << aReturnString );
1984 #endif
1985 
1986  return nRes;
1987 }
1988 
1989 ErrCode GraphicFilter::compressAsPNG(const Graphic& rGraphic, SvStream& rOutputStream)
1990 {
1991  css::uno::Sequence< css::beans::PropertyValue > aFilterData(1);
1992  aFilterData[0].Name = "Compression";
1993  aFilterData[0].Value <<= sal_uInt32(9);
1994 
1995  sal_uInt16 nFilterFormat = GetExportFormatNumberForShortName(u"PNG");
1996  return ExportGraphic(rGraphic, OUString(), rOutputStream, nFilterFormat, &aFilterData);
1997 }
1998 
1999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetDummyContext(bool value)
Definition: graph.cxx:487
bool ImportEpsGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ieps.cxx:582
OUString GetImportFormatExtension(sal_uInt16 nFormat, sal_Int32 nEntry=0)
#define IMP_MOV
VectorGraphicDataType
bool IsExportPixelFormat(sal_uInt16 nFormat)
SvStream & ReadInt16(sal_Int16 &rInt16)
static ErrCode readSVG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, std::unique_ptr< sal_uInt8[]> &rpGraphicContent, sal_Int32 &rGraphicContentSize)
OUString GetExportFormatName(sal_uInt16 nFormat)
Only create a bitmap, do not read pixel data.
URL aURL
Read pixel data into an existing bitmap.
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
sal_uInt16 GetImportFormatNumberForTypeName(std::u16string_view rType)
bool ImportTiffGraphicImport(SvStream &rStream, Graphic &rGraphic)
Definition: itiff.cxx:1715
void readGraphic(Graphic &rGraphic)
OUString GetImportFilterName(sal_uInt16 nFormat)
void setPrepared(bool bAnimated, const Size *pSizeHint)
Definition: impgraph.cxx:377
static ErrCode readEPS(SvStream &rStream, Graphic &rGraphic)
void setWidth(tools::Long nWidth)
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1521
UNOTOOLS_DLLPUBLIC bool IsDocument(OUString const &url)
ErrCode CanImportGraphic(const INetURLObject &rPath, sal_uInt16 nFormat, sal_uInt16 *pDeterminedFormat)
bool BmpReader(SvStream &rStream, Graphic &rGraphic)
Definition: BmpReader.cxx:23
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
static ErrCode readWMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, WmfExternal const *pExtHeader)
sal_uIntPtr sal_uLong
#define SAL_INFO_IF(condition, area, stream)
ErrCode compressAsPNG(const Graphic &rGraphic, SvStream &rOutputStream)
long Long
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: graph.cxx:380
OUString GetImportFormatName(sal_uInt16 nFormat)
virtual void doWork()=0
static ErrCode readGIF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
#define ZCODEC_DEFAULT_COMPRESSION
static ErrCode readPSD(SvStream &rStream, Graphic &rGraphic)
bool isPCT(SvStream &rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
GraphicType
Definition: graph.hxx:34
#define STREAM_SEEK_TO_END
exports com.sun.star. graphic
bool ImportPcdGraphic(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
Definition: ipcd.cxx:357
sal_uInt64 Seek(sal_uInt64 nPos)
bool read(BitmapEx &rBitmap)
OUString aFilterPath
Class to import and export graphic formats.
void Flush()
tools::Long Decompress(SvStream &rIStm, SvStream &rOStm)
bool ExportTiffGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
Definition: etiff.cxx:580
This template handles BitmapAccess the RAII way.
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
#define IMP_PICT
bool HasError() const
sal_uInt16 GetImportFormatNumberForExtension(std::u16string_view rExt)
get the index of the filter that matches this extension
#define ERRCODE_GRFILTER_IOERROR
OUString GetExportFormatExtension(sal_uInt16 nFormat, sal_Int32 nEntry=0)
Information about errors during the GraphicFilter operation.
#define IMP_EPS
void waitUntilDone(const std::shared_ptr< ThreadTaskTag > &, bool bJoin=true)
#define EXP_GIF
static ErrCode readPDF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: BitmapEx.cxx:374
sal_uInt64 SeekRel(sal_Int64 nPos)
#define IMP_JPEG
bool ImportRasGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: iras.cxx:398
bool IsGfxLink() const
Definition: graph.cxx:513
OUString GetExportInternalFilterName(sal_uInt16 nFormat)
OUString GetExportInternalFilterName(sal_uInt16 nFormat)
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1073
#define EXP_JPEG
sal_Int32 ReadInt32(const OUString &rKey, sal_Int32 nDefault)
Graphic ImportUnloadedGraphic(SvStream &rIStream, sal_uInt64 sizeLimit=0, const Size *pSizeHint=nullptr)
constexpr tools::Long Width() const
HashMap_OWString_Interface aMap
OUString GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
void Clear()
Definition: graph.cxx:288
static ErrCode readDXF(SvStream &rStream, Graphic &rGraphic)
#define TIF_SHORTNAME
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
#define JPG_SHORTNAME
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
bool IsAlpha() const
Definition: BitmapEx.cxx:193
#define IMP_PCD
ErrCode GetError() const
Sequence< PropertyValue > aArguments
Reference< XInputStream > xStream
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
static ErrCode readPCX(SvStream &rStream, Graphic &rGraphic)
#define EXP_TIFF
const Reference< XComponentContext > & m_rContext
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define EXP_SVMETAFILE
sal_uInt8 * ImplSearchEntry(sal_uInt8 *pSource, sal_uInt8 const *pDest, sal_uLong nComp, sal_uLong nSize)
OUString GetImportFilterType(sal_uInt16 nFormat)
static bool IsFuzzing()
#define PNG_SHORTNAME
static ErrCode readTGA(SvStream &rStream, Graphic &rGraphic)
bool ConvertGDIMetaFileToEMF(const GDIMetaFile &rMTF, SvStream &rTargetStream)
Definition: wmf.cxx:110
void ImportGraphics(std::vector< std::shared_ptr< Graphic > > &rGraphics, std::vector< std::unique_ptr< SvStream > > vStreams)
Imports multiple graphics.
bool ExportJPEG(SvStream &rOutputStream, const Graphic &rGraphic, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData, bool *pExportWasGrey)
Definition: jpeg.cxx:53
#define ERRCODE_GRFILTER_OPENERROR
sal_uInt16 GetExportFormatCount() const
static ErrCode readRAS(SvStream &rStream, Graphic &rGraphic)
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:340
#define BMP_SHORTNAME
#define IMP_DXF
#define ERRCODE_GRFILTER_FORMATERROR
bool ImportPNG(SvStream &rInputStream, Graphic &rGraphic, GraphicFilterImportFlags nImportFlags, BitmapScopedWriteAccess *pAccess, AlphaScopedWriteAccess *pAlphaAccess)
bool IsExportPixelFormat(sal_uInt16 nFormat)
OUString GetImportFormatShortName(sal_uInt16 nFormat)
VCL_DLLPUBLIC bool ImportGIF(SvStream &rStm, Graphic &rGraphic)
Definition: gifread.cxx:969
constexpr tools::Long getHeight() const
VCL_DLLPUBLIC bool ImportXPM(SvStream &rStm, Graphic &rGraphic)
Definition: xpmread.cxx:672
sal_uInt64 remainingSize()
sal_uInt16 GetImportFormatCount() const
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
OUString GetExportFormatName(sal_uInt16 nFormat)
void SetGfxLink(const std::shared_ptr< GfxLink > &rGfxLink)
Definition: graph.cxx:497
OUString GetExportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
ErrCode ImpTestOrFindFormat(const OUString &rPath, SvStream &rStream, sal_uInt16 &rFormat)
GraphicFilter(bool bUseConfig=true)
static ErrCode readPBM(SvStream &rStream, Graphic &rGraphic)
#define IMP_SVMETAFILE
static ThreadPool & getSharedOptimalPool()
DocumentType eType
#define IMP_RAS
static ErrCode LoadGraphic(const OUString &rPath, const OUString &rFilter, Graphic &rGraphic, GraphicFilter *pFilter=nullptr, sal_uInt16 *pDeterminedFormat=nullptr)
static ErrCode readJPEG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, GraphicFilterImportFlags nImportFlags)
#define IMP_BMP
#define EXP_SVG
static ErrCode readTIFF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
OUString GetImportFormatMediaType(sal_uInt16 nFormat)
bool ImportPsdGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipsd.cxx:765
SAL_DLLPRIVATE ImpGraphic * ImplGetImpGraphic() const
Definition: graph.hxx:89
Cache to keep list of graphic filters + the filters themselves.
void Draw(OutputDevice *pOutDev, const Point &rDestPt) const
Definition: graph.cxx:427
bool ConvertGraphicToWMF(const Graphic &rGraphic, SvStream &rTargetStream, FilterConfigItem const *pConfigItem, bool bPlaceable)
Definition: wmf.cxx:87
#define IMP_PBM
int i
void pushTask(std::unique_ptr< ThreadTask > pTask)
::osl::Mutex & getListMutex()
OUString GetImportFormatTypeName(sal_uInt16 nFormat)
std::vector< vcl::PNGWriter::ChunkData > & GetChunks()
Definition: pngwrite.cxx:647
GraphicType GetType() const
Definition: graph.cxx:294
#define EMF_SHORTNAME
void SetSmartProtocol(INetProtocol eTheSmartScheme)
static std::unique_ptr< sal_uInt8[]> getMicrosoftGifChunk(SvStream &rStream, sal_Int32 *chunkSize=nullptr)
#define STREAM_SEEK_TO_BEGIN
std::unique_ptr< FilterErrorEx > pErrorEx
sal_uInt16 GetExportFormatNumber(std::u16string_view rFormatName)
void MakeGraphicsAvailableThreaded(std::vector< Graphic * > &rGraphics)
Tries to ensure all Graphic objects are available (Graphic::isAvailable()).
FilterConfigCache * pConfig
sal_uInt16 GetImportFormatNumberForTypeName(std::u16string_view rType)
sal_uInt16 GetExportFormatNumber(std::u16string_view rFormatName)
VCL_DLLPUBLIC bool ImportXBM(SvStream &rStm, Graphic &rGraphic)
Definition: xbmread.cxx:371
std::size_t WriteBytes(const void *pData, std::size_t nSize)
const BitmapEx & GetBitmapExRef() const
Gives direct access to the contained BitmapEx.
Definition: graph.cxx:345
sal_uInt16 GetExportFormatNumberForMediaType(std::u16string_view rShortName)
float u
void BeginCompression(int nCompressLevel=ZCODEC_DEFAULT_COMPRESSION, bool gzLib=false)
tools::Long EndCompression()
#define IMP_XBM
static ErrCode readWithTypeSerializer(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, OUString aFilterName)
#define IMP_SVG
#define GRFILTER_FORMAT_DONTKNOW
static ErrCode readEMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, WmfExternal const *pExtHeader)
static ErrCode readPNG(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, std::unique_ptr< sal_uInt8[]> &rpGraphicContent, sal_Int32 &rGraphicContentSize)
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
OUString GetImportFilterTypeName(sal_uInt16 nFormat)
void SetVersion(sal_Int32 n)
sal_Int16 nVersion
GfxLink GetGfxLink() const
Definition: graph.cxx:508
bool ExportEpsGraphic(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
Definition: eps.cxx:2665
Link< ConvertData &, bool > GetFilterCallback() const
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
#define IMP_PSD
#define IMP_TIFF
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
static ErrCode readXBM(SvStream &rStream, Graphic &rGraphic)
oslInterlockedCount m_nStatus
IMPL_LINK(GraphicFilter, FilterCallback, ConvertData &, rData, bool)
OUString GetImportFormatName(sal_uInt16 nFormat)
OUString GetImportFormatShortName(sal_uInt16 nFormat)
std::size_t ReadBytes(void *pData, std::size_t nSize)
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1066
Size GetPrefSize() const
Definition: graph.cxx:364
bool ExportGifGraphic(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
Definition: egif.cxx:543
#define IMP_MET
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetExportFormatShortName(sal_uInt16 nFormat)
#define ERRCODE_GRFILTER_TOOBIG
bool ImportDxfGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: idxf.cxx:28
SvStreamEndian GetEndian() const
#define ERRCODE_GRFILTER_FILTERERROR
#define ERRCODE_GRFILTER_VERSIONERROR
#define IMP_WMF
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
#define EXP_EPS
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
static OUString ImpGetExtension(const OUString &rPath)
const css::uno::Sequence< css::beans::PropertyValue > & GetFilterData() const
static ErrCode readXPM(SvStream &rStream, Graphic &rGraphic)
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
static FilterList_impl * pFilterHdlList
#define SAL_WARN_IF(condition, area, stream)
#define ERRCODE_NONE
Definition: errcode.hxx:196
MapMode GetPrefMapMode() const
Definition: graph.cxx:375
constexpr tools::Long Height() const
unsigned char sal_uInt8
#define EXP_WMF
sal_uInt16 GetImportFormatCount() const
#define IMP_PNG
bool ImportMetGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ios2met.cxx:2790
void SetEndian(SvStreamEndian SvStreamEndian)
#define SAL_INFO(area, stream)
#define IMP_PCX
std::shared_ptr< GraphicReader > & GetReaderContext()
Definition: graph.cxx:477
INetProtocol GetProtocol() const
::std::vector< GraphicFilter * > FilterList_impl
OUString GetFileExtension() const
#define IMP_GIF
sal_uInt64 Tell() const
Reference< XComponentContext > getProcessComponentContext()
VCL_DLLPUBLIC bool ImportJPEG(SvStream &rInputStream, Graphic &rGraphic, GraphicFilterImportFlags nImportFlags, BitmapScopedWriteAccess *ppAccess)
Definition: jpeg.cxx:26
static std::shared_ptr< ThreadTaskTag > createThreadTaskTag()
OUString GetExportWildcard(sal_uInt16 nFormat)
bool peekGraphicFormat(SvStream &rStream, OUString &rFormatExtension, bool bTest)
#define IMP_PDF
#define EXP_EMF
OUString GetExportFilterName(sal_uInt16 nFormat)
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:369
void WriteInt32(const OUString &rKey, sal_Int32 nValue)
ErrCode ImplSetError(ErrCode nError, const SvStream *pStm=nullptr)
#define IMP_XPM
sal_uInt16 GetExportFormatNumberForMediaType(std::u16string_view rMediaType)
void setHeight(tools::Long nHeight)
#define EXP_BMP
#define ERRCODE_IO_PENDING
Definition: errcode.hxx:225
bool ImportPcxGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipcx.cxx:402
OUString GetExportFormatShortName(sal_uInt16 nFormat)
static GraphicFilter & GetGraphicFilter()
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
#define MET_SHORTNAME
SvStreamEndian
#define SVM_SHORTNAME
static ErrCode readMET(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
virtual void ResetError()
constexpr tools::Long getWidth() const
bool ImportPictGraphic(SvStream &rIStm, Graphic &rGraphic)
Definition: ipict.cxx:1999
static Graphic ImpGetScaledGraphic(const Graphic &rGraphic, FilterConfigItem &rConfigItem)
void SetDefaultType()
Definition: graph.cxx:299
static ErrCode readPICT(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
bool BmpWriter(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
Definition: BmpWriter.cxx:23
static ErrCode readBMP(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType)
static ErrCode readWMF_EMF(SvStream &rStream, Graphic &rGraphic, GfxLinkType &rLinkType, WmfExternal const *pExtHeader, VectorGraphicDataType eType)
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:523
GraphicFilterImportFlags
#define IMP_EMF
#define SVG_SHORTNAME
UNOTOOLS_DLLPUBLIC bool Kill(OUString const &url)
#define IMP_TGA
bool ImportPDF(SvStream &rStream, Graphic &rGraphic)
Imports a PDF stream into rGraphic.
Definition: pdfread.cxx:245
std::vector< sal_uInt8 > aData
Definition: pngwrite.hxx:52
#define GIF_SHORTNAME
sal_uInt16 GetExportFormatCount() const
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
bool ImportPbmGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: ipbm.cxx:534
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
#define PCT_SHORTNAME
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
#define WMF_SHORTNAME
bool IsDummyContext() const
Definition: graph.cxx:492
static ErrCode readPCD(SvStream &rStream, Graphic &rGraphic)
SvStream & Write(SvStream &rOStm)
Definition: gdimtf.cxx:2741
OUString GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
bool SetSmartURL(OUString const &rTheAbsURIRef, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
const void * GetData()
bool ImportTgaGraphic(SvStream &rStream, Graphic &rGraphic)
Definition: itga.cxx:784
#define EXP_PNG
bool IsGIFAnimated(SvStream &rStm, Size &rLogicSize)
Definition: gifread.cxx:956