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