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 <vcl/dibtools.hxx>
33 #include <fltcall.hxx>
34 #include <vcl/salctype.hxx>
35 #include <vcl/pngread.hxx>
36 #include <vcl/pngwrite.hxx>
38 #include <vcl/virdev.hxx>
39 #include <impgraph.hxx>
40 #include <vcl/svapp.hxx>
41 #include <osl/file.hxx>
42 #include <vcl/graphicfilter.hxx>
43 #include <vcl/FilterConfigItem.hxx>
44 #include <vcl/wmf.hxx>
45 #include "igif/gifread.hxx"
46 #include <vcl/pdfread.hxx>
47 #include "jpeg/jpeg.hxx"
48 #include "ixbm/xbmread.hxx"
49 #include "ixpm/xpmread.hxx"
50 #include <osl/module.hxx>
51 #include <com/sun/star/uno/Reference.h>
52 #include <com/sun/star/awt/Size.hpp>
53 #include <com/sun/star/uno/XInterface.hpp>
54 #include <com/sun/star/io/XActiveDataSource.hpp>
55 #include <com/sun/star/io/XOutputStream.hpp>
56 #include <com/sun/star/svg/XSVGWriter.hpp>
57 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
58 #include <com/sun/star/xml/sax/Writer.hpp>
60 #include <rtl/bootstrap.hxx>
61 #include <rtl/instance.hxx>
62 #include <tools/svlibrary.h>
63 #include <comphelper/string.hxx>
64 #include <unotools/ucbhelper.hxx>
65 #include <vector>
66 #include <memory>
67 #include <string_view>
68 
69 #include "FilterConfigCache.hxx"
71 
74 
75 #define PMGCHUNG_msOG 0x6d734f47 // Microsoft Office Animated GIF
76 
77 typedef ::std::vector< GraphicFilter* > FilterList_impl;
78 static FilterList_impl* pFilterHdlList = nullptr;
79 
80 static ::osl::Mutex& getListMutex()
81 {
82  static ::osl::Mutex s_aListProtection;
83  return s_aListProtection;
84 }
85 
86 namespace {
87 
88 class ImpFilterOutputStream : public ::cppu::WeakImplHelper< css::io::XOutputStream >
89 {
90  SvStream& mrStm;
91 
92  virtual void SAL_CALL writeBytes( const css::uno::Sequence< sal_Int8 >& rData ) override
93  { mrStm.WriteBytes(rData.getConstArray(), rData.getLength()); }
94  virtual void SAL_CALL flush() override
95  { mrStm.Flush(); }
96  virtual void SAL_CALL closeOutput() override {}
97 
98 public:
99 
100  explicit ImpFilterOutputStream( SvStream& rStm ) : mrStm( rStm ) {}
101 };
102 
103 }
104 
105 // Helper functions
106 
107 sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize )
108 {
109  while ( nComp-- >= nSize )
110  {
111  sal_uLong i;
112  for ( i = 0; i < nSize; i++ )
113  {
114  if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
115  break;
116  }
117  if ( i == nSize )
118  return pSource;
119  pSource++;
120  }
121  return nullptr;
122 }
123 
124 static OUString ImpGetExtension( const OUString &rPath )
125 {
126  OUString aExt;
127  INetURLObject aURL( rPath );
128  aExt = aURL.GetFileExtension().toAsciiUpperCase();
129  return aExt;
130 }
131 
132 bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
133 {
134  sal_uInt8 sBuf[3];
135  // store number format
136  SvStreamEndian oldNumberFormat = rStream.GetEndian();
137  sal_uInt32 nOffset; // in MS documents the pict format is used without the first 512 bytes
138  for ( nOffset = 0; ( nOffset <= 512 ) && ( ( nStreamPos + nOffset + 14 ) <= nStreamLen ); nOffset += 512 )
139  {
140  short y1,x1,y2,x2;
141  bool bdBoxOk = true;
142 
143  rStream.Seek( nStreamPos + nOffset);
144  // size of the pict in version 1 pict ( 2bytes) : ignored
145  rStream.SeekRel(2);
146  // bounding box (bytes 2 -> 9)
147  rStream.SetEndian(SvStreamEndian::BIG);
148  rStream.ReadInt16( y1 ).ReadInt16( x1 ).ReadInt16( y2 ).ReadInt16( x2 );
149  rStream.SetEndian(oldNumberFormat); // reset format
150 
151  if (x1 > x2 || y1 > y2 || // bad bdbox
152  (x1 == x2 && y1 == y2) || // 1 pixel picture
153  x2-x1 > 2048 || y2-y1 > 2048 ) // picture abnormally big
154  bdBoxOk = false;
155 
156  // read version op
157  rStream.ReadBytes(sBuf, 3);
158  // see http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Imaging_With_QuickDraw/Appendix_A.pdf
159  // normal version 2 - page A23 and A24
160  if ( sBuf[ 0 ] == 0x00 && sBuf[ 1 ] == 0x11 && sBuf[ 2 ] == 0x02)
161  return true;
162  // normal version 1 - page A25
163  else if (sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 && bdBoxOk)
164  return true;
165  }
166  return false;
167 }
168 
169 /*************************************************************************
170  *
171  * ImpPeekGraphicFormat()
172  *
173  * Description:
174  * This function is two-fold:
175  * 1.) Start reading file, determine the file format:
176  * Input parameters:
177  * rPath - file path
178  * rFormatExtension - content matter
179  * bTest - set false
180  * Output parameters:
181  * Return value - true if success
182  * rFormatExtension - on success: normal file extension in capitals
183  * 2.) Start reading file, verify file format
184  * Input parameters:
185  * rPath - file path
186  * rFormatExtension - normal file extension in capitals
187  * bTest - set true
188  * Output parameters:
189  * Return value - false, if cannot verify the file type
190  * passed to the function
191  * true, when the format is PROBABLY verified or
192  * WHEN THE FORMAT IS NOT KNOWN!
193  *
194  *************************************************************************/
195 
196 bool ImpPeekGraphicFormat( SvStream& rStream, OUString& rFormatExtension, bool bTest )
197 {
198  vcl::GraphicFormatDetector aDetector(rStream, rFormatExtension);
199  if (!aDetector.detect())
200  return false;
201 
202  // The following variable is used when bTest == true. It remains false
203  // if the format (rFormatExtension) has not yet been set.
204  bool bSomethingTested = false;
205 
206  // Now the different formats are checked. The order *does* matter. e.g. a MET file
207  // could also go through the BMP test, however, a BMP file can hardly go through the MET test.
208  // So MET should be tested prior to BMP. However, theoretically a BMP file could conceivably
209  // go through the MET test. These problems are of course not only in MET and BMP.
210  // Therefore, in the case of a format check (bTest == true) we only test *exactly* this
211  // format. Everything else could have fatal consequences, for example if the user says it is
212  // a BMP file (and it is a BMP) file, and the file would go through the MET test ...
213 
214  if (!bTest || rFormatExtension.startsWith("MET"))
215  {
216  bSomethingTested = true;
217  if (aDetector.checkMET())
218  {
219  rFormatExtension = aDetector.msDetectedFormat;
220  return true;
221  }
222  }
223 
224  if (!bTest || rFormatExtension.startsWith("BMP"))
225  {
226  bSomethingTested = true;
227  if (aDetector.checkBMP())
228  {
229  rFormatExtension = aDetector.msDetectedFormat;
230  return true;
231  }
232  }
233 
234  if (!bTest ||
235  rFormatExtension.startsWith("WMF") ||
236  rFormatExtension.startsWith("EMF"))
237  {
238  bSomethingTested = true;
239  if (aDetector.checkWMForEMF())
240  {
241  rFormatExtension = aDetector.msDetectedFormat;
242  return true;
243  }
244  }
245 
246  if (!bTest || rFormatExtension.startsWith("PCX"))
247  {
248  bSomethingTested = true;
249  if (aDetector.checkPCX())
250  {
251  rFormatExtension = aDetector.msDetectedFormat;
252  return true;
253  }
254  }
255 
256  if (!bTest || rFormatExtension.startsWith("TIF"))
257  {
258  bSomethingTested = true;
259  if (aDetector.checkTIF())
260  {
261  rFormatExtension = aDetector.msDetectedFormat;
262  return true;
263  }
264  }
265 
266  if (!bTest || rFormatExtension.startsWith("GIF"))
267  {
268  bSomethingTested = true;
269  if (aDetector.checkGIF())
270  {
271  rFormatExtension = aDetector.msDetectedFormat;
272  return true;
273  }
274  }
275 
276  if (!bTest || rFormatExtension.startsWith("PNG"))
277  {
278  bSomethingTested = true;
279  if (aDetector.checkPNG())
280  {
281  rFormatExtension = aDetector.msDetectedFormat;
282  return true;
283  }
284  }
285 
286  if (!bTest || rFormatExtension.startsWith("JPG"))
287  {
288  bSomethingTested = true;
289  if (aDetector.checkJPG())
290  {
291  rFormatExtension = aDetector.msDetectedFormat;
292  return true;
293  }
294  }
295 
296  if (!bTest || rFormatExtension.startsWith("SVM"))
297  {
298  bSomethingTested = true;
299  if (aDetector.checkSVM())
300  {
301  rFormatExtension = aDetector.msDetectedFormat;
302  return true;
303  }
304  }
305 
306  if (!bTest || rFormatExtension.startsWith("PCD"))
307  {
308  bSomethingTested = true;
309  if (aDetector.checkPCD())
310  {
311  rFormatExtension = aDetector.msDetectedFormat;
312  return true;
313  }
314  }
315 
316  if (!bTest || rFormatExtension.startsWith("PSD"))
317  {
318  bSomethingTested = true;
319  if (aDetector.checkPSD())
320  {
321  rFormatExtension = aDetector.msDetectedFormat;
322  return true;
323  }
324  }
325 
326  if (!bTest || rFormatExtension.startsWith("EPS"))
327  {
328  bSomethingTested = true;
329  if (aDetector.checkEPS())
330  {
331  rFormatExtension = aDetector.msDetectedFormat;
332  return true;
333  }
334  }
335 
336  if (!bTest || rFormatExtension.startsWith("DXF"))
337  {
338  if (aDetector.checkDXF())
339  {
340  rFormatExtension = aDetector.msDetectedFormat;
341  return true;
342  }
343  }
344 
345  if (!bTest || rFormatExtension.startsWith("PCT"))
346  {
347  bSomethingTested = true;
348  if (aDetector.checkPCT())
349  {
350  rFormatExtension = aDetector.msDetectedFormat;
351  return true;
352  }
353  }
354 
355  if (!bTest ||
356  rFormatExtension.startsWith("PBM") ||
357  rFormatExtension.startsWith("PGM") ||
358  rFormatExtension.startsWith("PPM"))
359  {
360  bSomethingTested = true;
361  if (aDetector.checkPBMorPGMorPPM())
362  {
363  rFormatExtension = aDetector.msDetectedFormat;
364  return true;
365  }
366  }
367 
368  if (!bTest || rFormatExtension.startsWith("RAS"))
369  {
370  bSomethingTested = true;
371  if (aDetector.checkRAS())
372  {
373  rFormatExtension = aDetector.msDetectedFormat;
374  return true;
375  }
376  }
377 
378  if (!bTest)
379  {
380  bSomethingTested = true;
381  if (aDetector.checkXPM())
382  {
383  rFormatExtension = aDetector.msDetectedFormat;
384  return true;
385  }
386 
387  }
388  else if (rFormatExtension.startsWith("XPM"))
389  {
390  return true;
391  }
392 
393  if (!bTest)
394  {
395  if (aDetector.checkXBM())
396  {
397  rFormatExtension = aDetector.msDetectedFormat;
398  return true;
399  }
400  }
401  else if (rFormatExtension.startsWith("XBM"))
402  {
403  return true;
404  }
405 
406  if (!bTest)
407  {
408  if (aDetector.checkSVG())
409  {
410  rFormatExtension = aDetector.msDetectedFormat;
411  return true;
412  }
413  }
414  else if (rFormatExtension.startsWith("SVG"))
415  {
416  return true;
417  }
418 
419  if (!bTest || rFormatExtension.startsWith("TGA"))
420  {
421  bSomethingTested = true;
422  if (aDetector.checkTGA())
423  {
424  rFormatExtension = aDetector.msDetectedFormat;
425  return true;
426  }
427  }
428 
429  if (!bTest || rFormatExtension.startsWith("MOV"))
430  {
431  if (aDetector.checkMOV())
432  {
433  rFormatExtension = aDetector.msDetectedFormat;
434  return true;
435  }
436  }
437 
438  if (!bTest || rFormatExtension.startsWith("PDF"))
439  {
440  if (aDetector.checkPDF())
441  {
442  rFormatExtension = aDetector.msDetectedFormat;
443  return true;
444  }
445  }
446 
447  return bTest && !bSomethingTested;
448 }
449 
450 ErrCode GraphicFilter::ImpTestOrFindFormat( const OUString& rPath, SvStream& rStream, sal_uInt16& rFormat )
451 {
452  // determine or check the filter/format by reading into it
453  if( rFormat == GRFILTER_FORMAT_DONTKNOW )
454  {
455  OUString aFormatExt;
456  if( ImpPeekGraphicFormat( rStream, aFormatExt, false ) )
457  {
458  rFormat = pConfig->GetImportFormatNumberForExtension( aFormatExt );
459  if( rFormat != GRFILTER_FORMAT_DONTKNOW )
460  return ERRCODE_NONE;
461  }
462  // determine filter by file extension
463  if( !rPath.isEmpty() )
464  {
465  OUString aExt( ImpGetExtension( rPath ) );
466  rFormat = pConfig->GetImportFormatNumberForExtension( aExt );
467  if( rFormat != GRFILTER_FORMAT_DONTKNOW )
468  return ERRCODE_NONE;
469  }
471  }
472  else
473  {
474  OUString aTmpStr( pConfig->GetImportFormatExtension( rFormat ) );
475  aTmpStr = aTmpStr.toAsciiUpperCase();
476  if( !ImpPeekGraphicFormat( rStream, aTmpStr, true ) )
478  if ( pConfig->GetImportFormatExtension( rFormat ).equalsIgnoreAsciiCase( "pcd" ) )
479  {
480  sal_Int32 nBase = 2; // default Base0
481  if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base4" ) )
482  nBase = 1;
483  else if ( pConfig->GetImportFilterType( rFormat ).equalsIgnoreAsciiCase( "pcd_Photo_CD_Base16" ) )
484  nBase = 0;
485  FilterConfigItem aFilterConfigItem( "Office.Common/Filter/Graphic/Import/PCD" );
486  aFilterConfigItem.WriteInt32( "Resolution", nBase );
487  }
488  }
489 
490  return ERRCODE_NONE;
491 }
492 
493 static Graphic ImpGetScaledGraphic( const Graphic& rGraphic, FilterConfigItem& rConfigItem )
494 {
495  Graphic aGraphic;
496 
497  sal_Int32 nLogicalWidth = rConfigItem.ReadInt32( "LogicalWidth", 0 );
498  sal_Int32 nLogicalHeight = rConfigItem.ReadInt32( "LogicalHeight", 0 );
499 
500  if ( rGraphic.GetType() != GraphicType::NONE )
501  {
502  sal_Int32 nMode = rConfigItem.ReadInt32( "ExportMode", -1 );
503 
504  if ( nMode == -1 ) // the property is not there, this is possible, if the graphic filter
505  { // is called via UnoGraphicExporter and not from a graphic export Dialog
506  nMode = 0; // then we are defaulting this mode to 0
507  if ( nLogicalWidth || nLogicalHeight )
508  nMode = 2;
509  }
510 
511  Size aOriginalSize;
512  Size aPrefSize( rGraphic.GetPrefSize() );
513  MapMode aPrefMapMode( rGraphic.GetPrefMapMode() );
514  if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
515  aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MapMode(MapUnit::Map100thMM));
516  else
517  aOriginalSize = OutputDevice::LogicToLogic(aPrefSize, aPrefMapMode, MapMode(MapUnit::Map100thMM));
518  if ( !nLogicalWidth )
519  nLogicalWidth = aOriginalSize.Width();
520  if ( !nLogicalHeight )
521  nLogicalHeight = aOriginalSize.Height();
522  if( rGraphic.GetType() == GraphicType::Bitmap )
523  {
524 
525  // Resolution is set
526  if( nMode == 1 )
527  {
528  BitmapEx aBitmap( rGraphic.GetBitmapEx() );
529  MapMode aMap( MapUnit::Map100thInch );
530 
531  sal_Int32 nDPI = rConfigItem.ReadInt32( "Resolution", 75 );
532  Fraction aFrac( 1, std::clamp( nDPI, sal_Int32(75), sal_Int32(600) ) );
533 
534  aMap.SetScaleX( aFrac );
535  aMap.SetScaleY( aFrac );
536 
537  Size aOldSize = aBitmap.GetSizePixel();
538  aGraphic = rGraphic;
539  aGraphic.SetPrefMapMode( aMap );
540  aGraphic.SetPrefSize( Size( aOldSize.Width() * 100,
541  aOldSize.Height() * 100 ) );
542  }
543  // Size is set
544  else if( nMode == 2 )
545  {
546  aGraphic = rGraphic;
547  aGraphic.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
548  aGraphic.SetPrefSize( Size( nLogicalWidth, nLogicalHeight ) );
549  }
550  else
551  aGraphic = rGraphic;
552 
553  sal_Int32 nColors = rConfigItem.ReadInt32( "Color", 0 );
554  if ( nColors ) // graphic conversion necessary ?
555  {
556  BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
557  aBmpEx.Convert( static_cast<BmpConversion>(nColors) ); // the entries in the xml section have the same meaning as
558  aGraphic = aBmpEx; // they have in the BmpConversion enum, so it should be
559  } // allowed to cast them
560  }
561  else
562  {
563  if( ( nMode == 1 ) || ( nMode == 2 ) )
564  {
565  GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
566  Size aNewSize( OutputDevice::LogicToLogic(Size(nLogicalWidth, nLogicalHeight), MapMode(MapUnit::Map100thMM), aMtf.GetPrefMapMode()) );
567 
568  if( aNewSize.Width() && aNewSize.Height() )
569  {
570  const Size aPreferredSize( aMtf.GetPrefSize() );
571  aMtf.Scale( Fraction( aNewSize.Width(), aPreferredSize.Width() ),
572  Fraction( aNewSize.Height(), aPreferredSize.Height() ) );
573  }
574  aGraphic = Graphic( aMtf );
575  }
576  else
577  aGraphic = rGraphic;
578  }
579 
580  }
581  else
582  aGraphic = rGraphic;
583 
584  return aGraphic;
585 }
586 
587 static OUString ImpCreateFullFilterPath( const OUString& rPath, const OUString& rFilterName )
588 {
589  OUString aPathURL;
590 
591  ::osl::FileBase::getFileURLFromSystemPath( rPath, aPathURL );
592  aPathURL += "/";
593 
594  OUString aSystemPath;
595  ::osl::FileBase::getSystemPathFromFileURL( aPathURL, aSystemPath );
596  aSystemPath += rFilterName;
597 
598  return aSystemPath;
599 }
600 
601 namespace {
602 
603 class ImpFilterLibCache;
604 
605 struct ImpFilterLibCacheEntry
606 {
607  ImpFilterLibCacheEntry* mpNext;
608 #ifndef DISABLE_DYNLOADING
609  osl::Module maLibrary;
610 #endif
611  OUString maFiltername;
612  OUString maFormatName;
613  PFilterCall mpfnImport;
614 
615  ImpFilterLibCacheEntry(const OUString& rPathname, const OUString& rFiltername, const OUString& rFormatName);
616  bool operator==( std::u16string_view rFiltername ) const { return maFiltername == rFiltername; }
617 
618  PFilterCall GetImportFunction();
619 };
620 
621 }
622 
623 ImpFilterLibCacheEntry::ImpFilterLibCacheEntry( const OUString& rPathname, const OUString& rFiltername, const OUString& rFormatName ) :
624  mpNext ( nullptr ),
625 #ifndef DISABLE_DYNLOADING
626  maLibrary ( rPathname ),
627 #endif
628  maFiltername ( rFiltername ),
629  maFormatName ( rFormatName ),
630  mpfnImport ( nullptr )
631 {
632 #ifdef DISABLE_DYNLOADING
633  (void) rPathname;
634 #endif
635 }
636 
637 #ifdef DISABLE_DYNLOADING
638 
639 extern "C" bool icdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
640 extern "C" bool idxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
641 extern "C" bool imeGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
642 extern "C" bool ipbGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
643 extern "C" bool ipdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
644 extern "C" bool ipsGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
645 extern "C" bool iptGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
646 extern "C" bool ipxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
647 extern "C" bool iraGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
648 extern "C" bool itgGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
649 extern "C" bool itiGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
650 
651 #endif
652 
653 PFilterCall ImpFilterLibCacheEntry::GetImportFunction()
654 {
655  if( !mpfnImport )
656  {
657 #ifndef DISABLE_DYNLOADING
658  if (maFormatName == "icd")
659  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("icdGraphicImport"));
660  else if (maFormatName == "idx")
661  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("idxGraphicImport"));
662  else if (maFormatName == "ime")
663  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("imeGraphicImport"));
664  else if (maFormatName == "ipb")
665  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("ipbGraphicImport"));
666  else if (maFormatName == "ipd")
667  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("ipdGraphicImport"));
668  else if (maFormatName == "ips")
669  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("ipsGraphicImport"));
670  else if (maFormatName == "ipt")
671  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("iptGraphicImport"));
672  else if (maFormatName == "ipx")
673  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("ipxGraphicImport"));
674  else if (maFormatName == "ira")
675  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("iraGraphicImport"));
676  else if (maFormatName == "itg")
677  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("itgGraphicImport"));
678  else if (maFormatName == "iti")
679  mpfnImport = reinterpret_cast<PFilterCall>(maLibrary.getFunctionSymbol("itiGraphicImport"));
680  #else
681  if (maFormatName == "icd")
682  mpfnImport = icdGraphicImport;
683  else if (maFormatName == "idx")
684  mpfnImport = idxGraphicImport;
685  else if (maFormatName == "ime")
686  mpfnImport = imeGraphicImport;
687  else if (maFormatName == "ipb")
688  mpfnImport = ipbGraphicImport;
689  else if (maFormatName == "ipd")
690  mpfnImport = ipdGraphicImport;
691  else if (maFormatName == "ips")
692  mpfnImport = ipsGraphicImport;
693  else if (maFormatName == "ipt")
694  mpfnImport = iptGraphicImport;
695  else if (maFormatName == "ipx")
696  mpfnImport = ipxGraphicImport;
697  else if (maFormatName == "ira")
698  mpfnImport = iraGraphicImport;
699  else if (maFormatName == "itg")
700  mpfnImport = itgGraphicImport;
701  else if (maFormatName == "iti")
702  mpfnImport = itiGraphicImport;
703  #endif
704  }
705 
706  return mpfnImport;
707 }
708 
709 namespace {
710 
711 class ImpFilterLibCache
712 {
713  ImpFilterLibCacheEntry* mpFirst;
714  ImpFilterLibCacheEntry* mpLast;
715 
716 public:
717  ImpFilterLibCache();
718  ~ImpFilterLibCache();
719 
720  ImpFilterLibCacheEntry* GetFilter( const OUString& rFilterPath, const OUString& rFiltername, const OUString& rFormatName );
721 };
722 
723 }
724 
725 ImpFilterLibCache::ImpFilterLibCache() :
726  mpFirst ( nullptr ),
727  mpLast ( nullptr )
728 {
729 }
730 
731 ImpFilterLibCache::~ImpFilterLibCache()
732 {
733  ImpFilterLibCacheEntry* pEntry = mpFirst;
734  while( pEntry )
735  {
736  ImpFilterLibCacheEntry* pNext = pEntry->mpNext;
737  delete pEntry;
738  pEntry = pNext;
739  }
740 }
741 
742 ImpFilterLibCacheEntry* ImpFilterLibCache::GetFilter(const OUString& rFilterPath, const OUString& rFilterName, const OUString& rFormatName)
743 {
744  ImpFilterLibCacheEntry* pEntry = mpFirst;
745 
746  while( pEntry )
747  {
748  if( *pEntry == rFilterName && pEntry->maFormatName == rFormatName )
749  break;
750  else
751  pEntry = pEntry->mpNext;
752  }
753  if( !pEntry )
754  {
755  OUString aPhysicalName( ImpCreateFullFilterPath( rFilterPath, rFilterName ) );
756  pEntry = new ImpFilterLibCacheEntry(aPhysicalName, rFilterName, rFormatName );
757 #ifndef DISABLE_DYNLOADING
758  if ( pEntry->maLibrary.is() )
759 #endif
760  {
761  if( !mpFirst )
762  mpFirst = mpLast = pEntry;
763  else
764  mpLast = mpLast->mpNext = pEntry;
765  }
766 #ifndef DISABLE_DYNLOADING
767  else
768  {
769  delete pEntry;
770  pEntry = nullptr;
771  }
772 #endif
773  }
774  return pEntry;
775 };
776 
777 namespace { struct Cache : public rtl::Static<ImpFilterLibCache, Cache> {}; }
778 
780  : bUseConfig(bConfig)
781 {
782  ImplInit();
783 }
784 
786 {
787  {
788  ::osl::MutexGuard aGuard( getListMutex() );
789  auto it = std::find(pFilterHdlList->begin(), pFilterHdlList->end(), this);
790  if( it != pFilterHdlList->end() )
791  pFilterHdlList->erase( it );
792 
793  if( pFilterHdlList->empty() )
794  {
795  delete pFilterHdlList;
796  pFilterHdlList = nullptr;
797  delete pConfig;
798  }
799  }
800 
801  pErrorEx.reset();
802 }
803 
805 {
806  {
807  ::osl::MutexGuard aGuard( getListMutex() );
808 
809  if ( !pFilterHdlList )
810  {
813  }
814  else
815  pConfig = pFilterHdlList->front()->pConfig;
816 
817  pFilterHdlList->push_back( this );
818  }
819 
820  if( bUseConfig )
821  {
822  OUString url("$BRAND_BASE_DIR/" LIBO_LIB_FOLDER);
823  rtl::Bootstrap::expandMacros(url); //TODO: detect failure
824  osl::FileBase::getSystemPathFromFileURL(url, aFilterPath);
825  }
826 
827  pErrorEx.reset( new FilterErrorEx );
828 }
829 
831 {
832  pErrorEx->nStreamError = pStm ? pStm->GetError() : ERRCODE_NONE;
833  return nError;
834 }
835 
837 {
838  return pConfig->GetImportFormatCount();
839 }
840 
841 sal_uInt16 GraphicFilter::GetImportFormatNumber( std::u16string_view rFormatName )
842 {
843  return pConfig->GetImportFormatNumber( rFormatName );
844 }
845 
846 sal_uInt16 GraphicFilter::GetImportFormatNumberForShortName( std::u16string_view rShortName )
847 {
848  return pConfig->GetImportFormatNumberForShortName( rShortName );
849 }
850 
851 sal_uInt16 GraphicFilter::GetImportFormatNumberForTypeName( std::u16string_view rType )
852 {
853  return pConfig->GetImportFormatNumberForTypeName( rType );
854 }
855 
856 OUString GraphicFilter::GetImportFormatName( sal_uInt16 nFormat )
857 {
858  return pConfig->GetImportFormatName( nFormat );
859 }
860 
861 OUString GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat )
862 {
863  return pConfig->GetImportFilterTypeName( nFormat );
864 }
865 
866 #ifdef _WIN32
867 OUString GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat )
868 {
869  return pConfig->GetImportFormatMediaType( nFormat );
870 }
871 #endif
872 
873 OUString GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat )
874 {
875  return pConfig->GetImportFormatShortName( nFormat );
876 }
877 
878 OUString GraphicFilter::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
879 {
880  return pConfig->GetImportWildcard( nFormat, nEntry );
881 }
882 
884 {
885  return pConfig->GetExportFormatCount();
886 }
887 
888 sal_uInt16 GraphicFilter::GetExportFormatNumber( std::u16string_view rFormatName )
889 {
890  return pConfig->GetExportFormatNumber( rFormatName );
891 }
892 
893 sal_uInt16 GraphicFilter::GetExportFormatNumberForMediaType( std::u16string_view rMediaType )
894 {
895  return pConfig->GetExportFormatNumberForMediaType( rMediaType );
896 }
897 
898 sal_uInt16 GraphicFilter::GetExportFormatNumberForShortName( std::u16string_view rShortName )
899 {
900  return pConfig->GetExportFormatNumberForShortName( rShortName );
901 }
902 
903 OUString GraphicFilter::GetExportInternalFilterName( sal_uInt16 nFormat )
904 {
905  return pConfig->GetExportInternalFilterName( nFormat );
906 }
907 
908 sal_uInt16 GraphicFilter::GetExportFormatNumberForTypeName( std::u16string_view rType )
909 {
910  return pConfig->GetExportFormatNumberForTypeName( rType );
911 }
912 
913 OUString GraphicFilter::GetExportFormatName( sal_uInt16 nFormat )
914 {
915  return pConfig->GetExportFormatName( nFormat );
916 }
917 
918 OUString GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat )
919 {
920  return pConfig->GetExportFormatMediaType( nFormat );
921 }
922 
923 OUString GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat )
924 {
925  return pConfig->GetExportFormatShortName( nFormat );
926 }
927 
928 OUString GraphicFilter::GetExportWildcard( sal_uInt16 nFormat )
929 {
930  return pConfig->GetExportWildcard( nFormat, 0 );
931 }
932 
933 bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat )
934 {
935  return pConfig->IsExportPixelFormat( nFormat );
936 }
937 
939  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
940 {
942  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::CanImportGraphic() : ProtType == INetProtocol::NotValid" );
943 
944  OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
945  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
946  if (xStream)
947  {
948  nRetValue = CanImportGraphic( aMainUrl, *xStream, nFormat, pDeterminedFormat );
949  }
950  return nRetValue;
951 }
952 
953 ErrCode GraphicFilter::CanImportGraphic( const OUString& rMainUrl, SvStream& rIStream,
954  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
955 {
956  sal_uLong nStreamPos = rIStream.Tell();
957  ErrCode nRes = ImpTestOrFindFormat( rMainUrl, rIStream, nFormat );
958 
959  rIStream.Seek(nStreamPos);
960 
961  if( nRes==ERRCODE_NONE && pDeterminedFormat!=nullptr )
962  *pDeterminedFormat = nFormat;
963 
964  return ImplSetError( nRes, &rIStream );
965 }
966 
967 //SJ: TODO, we need to create a GraphicImporter component
969  sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, GraphicFilterImportFlags nImportFlags )
970 {
972  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ImportGraphic() : ProtType == INetProtocol::NotValid" );
973 
974  OUString aMainUrl( rPath.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
975  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::READ | StreamMode::SHARE_DENYNONE ));
976  if (xStream)
977  {
978  nRetValue = ImportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pDeterminedFormat, nImportFlags );
979  }
980  return nRetValue;
981 }
982 
984  Graphic& rGraphic,
985  const OUString& rPath,
986  SvStream& rIStream,
987  sal_uInt16 nFormat,
988  sal_uInt16* pDeterminedFormat,
989  GraphicFilterImportFlags nImportFlags,
990  WmfExternal const *pExtHeader)
991 {
992  return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, nullptr, pExtHeader );
993 }
994 
995 namespace {
996 
999 struct GraphicImportContext
1000 {
1002  std::unique_ptr<SvStream> m_pStream;
1004  std::shared_ptr<Graphic> m_pGraphic;
1006  std::unique_ptr<BitmapScopedWriteAccess> m_pAccess;
1010  GfxLinkType m_eLinkType = GfxLinkType::NONE;
1012  sal_uInt64 m_nStreamBegin = 0;
1015 };
1016 
1018 class GraphicImportTask : public comphelper::ThreadTask
1019 {
1020  GraphicImportContext& m_rContext;
1021 public:
1022  GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext);
1023  void doWork() override;
1025  static void doImport(GraphicImportContext& rContext);
1026 };
1027 
1028 }
1029 
1030 GraphicImportTask::GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext)
1031  : comphelper::ThreadTask(pTag),
1032  m_rContext(rContext)
1033 {
1034 }
1035 
1036 void GraphicImportTask::doWork()
1037 {
1038  GraphicImportTask::doImport(m_rContext);
1039 }
1040 
1041 void GraphicImportTask::doImport(GraphicImportContext& rContext)
1042 {
1043  if (!ImportJPEG(*rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, rContext.m_pAccess.get()))
1044  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
1045  else
1046  rContext.m_eLinkType = GfxLinkType::NativeJpg;
1047 }
1048 
1049 void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, std::vector< std::unique_ptr<SvStream> > vStreams)
1050 {
1051  static bool bThreads = !getenv("VCL_NO_THREAD_IMPORT");
1052  std::vector<GraphicImportContext> aContexts;
1053  aContexts.reserve(vStreams.size());
1055  std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
1056 
1057  for (auto& pStream : vStreams)
1058  {
1059  aContexts.emplace_back();
1060  GraphicImportContext& rContext = aContexts.back();
1061 
1062  if (pStream)
1063  {
1064  rContext.m_pStream = std::move(pStream);
1065  rContext.m_pGraphic = std::make_shared<Graphic>();
1066  rContext.m_nStatus = ERRCODE_NONE;
1067 
1068  // Detect the format.
1069  ResetLastError();
1070  rContext.m_nStreamBegin = rContext.m_pStream->Tell();
1071  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
1072  rContext.m_nStatus = ImpTestOrFindFormat(OUString(), *rContext.m_pStream, nFormat);
1073  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
1074 
1075  // Import the graphic.
1076  if (rContext.m_nStatus == ERRCODE_NONE && !rContext.m_pStream->GetError())
1077  {
1078  OUString aFilterName = pConfig->GetImportFilterName(nFormat);
1079 
1080  if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
1081  {
1082  rContext.m_nImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
1083 
1084  if (!ImportJPEG( *rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
1085  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
1086  else
1087  {
1088  Bitmap& rBitmap = const_cast<Bitmap&>(rContext.m_pGraphic->GetBitmapExRef().GetBitmap());
1089  rContext.m_pAccess = std::make_unique<BitmapScopedWriteAccess>(rBitmap);
1090  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
1091  if (bThreads)
1092  rSharedPool.pushTask(std::make_unique<GraphicImportTask>(pTag, rContext));
1093  else
1094  GraphicImportTask::doImport(rContext);
1095  }
1096  }
1097  else
1098  rContext.m_nStatus = ERRCODE_GRFILTER_FILTERERROR;
1099  }
1100  }
1101  }
1102 
1103  rSharedPool.waitUntilDone(pTag);
1104 
1105  // Process data after import.
1106  for (auto& rContext : aContexts)
1107  {
1108  rContext.m_pAccess.reset();
1109 
1110  if (rContext.m_nStatus == ERRCODE_NONE && (rContext.m_eLinkType != GfxLinkType::NONE) && !rContext.m_pGraphic->GetReaderContext())
1111  {
1112  std::unique_ptr<sal_uInt8[]> pGraphicContent;
1113 
1114  const sal_uInt64 nStreamEnd = rContext.m_pStream->Tell();
1115  sal_Int32 nGraphicContentSize = nStreamEnd - rContext.m_nStreamBegin;
1116 
1117  if (nGraphicContentSize > 0)
1118  {
1119  try
1120  {
1121  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1122  }
1123  catch (const std::bad_alloc&)
1124  {
1125  rContext.m_nStatus = ERRCODE_GRFILTER_TOOBIG;
1126  }
1127 
1128  if (rContext.m_nStatus == ERRCODE_NONE)
1129  {
1130  rContext.m_pStream->Seek(rContext.m_nStreamBegin);
1131  rContext.m_pStream->ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1132  }
1133  }
1134 
1135  if (rContext.m_nStatus == ERRCODE_NONE)
1136  rContext.m_pGraphic->SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, rContext.m_eLinkType));
1137  }
1138 
1139  if (rContext.m_nStatus != ERRCODE_NONE)
1140  rContext.m_pGraphic = nullptr;
1141 
1142  rGraphics.push_back(rContext.m_pGraphic);
1143  }
1144 }
1145 
1146 void GraphicFilter::MakeGraphicsAvailableThreaded(std::vector<Graphic*>& graphics)
1147 {
1148  // Graphic::makeAvailable() is not thread-safe. Only the jpeg loader is, so here
1149  // we process only jpeg images that also have their stream data, load new Graphic's
1150  // from them and then update the passed objects using them.
1151  std::vector< Graphic* > toLoad;
1152  for(auto graphic : graphics)
1153  {
1154  // Need to use GetSharedGfxLink, to access the pointer without copying.
1155  if(!graphic->isAvailable() && graphic->IsGfxLink()
1156  && graphic->GetSharedGfxLink()->GetType() == GfxLinkType::NativeJpg
1157  && graphic->GetSharedGfxLink()->GetDataSize() != 0 )
1158  toLoad.push_back( graphic );
1159  }
1160  if( toLoad.empty())
1161  return;
1162  std::vector< std::unique_ptr<SvStream>> streams;
1163  for( auto graphic : toLoad )
1164  {
1165  streams.push_back( std::make_unique<SvMemoryStream>( const_cast<sal_uInt8*>(graphic->GetSharedGfxLink()->GetData()),
1166  graphic->GetSharedGfxLink()->GetDataSize(), StreamMode::READ | StreamMode::WRITE));
1167  }
1168  std::vector< std::shared_ptr<Graphic>> loadedGraphics;
1169  ImportGraphics(loadedGraphics, std::move(streams));
1170  assert(loadedGraphics.size() == toLoad.size());
1171  for( size_t i = 0; i < toLoad.size(); ++i )
1172  {
1173  if(loadedGraphics[ i ] != nullptr)
1174  toLoad[ i ]->ImplGetImpGraphic()->updateFromLoadedGraphic(loadedGraphics[ i ]->ImplGetImpGraphic());
1175  }
1176 }
1177 
1178 
1180  const Size* pSizeHint)
1181 {
1182  Graphic aGraphic;
1183  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
1184  GfxLinkType eLinkType = GfxLinkType::NONE;
1185 
1186  ResetLastError();
1187 
1188  const sal_uLong nStreamBegin = rIStream.Tell();
1189 
1190  rIStream.Seek(nStreamBegin);
1191 
1192  ErrCode nStatus = ImpTestOrFindFormat("", rIStream, nFormat);
1193 
1194  rIStream.Seek(nStreamBegin);
1195  sal_uInt32 nStreamLength(rIStream.remainingSize());
1196  if (sizeLimit && sizeLimit < nStreamLength)
1197  nStreamLength = sizeLimit;
1198 
1199  OUString aFilterName = pConfig->GetImportFilterName(nFormat);
1200  OUString aExternalFilterName = pConfig->GetExternalFilterName(nFormat, false);
1201 
1202  std::unique_ptr<sal_uInt8[]> pGraphicContent;
1203  sal_Int32 nGraphicContentSize = 0;
1204 
1205  // read graphic
1206  if (pConfig->IsImportInternalFilter(nFormat))
1207  {
1208  if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
1209  {
1210  eLinkType = GfxLinkType::NativeGif;
1211  }
1212  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
1213  {
1214  vcl::PNGReader aPNGReader(rIStream);
1215 
1216  // check if this PNG contains a GIF chunk!
1217  const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
1218  for (auto const& chunk : rChunkData)
1219  {
1220  // Microsoft Office is storing Animated GIFs in following chunk
1221  if (chunk.nType == PMGCHUNG_msOG)
1222  {
1223  sal_uInt32 nChunkSize = chunk.aData.size();
1224 
1225  if (nChunkSize > 11)
1226  {
1227  const std::vector<sal_uInt8>& rData = chunk.aData;
1228  nGraphicContentSize = nChunkSize - 11;
1229  SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), nGraphicContentSize, StreamMode::READ);
1230  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1231  sal_uInt64 aCurrentPosition = aIStrm.Tell();
1232  aIStrm.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1233  aIStrm.Seek(aCurrentPosition);
1234  eLinkType = GfxLinkType::NativeGif;
1235  break;
1236  }
1237  }
1238  }
1239  if (eLinkType == GfxLinkType::NONE)
1240  {
1241  eLinkType = GfxLinkType::NativePng;
1242  }
1243  }
1244  else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
1245  {
1246  eLinkType = GfxLinkType::NativeJpg;
1247  }
1248  else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
1249  {
1250  bool bOkay(false);
1251 
1252  if (nStreamLength > 0)
1253  {
1254  std::vector<sal_uInt8> aTwoBytes(2);
1255  rIStream.ReadBytes(aTwoBytes.data(), 2);
1256  rIStream.Seek(nStreamBegin);
1257 
1258  if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
1259  {
1260  SvMemoryStream aMemStream;
1261  ZCodec aCodec;
1262  tools::Long nMemoryLength;
1263 
1264  aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
1265  nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
1266  aCodec.EndCompression();
1267 
1268  if (!rIStream.GetError() && nMemoryLength >= 0)
1269  {
1270  nGraphicContentSize = nMemoryLength;
1271  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1272 
1273  aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
1274  aMemStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1275 
1276  bOkay = true;
1277  }
1278  }
1279  else
1280  {
1281  nGraphicContentSize = nStreamLength;
1282  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1283  rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
1284 
1285  bOkay = true;
1286  }
1287  }
1288 
1289  if (bOkay)
1290  {
1291  eLinkType = GfxLinkType::NativeSvg;
1292  }
1293  else
1294  {
1295  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1296  }
1297  }
1298  else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
1299  {
1300  eLinkType = GfxLinkType::NativeBmp;
1301  }
1302  else if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
1303  {
1304  eLinkType = GfxLinkType::NativeMov;
1305  }
1306  else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) ||
1307  aFilterName.equalsIgnoreAsciiCase(IMP_EMF))
1308  {
1309  nGraphicContentSize = nStreamLength;
1310  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1311 
1312  rIStream.Seek(nStreamBegin);
1313  rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
1314 
1315  if (!rIStream.GetError())
1316  {
1317  eLinkType = GfxLinkType::NativeWmf;
1318  }
1319  else
1320  {
1321  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1322  }
1323  }
1324  else if (aFilterName == IMP_PDF)
1325  {
1326  eLinkType = GfxLinkType::NativePdf;
1327  }
1328  else
1329  {
1330  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1331  }
1332  }
1333  else
1334  {
1335  ImpFilterLibCacheEntry* pFilter = nullptr;
1336 
1337  if (!aFilterPath.isEmpty())
1338  {
1339  // find first filter in filter paths
1340  ImpFilterLibCache &rCache = Cache::get();
1341  sal_Int32 nIdx{0};
1342  do {
1343  pFilter = rCache.GetFilter(aFilterPath.getToken(0, ';', nIdx), aFilterName, aExternalFilterName);
1344  } while (nIdx>=0 && pFilter==nullptr);
1345  }
1346 
1347  if( !pFilter )
1348  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1349  else
1350  {
1351  PFilterCall pFunc = pFilter->GetImportFunction();
1352 
1353  if (!pFunc)
1354  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1355  else
1356  {
1357  OUString aShortName;
1358  if (nFormat != GRFILTER_FORMAT_DONTKNOW)
1359  aShortName = GetImportFormatShortName(nFormat).toAsciiUpperCase();
1360 
1361  if (aShortName.startsWith(TIF_SHORTNAME))
1362  eLinkType = GfxLinkType::NativeTif;
1363  else if( aShortName.startsWith(MET_SHORTNAME))
1364  eLinkType = GfxLinkType::NativeMet;
1365  else if( aShortName.startsWith(PCT_SHORTNAME))
1366  eLinkType = GfxLinkType::NativePct;
1367  }
1368  }
1369  }
1370 
1371  if (nStatus == ERRCODE_NONE && eLinkType != GfxLinkType::NONE)
1372  {
1373  if (!pGraphicContent)
1374  {
1375  nGraphicContentSize = nStreamLength;
1376 
1377  if (nGraphicContentSize > 0)
1378  {
1379  try
1380  {
1381  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1382  }
1383  catch (const std::bad_alloc&)
1384  {
1385  nStatus = ERRCODE_GRFILTER_TOOBIG;
1386  }
1387 
1388  if (nStatus == ERRCODE_NONE)
1389  {
1390  rIStream.Seek(nStreamBegin);
1391  rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1392  }
1393  }
1394  }
1395 
1396  if( nStatus == ERRCODE_NONE )
1397  {
1398  bool bAnimated = false;
1399  if (eLinkType == GfxLinkType::NativeGif)
1400  {
1401  SvMemoryStream aMemoryStream(pGraphicContent.get(), nGraphicContentSize, StreamMode::READ);
1402  bAnimated = IsGIFAnimated(aMemoryStream);
1403  }
1404  aGraphic.SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
1405  aGraphic.ImplGetImpGraphic()->ImplSetPrepared(bAnimated, pSizeHint);
1406  }
1407  }
1408 
1409  // Set error code or try to set native buffer
1410  if (nStatus != ERRCODE_NONE)
1411  ImplSetError(nStatus, &rIStream);
1412  if (nStatus != ERRCODE_NONE || eLinkType == GfxLinkType::NONE)
1413  rIStream.Seek(nStreamBegin);
1414 
1415  return aGraphic;
1416 }
1417 
1419 {
1420  sal_Int32 nTokenCount = comphelper::string::getTokenCount(aFilterPath, ';');
1421  ImpFilterLibCache& rCache = Cache::get();
1422  static const std::initializer_list<std::u16string_view> aFilterNames = {
1423  u"icd", u"idx", u"ime", u"ipb", u"ipd", u"ips", u"ipt", u"ipx", u"ira", u"itg", u"iti",
1424  };
1425 
1426  // Load library for each filter.
1427  for (const auto& rFilterName : aFilterNames)
1428  {
1429  ImpFilterLibCacheEntry* pFilter = nullptr;
1430  // Look at the library in each element inside the filter path.
1431  for (sal_Int32 i = 0; i < nTokenCount; ++i)
1432  {
1433  pFilter = rCache.GetFilter(aFilterPath.getToken(i, ';'), SVLIBRARY("gie"), rFilterName);
1434  if (pFilter)
1435  {
1436  break;
1437  }
1438  }
1439  }
1440 }
1441 
1442 ErrCode GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath, SvStream& rIStream,
1443  sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
1444  const css::uno::Sequence< css::beans::PropertyValue >* /*pFilterData*/,
1445  WmfExternal const *pExtHeader )
1446 {
1447  OUString aFilterName;
1448  OUString aExternalFilterName;
1449  sal_uLong nStreamBegin;
1450  ErrCode nStatus;
1451  GfxLinkType eLinkType = GfxLinkType::NONE;
1452  const bool bLinkSet = rGraphic.IsGfxLink();
1453 
1454  std::unique_ptr<sal_uInt8[]> pGraphicContent;
1455  sal_Int32 nGraphicContentSize = 0;
1456 
1457  ResetLastError();
1458 
1459  std::shared_ptr<GraphicReader> pContext = rGraphic.GetReaderContext();
1460  bool bDummyContext = rGraphic.IsDummyContext();
1461  if( !pContext || bDummyContext )
1462  {
1463  if( bDummyContext )
1464  {
1465  rGraphic.SetDummyContext( false );
1466  nStreamBegin = 0;
1467  }
1468  else
1469  nStreamBegin = rIStream.Tell();
1470 
1471  nStatus = ImpTestOrFindFormat( rPath, rIStream, nFormat );
1472  // if pending, return ERRCODE_NONE in order to request more bytes
1473  if( rIStream.GetError() == ERRCODE_IO_PENDING )
1474  {
1475  rGraphic.SetDummyContext(true);
1476  rIStream.ResetError();
1477  rIStream.Seek( nStreamBegin );
1478  return ImplSetError( ERRCODE_NONE );
1479  }
1480 
1481  rIStream.Seek( nStreamBegin );
1482 
1483  if( ( nStatus != ERRCODE_NONE ) || rIStream.GetError() )
1484  return ImplSetError( ( nStatus != ERRCODE_NONE ) ? nStatus : ERRCODE_GRFILTER_OPENERROR, &rIStream );
1485 
1486  if( pDeterminedFormat )
1487  *pDeterminedFormat = nFormat;
1488 
1489  aFilterName = pConfig->GetImportFilterName( nFormat );
1490  aExternalFilterName = pConfig->GetExternalFilterName(nFormat, false);
1491  }
1492  else
1493  {
1494  aFilterName = pContext->GetUpperFilterName();
1495 
1496  nStreamBegin = 0;
1497  nStatus = ERRCODE_NONE;
1498  }
1499 
1500  // read graphic
1501  if ( pConfig->IsImportInternalFilter( nFormat ) )
1502  {
1503  if( aFilterName.equalsIgnoreAsciiCase( IMP_GIF ) )
1504  {
1505  if( !ImportGIF( rIStream, rGraphic ) )
1506  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1507  else
1508  eLinkType = GfxLinkType::NativeGif;
1509  }
1510  else if( aFilterName.equalsIgnoreAsciiCase( IMP_PNG ) )
1511  {
1512  vcl::PNGReader aPNGReader( rIStream );
1513 
1514  {
1515  // check if this PNG contains a GIF chunk!
1516  const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
1517  for (auto const& chunk : rChunkData)
1518  {
1519  // Microsoft Office is storing Animated GIFs in following chunk
1520  if (chunk.nType == PMGCHUNG_msOG)
1521  {
1522  sal_uInt32 nChunkSize = chunk.aData.size();
1523 
1524  if (nChunkSize > 11)
1525  {
1526  const std::vector<sal_uInt8>& rData = chunk.aData;
1527  nGraphicContentSize = nChunkSize - 11;
1528  SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), nGraphicContentSize, StreamMode::READ);
1529  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1530  sal_uInt64 aCurrentPosition = aIStrm.Tell();
1531  aIStrm.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1532  aIStrm.Seek(aCurrentPosition);
1533  ImportGIF(aIStrm, rGraphic);
1534  eLinkType = GfxLinkType::NativeGif;
1535  break;
1536  }
1537  }
1538  }
1539  }
1540 
1541  if ( eLinkType == GfxLinkType::NONE )
1542  {
1543  BitmapEx aBmpEx( aPNGReader.Read() );
1544  if ( aBmpEx.IsEmpty() )
1545  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1546  else
1547  {
1548  rGraphic = aBmpEx;
1549  eLinkType = GfxLinkType::NativePng;
1550  }
1551  }
1552  }
1553  else if( aFilterName.equalsIgnoreAsciiCase( IMP_JPEG ) )
1554  {
1555  // set LOGSIZE flag always, if not explicitly disabled
1556  // (see #90508 and #106763)
1557  if( !( nImportFlags & GraphicFilterImportFlags::DontSetLogsizeForJpeg ) )
1559 
1560  sal_uInt64 nPosition = rIStream.Tell();
1561  if( !ImportJPEG( rIStream, rGraphic, nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr ) )
1562  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1563  else
1564  {
1565  Bitmap& rBitmap = const_cast<Bitmap&>(rGraphic.GetBitmapExRef().GetBitmap());
1566  BitmapScopedWriteAccess pWriteAccess(rBitmap);
1567  rIStream.Seek(nPosition);
1568  if( !ImportJPEG( rIStream, rGraphic, nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, &pWriteAccess ) )
1569  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1570  else
1571  eLinkType = GfxLinkType::NativeJpg;
1572  }
1573  }
1574  else if( aFilterName.equalsIgnoreAsciiCase( IMP_SVG ) )
1575  {
1576  const sal_uInt32 nStreamPosition(rIStream.Tell());
1577  const sal_uInt32 nStreamLength(rIStream.remainingSize());
1578 
1579  bool bOkay(false);
1580 
1581  if(nStreamLength > 0)
1582  {
1583  std::vector<sal_uInt8> aTwoBytes(2);
1584  rIStream.ReadBytes(aTwoBytes.data(), 2);
1585  rIStream.Seek(nStreamPosition);
1586 
1587  if(aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
1588  {
1589  SvMemoryStream aMemStream;
1590  ZCodec aCodec;
1591  tools::Long nMemoryLength;
1592 
1593  aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
1594  nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
1595  aCodec.EndCompression();
1596 
1597  if (!rIStream.GetError() && nMemoryLength >= 0)
1598  {
1599  VectorGraphicDataArray aNewData(nMemoryLength);
1600  aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
1601  aMemStream.ReadBytes(aNewData.begin(), nMemoryLength);
1602 
1603  // Make a uncompressed copy for GfxLink
1604  nGraphicContentSize = nMemoryLength;
1605  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1606  std::copy(aNewData.begin(), aNewData.end(), pGraphicContent.get());
1607 
1608  if(!aMemStream.GetError() )
1609  {
1610  auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aNewData, rPath, VectorGraphicDataType::Svg);
1611  rGraphic = Graphic(aVectorGraphicDataPtr);
1612  bOkay = true;
1613  }
1614  }
1615  }
1616  else
1617  {
1618  VectorGraphicDataArray aNewData(nStreamLength);
1619  rIStream.ReadBytes(aNewData.begin(), nStreamLength);
1620 
1621  if(!rIStream.GetError())
1622  {
1623  auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aNewData, rPath, VectorGraphicDataType::Svg);
1624  rGraphic = Graphic(aVectorGraphicDataPtr);
1625  bOkay = true;
1626  }
1627  }
1628  }
1629 
1630  if (bOkay)
1631  {
1632  eLinkType = GfxLinkType::NativeSvg;
1633  }
1634  else
1635  {
1636  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1637  }
1638  }
1639  else if( aFilterName.equalsIgnoreAsciiCase( IMP_XBM ) )
1640  {
1641  if( !ImportXBM( rIStream, rGraphic ) )
1642  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1643  }
1644  else if( aFilterName.equalsIgnoreAsciiCase( IMP_XPM ) )
1645  {
1646  if( !ImportXPM( rIStream, rGraphic ) )
1647  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1648  }
1649  else if( aFilterName.equalsIgnoreAsciiCase( IMP_BMP ) ||
1650  aFilterName.equalsIgnoreAsciiCase( IMP_SVMETAFILE ) )
1651  {
1652  // SV internal filters for import bitmaps and MetaFiles
1653  ReadGraphic( rIStream, rGraphic );
1654  if( rIStream.GetError() )
1655  {
1656  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1657  }
1658  else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
1659  {
1660  // #i15508# added BMP type (checked, works)
1661  eLinkType = GfxLinkType::NativeBmp;
1662  }
1663  }
1664  else if( aFilterName.equalsIgnoreAsciiCase( IMP_MOV ) )
1665  {
1666  ReadGraphic( rIStream, rGraphic );
1667  if( rIStream.GetError() )
1668  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1669  else
1670  {
1671  rGraphic.SetDefaultType();
1672  rIStream.Seek( STREAM_SEEK_TO_END );
1673  eLinkType = GfxLinkType::NativeMov;
1674  }
1675  }
1676  else if( aFilterName.equalsIgnoreAsciiCase( IMP_WMF ) ||
1677  aFilterName.equalsIgnoreAsciiCase( IMP_EMF ) )
1678  {
1679  // use new UNO API service, do not directly import but create a
1680  // Graphic that contains the original data and decomposes to
1681  // primitives on demand
1682 
1683  const sal_uInt32 nStreamLength(rIStream.remainingSize());
1684  VectorGraphicDataArray aNewData(nStreamLength);
1685  bool bOkay(false);
1686 
1687  rIStream.ReadBytes(aNewData.begin(), nStreamLength);
1688 
1689  if (!rIStream.GetError())
1690  {
1691  const bool bIsWmf(aFilterName.equalsIgnoreAsciiCase(IMP_WMF));
1693  auto aVectorGraphicDataPtr =
1694  std::make_shared<VectorGraphicData>(
1695  aNewData,
1696  rPath,
1697  aDataType);
1698 
1699  if (pExtHeader)
1700  {
1701  aVectorGraphicDataPtr->setWmfExternalHeader(*pExtHeader);
1702  }
1703 
1704  rGraphic = Graphic(aVectorGraphicDataPtr);
1705  bOkay = true;
1706  }
1707 
1708  if (bOkay)
1709  {
1710  eLinkType = GfxLinkType::NativeWmf;
1711  }
1712  else
1713  {
1714  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1715  }
1716  }
1717  else if (aFilterName.equalsIgnoreAsciiCase(IMP_PDF))
1718  {
1719  if (vcl::ImportPDF(rIStream, rGraphic))
1720  eLinkType = GfxLinkType::NativePdf;
1721  else
1722  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1723  }
1724  else
1725  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1726  }
1727  else
1728  {
1729  ImpFilterLibCacheEntry* pFilter = nullptr;
1730 
1731  if (!aFilterPath.isEmpty())
1732  {
1733  // find first filter in filter paths
1734  ImpFilterLibCache &rCache = Cache::get();
1735  sal_Int32 nIdx{0};
1736  do {
1737  pFilter = rCache.GetFilter(aFilterPath.getToken(0, ';', nIdx), aFilterName, aExternalFilterName);
1738  } while (nIdx>=0 && pFilter==nullptr);
1739  }
1740 
1741  if( !pFilter )
1742  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1743  else
1744  {
1745  PFilterCall pFunc = pFilter->GetImportFunction();
1746 
1747  if( !pFunc )
1748  nStatus = ERRCODE_GRFILTER_FILTERERROR;
1749  else
1750  {
1751  std::unique_ptr<FilterConfigItem> pFilterConfigItem;
1752  OUString aShortName;
1753  if( nFormat != GRFILTER_FORMAT_DONTKNOW )
1754  {
1755  aShortName = GetImportFormatShortName( nFormat ).toAsciiUpperCase();
1756  if (aShortName == "PCD" && !utl::ConfigManager::IsFuzzing())
1757  {
1758  OUString aFilterConfigPath( "Office.Common/Filter/Graphic/Import/PCD" );
1759  pFilterConfigItem = std::make_unique<FilterConfigItem>( aFilterConfigPath );
1760  }
1761  }
1762  if( !(*pFunc)( rIStream, rGraphic, pFilterConfigItem.get() ) )
1763  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1764  else
1765  {
1766  // try to set link type if format matches
1767  if( nFormat != GRFILTER_FORMAT_DONTKNOW )
1768  {
1769  if( aShortName.startsWith( TIF_SHORTNAME ) )
1770  eLinkType = GfxLinkType::NativeTif;
1771  else if( aShortName.startsWith( MET_SHORTNAME ) )
1772  eLinkType = GfxLinkType::NativeMet;
1773  else if( aShortName.startsWith( PCT_SHORTNAME ) )
1774  eLinkType = GfxLinkType::NativePct;
1775  }
1776  }
1777  }
1778  }
1779  }
1780 
1781  if( nStatus == ERRCODE_NONE && ( eLinkType != GfxLinkType::NONE ) && !rGraphic.GetReaderContext() && !bLinkSet )
1782  {
1783  if (!pGraphicContent)
1784  {
1785  const sal_uLong nStreamEnd = rIStream.Tell();
1786  nGraphicContentSize = nStreamEnd - nStreamBegin;
1787 
1788  if (nGraphicContentSize > 0)
1789  {
1790  try
1791  {
1792  pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
1793  }
1794  catch (const std::bad_alloc&)
1795  {
1796  nStatus = ERRCODE_GRFILTER_TOOBIG;
1797  }
1798 
1799  if( nStatus == ERRCODE_NONE )
1800  {
1801  rIStream.Seek(nStreamBegin);
1802  rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
1803  }
1804  }
1805  }
1806  if( nStatus == ERRCODE_NONE )
1807  {
1808  rGraphic.SetGfxLink(std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
1809  }
1810  }
1811 
1812  // Set error code or try to set native buffer
1813  if( nStatus != ERRCODE_NONE )
1814  {
1815  ImplSetError( nStatus, &rIStream );
1816  rIStream.Seek( nStreamBegin );
1817  rGraphic.Clear();
1818  }
1819 
1820  return nStatus;
1821 }
1822 
1824  sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1825 {
1826  SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1828  SAL_WARN_IF( rPath.GetProtocol() == INetProtocol::NotValid, "vcl.filter", "GraphicFilter::ExportGraphic() : ProtType == INetProtocol::NotValid" );
1829 
1830  OUString aMainUrl(rPath.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1831  bool bAlreadyExists = utl::UCBContentHelper::IsDocument(aMainUrl);
1832 
1833  std::unique_ptr<SvStream> xStream(::utl::UcbStreamHelper::CreateStream( aMainUrl, StreamMode::WRITE | StreamMode::TRUNC ));
1834  if (xStream)
1835  {
1836  nRetValue = ExportGraphic( rGraphic, aMainUrl, *xStream, nFormat, pFilterData );
1837  xStream.reset();
1838 
1839  if( ( ERRCODE_NONE != nRetValue ) && !bAlreadyExists )
1840  utl::UCBContentHelper::Kill(aMainUrl);
1841  }
1842  return nRetValue;
1843 }
1844 
1845 #ifdef DISABLE_DYNLOADING
1846 
1847 extern "C" bool egiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
1848 extern "C" bool epsGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
1849 extern "C" bool etiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem );
1850 
1851 #endif
1852 
1853 ErrCode GraphicFilter::ExportGraphic( const Graphic& rGraphic, const OUString& rPath,
1854  SvStream& rOStm, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
1855 {
1856  SAL_INFO( "vcl.filter", "GraphicFilter::ExportGraphic() (thb)" );
1857  sal_uInt16 nFormatCount = GetExportFormatCount();
1858 
1859  ResetLastError();
1860 
1861  if( nFormat == GRFILTER_FORMAT_DONTKNOW )
1862  {
1863  INetURLObject aURL( rPath );
1864  OUString aExt( aURL.GetFileExtension().toAsciiUpperCase() );
1865 
1866  for( sal_uInt16 i = 0; i < nFormatCount; i++ )
1867  {
1868  if ( pConfig->GetExportFormatExtension( i ).equalsIgnoreAsciiCase( aExt ) )
1869  {
1870  nFormat=i;
1871  break;
1872  }
1873  }
1874  }
1875  if( nFormat >= nFormatCount )
1877 
1878  FilterConfigItem aConfigItem( pFilterData );
1879  OUString aFilterName( pConfig->GetExportFilterName( nFormat ) );
1880  OUString aExternalFilterName(pConfig->GetExternalFilterName(nFormat, true));
1881  ErrCode nStatus = ERRCODE_NONE;
1883  Graphic aGraphic = ImpGetScaledGraphic( rGraphic, aConfigItem );
1884  eType = aGraphic.GetType();
1885 
1886  if( pConfig->IsExportPixelFormat( nFormat ) )
1887  {
1888  if( eType != GraphicType::Bitmap )
1889  {
1890  Size aSizePixel;
1891  sal_uLong nBitsPerPixel,nNeededMem,nMaxMem;
1893 
1894  nMaxMem = 1024;
1895  nMaxMem *= 1024; // In Bytes
1896 
1897  // Calculate how big the image would normally be:
1898  aSizePixel=aVirDev->LogicToPixel(aGraphic.GetPrefSize(),aGraphic.GetPrefMapMode());
1899 
1900  // Calculate how much memory the image will take up
1901  nBitsPerPixel=aVirDev->GetBitCount();
1902  nNeededMem=(static_cast<sal_uLong>(aSizePixel.Width())*static_cast<sal_uLong>(aSizePixel.Height())*nBitsPerPixel+7)/8;
1903 
1904  // is the image larger than available memory?
1905  if (nMaxMem<nNeededMem)
1906  {
1907  double fFak=sqrt(static_cast<double>(nMaxMem)/static_cast<double>(nNeededMem));
1908  aSizePixel.setWidth(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Width())*fFak) );
1909  aSizePixel.setHeight(static_cast<sal_uLong>(static_cast<double>(aSizePixel.Height())*fFak) );
1910  }
1911 
1912  aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1913  aVirDev->SetOutputSizePixel(aSizePixel);
1914  Graphic aGraphic2=aGraphic;
1915  aGraphic2.Draw(aVirDev.get(),Point(0,0),aSizePixel); // this changes the MapMode
1916  aVirDev->SetMapMode(MapMode(MapUnit::MapPixel));
1917  aGraphic=Graphic(aVirDev->GetBitmapEx(Point(0,0),aSizePixel));
1918  }
1919  }
1920  if( rOStm.GetError() )
1921  nStatus = ERRCODE_GRFILTER_IOERROR;
1922  if( ERRCODE_NONE == nStatus )
1923  {
1924  if ( pConfig->IsExportInternalFilter( nFormat ) )
1925  {
1926  if( aFilterName.equalsIgnoreAsciiCase( EXP_BMP ) )
1927  {
1928  BitmapEx aBmp( aGraphic.GetBitmapEx() );
1929  BmpConversion nColorRes = static_cast<BmpConversion>(aConfigItem.ReadInt32( "Color", 0 ));
1930  if ( nColorRes != BmpConversion::NNONE && ( nColorRes <= BmpConversion::N24Bit) )
1931  {
1932  if( !aBmp.Convert( nColorRes ) )
1933  aBmp = aGraphic.GetBitmapEx();
1934  }
1935  bool bRleCoding = aConfigItem.ReadBool( "RLE_Coding", true );
1936  // save RLE encoded?
1937  WriteDIB(aBmp, rOStm, bRleCoding);
1938 
1939  if( rOStm.GetError() )
1940  nStatus = ERRCODE_GRFILTER_IOERROR;
1941  }
1942  else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVMETAFILE ) )
1943  {
1944  sal_Int32 nVersion = aConfigItem.ReadInt32( "Version", 0 ) ;
1945  if ( nVersion )
1946  rOStm.SetVersion( nVersion );
1947 
1948  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1949  GDIMetaFile aMTF(aGraphic.GetGDIMetaFile());
1950 
1951  aMTF.Write( rOStm );
1952 
1953  if( rOStm.GetError() )
1954  nStatus = ERRCODE_GRFILTER_IOERROR;
1955  }
1956  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_WMF ) )
1957  {
1958  bool bDone(false);
1959 
1960  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1961  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1962 
1963  if (rVectorGraphicDataPtr
1964  && rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()
1965  && VectorGraphicDataType::Wmf == rVectorGraphicDataPtr->getVectorGraphicDataType())
1966  {
1967  rOStm.WriteBytes(rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength());
1968 
1969  if (rOStm.GetError())
1970  {
1971  nStatus = ERRCODE_GRFILTER_IOERROR;
1972  }
1973  else
1974  {
1975  bDone = true;
1976  }
1977  }
1978 
1979  if (!bDone)
1980  {
1981  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
1982  if (!ConvertGDIMetaFileToWMF(aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem))
1983  nStatus = ERRCODE_GRFILTER_FORMATERROR;
1984 
1985  if (rOStm.GetError())
1986  nStatus = ERRCODE_GRFILTER_IOERROR;
1987  }
1988  }
1989  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_EMF ) )
1990  {
1991  bool bDone(false);
1992 
1993  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
1994  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
1995 
1996  if (rVectorGraphicDataPtr
1997  && rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()
1998  && VectorGraphicDataType::Emf == rVectorGraphicDataPtr->getVectorGraphicDataType())
1999  {
2000  rOStm.WriteBytes(rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength());
2001 
2002  if (rOStm.GetError())
2003  {
2004  nStatus = ERRCODE_GRFILTER_IOERROR;
2005  }
2006  else
2007  {
2008  bDone = true;
2009  }
2010  }
2011 
2012  if (!bDone)
2013  {
2014  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
2015  if (!ConvertGDIMetaFileToEMF(aGraphic.GetGDIMetaFile(), rOStm))
2016  nStatus = ERRCODE_GRFILTER_FORMATERROR;
2017 
2018  if (rOStm.GetError())
2019  nStatus = ERRCODE_GRFILTER_IOERROR;
2020  }
2021  }
2022  else if( aFilterName.equalsIgnoreAsciiCase( EXP_JPEG ) )
2023  {
2024  bool bExportedGrayJPEG = false;
2025  if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) )
2026  nStatus = ERRCODE_GRFILTER_FORMATERROR;
2027 
2028  if( rOStm.GetError() )
2029  nStatus = ERRCODE_GRFILTER_IOERROR;
2030  }
2031  else if ( aFilterName.equalsIgnoreAsciiCase( EXP_PNG ) )
2032  {
2033  vcl::PNGWriter aPNGWriter( aGraphic.GetBitmapEx(), pFilterData );
2034  if ( pFilterData )
2035  {
2036  for ( const auto& rPropVal : *pFilterData )
2037  {
2038  if ( rPropVal.Name == "AdditionalChunks" )
2039  {
2040  css::uno::Sequence< css::beans::PropertyValue > aAdditionalChunkSequence;
2041  if ( rPropVal.Value >>= aAdditionalChunkSequence )
2042  {
2043  for ( const auto& rAdditionalChunk : std::as_const(aAdditionalChunkSequence) )
2044  {
2045  if ( rAdditionalChunk.Name.getLength() == 4 )
2046  {
2047  sal_uInt32 nChunkType = 0;
2048  for ( sal_Int32 k = 0; k < 4; k++ )
2049  {
2050  nChunkType <<= 8;
2051  nChunkType |= static_cast<sal_uInt8>(rAdditionalChunk.Name[ k ]);
2052  }
2053  css::uno::Sequence< sal_Int8 > aByteSeq;
2054  if ( rAdditionalChunk.Value >>= aByteSeq )
2055  {
2056  std::vector< vcl::PNGWriter::ChunkData >& rChunkData = aPNGWriter.GetChunks();
2057  if ( !rChunkData.empty() )
2058  {
2059  sal_uInt32 nChunkLen = aByteSeq.getLength();
2060 
2061  vcl::PNGWriter::ChunkData aChunkData;
2062  aChunkData.nType = nChunkType;
2063  if ( nChunkLen )
2064  {
2065  aChunkData.aData.resize( nChunkLen );
2066  memcpy( aChunkData.aData.data(), aByteSeq.getConstArray(), nChunkLen );
2067  }
2068  std::vector< vcl::PNGWriter::ChunkData >::iterator aIter = rChunkData.end() - 1;
2069  rChunkData.insert( aIter, aChunkData );
2070  }
2071  }
2072  }
2073  }
2074  }
2075  }
2076  }
2077  }
2078  aPNGWriter.Write( rOStm );
2079 
2080  if( rOStm.GetError() )
2081  nStatus = ERRCODE_GRFILTER_IOERROR;
2082  }
2083  else if( aFilterName.equalsIgnoreAsciiCase( EXP_SVG ) )
2084  {
2085  bool bDone(false);
2086 
2087  // do we have a native Vector Graphic Data RenderGraphic, whose data can be written directly?
2088  auto const & rVectorGraphicDataPtr(rGraphic.getVectorGraphicData());
2089 
2090  if (rVectorGraphicDataPtr
2091  && rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()
2092  && VectorGraphicDataType::Svg == rVectorGraphicDataPtr->getVectorGraphicDataType())
2093  {
2094  rOStm.WriteBytes(rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength());
2095 
2096  if( rOStm.GetError() )
2097  {
2098  nStatus = ERRCODE_GRFILTER_IOERROR;
2099  }
2100  else
2101  {
2102  bDone = true;
2103  }
2104  }
2105 
2106  if( !bDone )
2107  {
2108  // do the normal GDIMetaFile export instead
2109  try
2110  {
2111  css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2112 
2113  css::uno::Reference< css::xml::sax::XDocumentHandler > xSaxWriter(
2114  css::xml::sax::Writer::create( xContext ), css::uno::UNO_QUERY_THROW);
2115  css::uno::Sequence< css::uno::Any > aArguments( 1 );
2116  aArguments[ 0 ] <<= aConfigItem.GetFilterData();
2117  css::uno::Reference< css::svg::XSVGWriter > xSVGWriter(
2118  xContext->getServiceManager()->createInstanceWithArgumentsAndContext( "com.sun.star.svg.SVGWriter", aArguments, xContext),
2119  css::uno::UNO_QUERY );
2120  if( xSaxWriter.is() && xSVGWriter.is() )
2121  {
2122  css::uno::Reference< css::io::XActiveDataSource > xActiveDataSource(
2123  xSaxWriter, css::uno::UNO_QUERY );
2124 
2125  if( xActiveDataSource.is() )
2126  {
2127  const css::uno::Reference< css::uno::XInterface > xStmIf(
2128  static_cast< ::cppu::OWeakObject* >( new ImpFilterOutputStream( rOStm ) ) );
2129 
2130  SvMemoryStream aMemStm( 65535, 65535 );
2131 
2132  // #i119735# just use GetGDIMetaFile, it will create a buffered version of contained bitmap now automatically
2133  const_cast<GDIMetaFile&>( aGraphic.GetGDIMetaFile() ).Write( aMemStm );
2134 
2135  xActiveDataSource->setOutputStream( css::uno::Reference< css::io::XOutputStream >(
2136  xStmIf, css::uno::UNO_QUERY ) );
2137  css::uno::Sequence< sal_Int8 > aMtfSeq( static_cast<sal_Int8 const *>(aMemStm.GetData()), aMemStm.Tell() );
2138  xSVGWriter->write( xSaxWriter, aMtfSeq );
2139  }
2140  }
2141  }
2142  catch(const css::uno::Exception&)
2143  {
2144  nStatus = ERRCODE_GRFILTER_IOERROR;
2145  }
2146  }
2147  }
2148  else
2149  nStatus = ERRCODE_GRFILTER_FILTERERROR;
2150  }
2151  else
2152  {
2153  sal_Int32 nIdx {aFilterPath.isEmpty() ? -1 : 0};
2154  while (nIdx>=0)
2155  {
2156 #ifndef DISABLE_DYNLOADING
2157  OUString aPhysicalName( ImpCreateFullFilterPath( aFilterPath.getToken(0, ';', nIdx), aFilterName ) );
2158  osl::Module aLibrary( aPhysicalName );
2159 
2160  PFilterCall pFunc = nullptr;
2161  if (aExternalFilterName == "egi")
2162  pFunc = reinterpret_cast<PFilterCall>(aLibrary.getFunctionSymbol("egiGraphicExport"));
2163  else if (aExternalFilterName == "eps")
2164  pFunc = reinterpret_cast<PFilterCall>(aLibrary.getFunctionSymbol("epsGraphicExport"));
2165  else if (aExternalFilterName == "eti")
2166  pFunc = reinterpret_cast<PFilterCall>(aLibrary.getFunctionSymbol("etiGraphicExport"));
2167  // Execute dialog in DLL
2168  #else
2169  --nIdx; // Just one iteration
2170  PFilterCall pFunc = NULL;
2171  if (aExternalFilterName == "egi")
2172  pFunc = egiGraphicExport;
2173  else if (aExternalFilterName == "eps")
2174  pFunc = epsGraphicExport;
2175  else if (aExternalFilterName == "eti")
2176  pFunc = etiGraphicExport;
2177  #endif
2178  if( pFunc )
2179  {
2180  if ( !(*pFunc)( rOStm, aGraphic, &aConfigItem ) )
2181  nStatus = ERRCODE_GRFILTER_FORMATERROR;
2182  break;
2183  }
2184  else
2185  nStatus = ERRCODE_GRFILTER_FILTERERROR;
2186  }
2187  }
2188  }
2189  if( nStatus != ERRCODE_NONE )
2190  {
2191  ImplSetError( nStatus, &rOStm );
2192  }
2193  return nStatus;
2194 }
2195 
2196 
2198 {
2199  pErrorEx->nStreamError = ERRCODE_NONE;
2200 }
2201 
2203 {
2204  Link<ConvertData&,bool> aLink( LINK( const_cast<GraphicFilter*>(this), GraphicFilter, FilterCallback ) );
2205  return aLink;
2206 }
2207 
2208 IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
2209 {
2210  bool bRet = false;
2211 
2212  sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
2213  OUString aShortName;
2214  css::uno::Sequence< css::beans::PropertyValue > aFilterData;
2215  switch( rData.mnFormat )
2216  {
2217  case ConvertDataFormat::BMP: aShortName = BMP_SHORTNAME; break;
2218  case ConvertDataFormat::GIF: aShortName = GIF_SHORTNAME; break;
2219  case ConvertDataFormat::JPG: aShortName = JPG_SHORTNAME; break;
2220  case ConvertDataFormat::MET: aShortName = MET_SHORTNAME; break;
2221  case ConvertDataFormat::PCT: aShortName = PCT_SHORTNAME; break;
2222  case ConvertDataFormat::PNG: aShortName = PNG_SHORTNAME; break;
2223  case ConvertDataFormat::SVM: aShortName = SVM_SHORTNAME; break;
2224  case ConvertDataFormat::TIF: aShortName = TIF_SHORTNAME; break;
2225  case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
2226  case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
2227  case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
2228 
2229  default:
2230  break;
2231  }
2232  if( GraphicType::NONE == rData.maGraphic.GetType() || rData.maGraphic.GetReaderContext() ) // Import
2233  {
2234  // Import
2235  nFormat = GetImportFormatNumberForShortName( aShortName );
2236  bRet = ImportGraphic( rData.maGraphic, OUString(), rData.mrStm, nFormat ) == ERRCODE_NONE;
2237  }
2238  else if( !aShortName.isEmpty() )
2239  {
2240  // Export
2241 #if defined(IOS) || defined(ANDROID)
2242  if (aShortName == PNG_SHORTNAME)
2243  {
2244  aFilterData.realloc(aFilterData.getLength() + 1);
2245  aFilterData[aFilterData.getLength() - 1].Name = "Compression";
2246  // We "know" that this gets passed to zlib's deflateInit2_(). 1 means best speed.
2247  aFilterData[aFilterData.getLength() - 1].Value <<= static_cast<sal_Int32>(1);
2248  }
2249 #endif
2250  nFormat = GetExportFormatNumberForShortName( aShortName );
2251  bRet = ExportGraphic( rData.maGraphic, OUString(), rData.mrStm, nFormat, &aFilterData ) == ERRCODE_NONE;
2252  }
2253 
2254  return bRet;
2255 }
2256 
2257 namespace
2258 {
2259  class StandardGraphicFilter
2260  {
2261  public:
2262  StandardGraphicFilter()
2263  {
2264  m_aFilter.GetImportFormatCount();
2265  }
2266  GraphicFilter m_aFilter;
2267  };
2268 
2269  class theGraphicFilter : public rtl::Static<StandardGraphicFilter, theGraphicFilter> {};
2270 }
2271 
2273 {
2274  return theGraphicFilter::get().m_aFilter;
2275 }
2276 
2277 ErrCode GraphicFilter::LoadGraphic( const OUString &rPath, const OUString &rFilterName,
2278  Graphic& rGraphic, GraphicFilter* pFilter,
2279  sal_uInt16* pDeterminedFormat )
2280 {
2281  if ( !pFilter )
2282  pFilter = &GetGraphicFilter();
2283 
2284  const sal_uInt16 nFilter = !rFilterName.isEmpty() && pFilter->GetImportFormatCount()
2285  ? pFilter->GetImportFormatNumber( rFilterName )
2287 
2288  INetURLObject aURL( rPath );
2289  if ( aURL.HasError() )
2290  {
2291  aURL.SetSmartProtocol( INetProtocol::File );
2292  aURL.SetSmartURL( rPath );
2293  }
2294 
2295  std::unique_ptr<SvStream> pStream;
2296  if ( INetProtocol::File != aURL.GetProtocol() )
2297  pStream = ::utl::UcbStreamHelper::CreateStream( rPath, StreamMode::READ );
2298 
2299  ErrCode nRes = ERRCODE_NONE;
2300  if ( !pStream )
2301  nRes = pFilter->ImportGraphic( rGraphic, aURL, nFilter, pDeterminedFormat );
2302  else
2303  nRes = pFilter->ImportGraphic( rGraphic, rPath, *pStream, nFilter, pDeterminedFormat );
2304 
2305 #ifdef DBG_UTIL
2306  OUString aReturnString;
2307 
2308  if (nRes == ERRCODE_GRFILTER_OPENERROR)
2309  aReturnString="open error";
2310  else if (nRes == ERRCODE_GRFILTER_IOERROR)
2311  aReturnString="IO error";
2312  else if (nRes == ERRCODE_GRFILTER_FORMATERROR)
2313  aReturnString="format error";
2314  else if (nRes == ERRCODE_GRFILTER_VERSIONERROR)
2315  aReturnString="version error";
2316  else if (nRes == ERRCODE_GRFILTER_FILTERERROR)
2317  aReturnString="filter error";
2318  else if (nRes == ERRCODE_GRFILTER_TOOBIG)
2319  aReturnString="graphic is too big";
2320 
2321  SAL_INFO_IF( nRes, "vcl.filter", "Problem importing graphic " << rPath << ". Reason: " << aReturnString );
2322 #endif
2323 
2324  return nRes;
2325 }
2326 
2327 ErrCode GraphicFilter::compressAsPNG(const Graphic& rGraphic, SvStream& rOutputStream)
2328 {
2329  css::uno::Sequence< css::beans::PropertyValue > aFilterData(1);
2330  aFilterData[0].Name = "Compression";
2331  aFilterData[0].Value <<= sal_uInt32(9);
2332 
2333  sal_uInt16 nFilterFormat = GetExportFormatNumberForShortName(u"PNG");
2334  return ExportGraphic(rGraphic, OUString(), rOutputStream, nFilterFormat, &aFilterData);
2335 }
2336 
2337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetDummyContext(bool value)
Definition: graph.cxx:482
OUString GetExternalFilterName(sal_uInt16 nFormat, bool bExport)
OUString GetImportFormatExtension(sal_uInt16 nFormat, sal_Int32 nEntry=0)
#define IMP_MOV
VectorGraphicDataType
bool IsExportPixelFormat(sal_uInt16 nFormat)
SvStream & ReadInt16(sal_Int16 &rInt16)
OUString GetExportFormatName(sal_uInt16 nFormat)
Only create a bitmap, do not read pixel data.
SAL_DLLPUBLIC_EXPORT bool ipdGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
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)
OUString GetImportFilterName(sal_uInt16 nFormat)
void setWidth(tools::Long nWidth)
SAL_DLLPUBLIC_EXPORT bool egiGraphicExport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
void ReadGraphic(SvStream &rIStream, Graphic &rGraphic)
Definition: graph.cxx:523
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1514
UNOTOOLS_DLLPUBLIC bool IsDocument(OUString const &url)
SAL_DLLPUBLIC_EXPORT bool etiGraphicExport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
ErrCode CanImportGraphic(const INetURLObject &rPath, sal_uInt16 nFormat, sal_uInt16 *pDeterminedFormat)
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
bool(* PFilterCall)(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
Definition: fltcall.hxx:27
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:375
OUString GetImportFormatName(sal_uInt16 nFormat)
virtual void doWork()=0
#define ZCODEC_DEFAULT_COMPRESSION
bool ConvertGDIMetaFileToWMF(const GDIMetaFile &rMTF, SvStream &rTargetStream, FilterConfigItem const *pConfigItem, bool bPlaceable)
Definition: wmf.cxx:69
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
sal_uInt64 Seek(sal_uInt64 nPos)
OUString aFilterPath
Class to import and export graphic formats.
void Flush()
tools::Long Decompress(SvStream &rIStm, SvStream &rOStm)
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
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.
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: bitmapex.cxx:450
SAL_DLLPUBLIC_EXPORT bool idxGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
sal_Int32 getTokenCount(const OString &rIn, char cTok)
sal_uInt64 SeekRel(sal_Int64 nPos)
#define IMP_JPEG
bool IsGfxLink() const
Definition: graph.cxx:508
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:1047
#define EXP_JPEG
sal_Int32 ReadInt32(const OUString &rKey, sal_Int32 nDefault)
Graphic ImportUnloadedGraphic(SvStream &rIStream, sal_uInt64 sizeLimit=0, const Size *pSizeHint=nullptr)
#define DISABLE_DYNLOADING
HashMap_OWString_Interface aMap
OUString GetImportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
void Clear()
Definition: graph.cxx:283
#define TIF_SHORTNAME
sal_uInt16 GetExportFormatNumberForTypeName(std::u16string_view rType)
#define JPG_SHORTNAME
return NULL
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
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)
const Reference< XComponentContext > & m_rContext
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
#define EXP_SVMETAFILE
EdgeEntry * mpNext
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
bool ConvertGDIMetaFileToEMF(const GDIMetaFile &rMTF, SvStream &rTargetStream)
Definition: wmf.cxx:86
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
SAL_DLLPUBLIC_EXPORT bool icdGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pConfigItem)
#define ERRCODE_GRFILTER_OPENERROR
sal_uInt16 GetExportFormatCount() const
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:335
#define BMP_SHORTNAME
#define ERRCODE_GRFILTER_FORMATERROR
bool IsExportPixelFormat(sal_uInt16 nFormat)
OUString GetImportFormatShortName(sal_uInt16 nFormat)
VCL_DLLPUBLIC bool ImportGIF(SvStream &rStm, Graphic &rGraphic)
Definition: gifread.cxx:961
VCL_DLLPUBLIC bool ImportXPM(SvStream &rStm, Graphic &rGraphic)
Definition: xpmread.cxx:670
sal_uInt64 remainingSize()
sal_uInt16 GetImportFormatCount() const
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
SAL_DLLPUBLIC_EXPORT bool ipsGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
OUString GetExportFormatName(sal_uInt16 nFormat)
void SetGfxLink(const std::shared_ptr< GfxLink > &rGfxLink)
Definition: graph.cxx:492
SAL_DLLPUBLIC_EXPORT bool itiGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
OUString GetExportWildcard(sal_uInt16 nFormat, sal_Int32 nEntry)
ErrCode ImpTestOrFindFormat(const OUString &rPath, SvStream &rStream, sal_uInt16 &rFormat)
GraphicFilter(bool bUseConfig=true)
const std::vector< ChunkData > & GetChunks() const
Definition: pngread.cxx:1700
SAL_DLLPUBLIC_EXPORT bool imeGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
#define IMP_SVMETAFILE
static ThreadPool & getSharedOptimalPool()
bool operator==(const ItalicMatrix &a, const ItalicMatrix &b)
Definition: vclenum.hxx:206
DocumentType eType
static ErrCode LoadGraphic(const OUString &rPath, const OUString &rFilter, Graphic &rGraphic, GraphicFilter *pFilter=nullptr, sal_uInt16 *pDeterminedFormat=nullptr)
#define IMP_BMP
#define EXP_SVG
OUString GetImportFormatMediaType(sal_uInt16 nFormat)
SAL_DLLPUBLIC_EXPORT bool iraGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
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:422
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:709
GraphicType GetType() const
Definition: graph.cxx:289
#define EMF_SHORTNAME
void SetSmartProtocol(INetProtocol eTheSmartScheme)
#define STREAM_SEEK_TO_BEGIN
std::unique_ptr< FilterErrorEx > pErrorEx
void ImplSetPrepared(bool bAnimated, const Size *pSizeHint)
Definition: impgraph.cxx:400
bool ReadBool(const OUString &rKey, bool bDefault)
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_DLLPUBLIC_EXPORT bool iptGraphicImport(SvStream &rIStm, Graphic &rGraphic, FilterConfigItem *)
sal_uInt16 GetImportFormatNumberForTypeName(std::u16string_view rType)
sal_uInt16 GetExportFormatNumber(std::u16string_view rFormatName)
tools::Long Width() const
VCL_DLLPUBLIC bool ImportXBM(SvStream &rStm, Graphic &rGraphic)
Definition: xbmread.cxx:370
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:340
sal_uInt16 GetExportFormatNumberForMediaType(std::u16string_view rShortName)
float u
void BeginCompression(int nCompressLevel=ZCODEC_DEFAULT_COMPRESSION, bool gzLib=false)
tools::Long EndCompression()
SAL_DLLPUBLIC_EXPORT bool epsGraphicExport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *pFilterConfigItem)
#define IMP_XBM
#define IMP_SVG
SAL_DLLPUBLIC_EXPORT bool ipxGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
#define GRFILTER_FORMAT_DONTKNOW
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:325
OUString GetImportFilterTypeName(sal_uInt16 nFormat)
BmpConversion
Definition: bitmap.hxx:66
void SetVersion(sal_Int32 n)
sal_Int16 nVersion
Link< ConvertData &, bool > GetFilterCallback() const
#define PMGCHUNG_msOG
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
sal_uInt16 GetImportFormatNumber(std::u16string_view rFormatName)
SAL_DLLPUBLIC_EXPORT bool itgGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
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:232
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1049
Size GetPrefSize() const
Definition: graph.cxx:359
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
OUString GetExportFormatShortName(sal_uInt16 nFormat)
#define ERRCODE_GRFILTER_TOOBIG
SvStreamEndian GetEndian() const
#define ERRCODE_GRFILTER_FILTERERROR
#define ERRCODE_GRFILTER_VERSIONERROR
SAL_DLLPUBLIC_EXPORT bool ipbGraphicImport(SvStream &rStream, Graphic &rGraphic, FilterConfigItem *)
#define IMP_WMF
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
bool IsImportInternalFilter(sal_uInt16 nFormat)
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
static OUString ImpGetExtension(const OUString &rPath)
const css::uno::Sequence< css::beans::PropertyValue > & GetFilterData() const
static FilterList_impl * pFilterHdlList
#define SAL_WARN_IF(condition, area, stream)
#define ERRCODE_NONE
Definition: errcode.hxx:198
MapMode GetPrefMapMode() const
Definition: graph.cxx:370
unsigned char sal_uInt8
#define EXP_WMF
sal_uInt16 GetImportFormatCount() const
#define IMP_PNG
void SetEndian(SvStreamEndian SvStreamEndian)
#define SAL_INFO(area, stream)
std::shared_ptr< GraphicReader > & GetReaderContext()
Definition: graph.cxx:472
INetProtocol GetProtocol() const
::std::vector< GraphicFilter * > FilterList_impl
bool ImpPeekGraphicFormat(SvStream &rStream, OUString &rFormatExtension, bool bTest)
OUString GetFileExtension() const
tools::Long Height() 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)
#define IMP_PDF
#define EXP_EMF
OUString GetExportFilterName(sal_uInt16 nFormat)
void SetPrefSize(const Size &rPrefSize)
Definition: graph.cxx:364
void WriteInt32(const OUString &rKey, sal_Int32 nValue)
#define SVLIBRARY(Base)
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:227
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
virtual void ResetError()
static Graphic ImpGetScaledGraphic(const Graphic &rGraphic, FilterConfigItem &rConfigItem)
void SetDefaultType()
Definition: graph.cxx:294
bool WriteDIB(const Bitmap &rSource, SvStream &rOStm, bool bCompressed, bool bFileHeader)
Definition: dibtools.cxx:1857
static OUString ImpCreateFullFilterPath(const OUString &rPath, const OUString &rFilterName)
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:534
GraphicFilterImportFlags
#define IMP_EMF
#define SVG_SHORTNAME
UNOTOOLS_DLLPUBLIC bool Kill(OUString const &url)
bool ImportPDF(SvStream &rStream, Graphic &rGraphic)
Imports a PDF stream into rGraphic as VectorGraphicData.
Definition: pdfread.cxx:233
std::vector< sal_uInt8 > aData
Definition: pngwrite.hxx:52
#define GIF_SHORTNAME
sal_uInt16 GetExportFormatCount() const
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
bool IsExportInternalFilter(sal_uInt16 nFormat)
OUString GetExportFormatMediaType(sal_uInt16 nFormat)
#define PCT_SHORTNAME
bool IsGIFAnimated(SvStream &rStm)
Definition: gifread.cxx:949
sal_uInt16 GetImportFormatNumberForShortName(std::u16string_view rShortName)
#define WMF_SHORTNAME
bool IsDummyContext() const
Definition: graph.cxx:487
SvStream & Write(SvStream &rOStm)
Definition: gdimtf.cxx:2746
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()
#define EXP_PNG
BitmapEx Read()
Definition: pngread.cxx:1695
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo