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