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