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