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 #ifndef INCLUDED_VCL_GRAPHICFILTER_HXX
21 #define INCLUDED_VCL_GRAPHICFILTER_HXX
22 
23 #include <tools/gen.hxx>
24 #include <vcl/dllapi.h>
25 #include <vcl/graph.hxx>
26 #include <vcl/errcode.hxx>
27 #include <o3tl/typed_flags_set.hxx>
28 
29 #include <memory>
30 #include <optional>
31 
32 namespace com::sun::star::beans { struct PropertyValue; }
33 namespace com::sun::star::uno { template <class E> class Sequence; }
34 
35 class INetURLObject;
36 
37 class FilterConfigCache;
38 class SvStream;
39 struct WmfExternal;
40 struct ConvertData;
41 
42 #define ERRCODE_GRFILTER_OPENERROR    ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 1)
43 #define ERRCODE_GRFILTER_IOERROR      ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 2)
44 #define ERRCODE_GRFILTER_FORMATERROR  ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 3)
45 #define ERRCODE_GRFILTER_VERSIONERROR ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 4)
46 #define ERRCODE_GRFILTER_FILTERERROR  ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 5)
47 #define ERRCODE_GRFILTER_TOOBIG       ErrCode(ErrCodeArea::Vcl, ErrCodeClass::General, 7)
48 
49 #define GRFILTER_OUTHINT_GREY       1
50 
51 #define GRFILTER_FORMAT_NOTFOUND    (sal_uInt16(0xFFFF))
52 #define GRFILTER_FORMAT_DONTKNOW    (sal_uInt16(0xFFFF))
53 
54 enum class GraphicFilterImportFlags
55 {
56     NONE                   = 0x000,
57     SetLogsizeForJpeg      = 0x001,
58     DontSetLogsizeForJpeg  = 0x002,
59     /// Only create a bitmap, do not read pixel data.
60     OnlyCreateBitmap       = 0x020,
61     /// Read pixel data into an existing bitmap.
62     UseExistingBitmap      = 0x040,
63 };
64 namespace o3tl
65 {
66     template<> struct typed_flags<GraphicFilterImportFlags> : is_typed_flags<GraphicFilterImportFlags, 0x0063> {};
67 }
68 
69 #define IMP_BMP                 "SVBMP"
70 #define IMP_MOV                 "SVMOV"
71 #define IMP_SVMETAFILE          "SVMETAFILE"
72 #define IMP_WMF                 "SVWMF"
73 #define IMP_EMF                 "SVEMF"
74 #define IMP_GIF                 "SVIGIF"
75 #define IMP_PNG                 "SVIPNG"
76 #define IMP_JPEG                "SVIJPEG"
77 #define IMP_XBM                 "SVIXBM"
78 #define IMP_XPM                 "SVIXPM"
79 #define IMP_SVG                 "SVISVG"
80 #define IMP_PDF                 "SVIPDF"
81 #define IMP_TIFF                "SVTIFF"
82 #define IMP_TGA                 "SVTGA"
83 #define IMP_PICT                "SVPICT"
84 #define IMP_MET                 "SVMET"
85 #define IMP_RAS                 "SVRAS"
86 #define IMP_PCX                 "SVPCX"
87 #define IMP_EPS                 "SVIEPS"
88 #define IMP_PSD                 "SVPSD"
89 #define IMP_PCD                 "SVPCD"
90 #define IMP_PBM                 "SVPBM"
91 #define IMP_DXF                 "SVDXF"
92 
93 #define EXP_BMP                 "SVBMP"
94 #define EXP_SVMETAFILE          "SVMETAFILE"
95 #define EXP_WMF                 "SVWMF"
96 #define EXP_EMF                 "SVEMF"
97 #define EXP_JPEG                "SVEJPEG"
98 #define EXP_SVG                 "SVESVG"
99 #define EXP_PDF                 "SVEPDF"
100 #define EXP_PNG                 "SVEPNG"
101 #define EXP_TIFF                "SVTIFF"
102 #define EXP_EPS                 "SVEEPS"
103 #define EXP_GIF                 "SVEGIF"
104 
105 
106 #define BMP_SHORTNAME           u"BMP"
107 #define GIF_SHORTNAME           u"GIF"
108 #define JPG_SHORTNAME           u"JPG"
109 #define MET_SHORTNAME           u"MET"
110 #define PCT_SHORTNAME           u"PCT"
111 #define PNG_SHORTNAME           u"PNG"
112 #define SVM_SHORTNAME           u"SVM"
113 #define TIF_SHORTNAME           u"TIF"
114 #define WMF_SHORTNAME           u"WMF"
115 #define EMF_SHORTNAME           u"EMF"
116 #define SVG_SHORTNAME           u"SVG"
117 #define PDF_SHORTNAME           u"PDF"
118 
119 //  Info class for all supported file formats
120 
121 enum class GraphicFileFormat
122 {
123     NOT = 0x0000,
124     BMP = 0x0001,
125     GIF = 0x0002,
126     JPG = 0x0003,
127     PCD = 0x0004,
128     PCX = 0x0005,
129     PNG = 0x0006,
130     TIF = 0x0007,
131     XBM = 0x0008,
132     XPM = 0x0009,
133     PBM = 0x000a,
134     PGM = 0x000b,
135     PPM = 0x000c,
136     RAS = 0x000d,
137     TGA = 0x000e,
138     PSD = 0x000f,
139     EPS = 0x0010,
140     DXF = 0x00f1,
141     MET = 0x00f2,
142     PCT = 0x00f3,
143     // retired SGF = 0x00f4,
144     SVM = 0x00f5,
145     WMF = 0x00f6,
146     // retired SGV = 0x00f7,
147     EMF = 0x00f8,
148     SVG = 0x00f9
149 };
150 
151 
152 class VCL_DLLPUBLIC GraphicDescriptor final
153 {
154     SvStream*           pFileStm;
155 
156     OUString            aPathExt;
157     Size                aPixSize;
158     Size                aLogSize;
159     std::optional<Size> maPreferredLogSize;
160     std::optional<MapMode> maPreferredMapMode;
161     sal_uInt16          nBitsPerPixel;
162     sal_uInt16          nPlanes;
163     GraphicFileFormat   nFormat;
164     bool                bOwnStream;
165     sal_uInt8 mnNumberOfImageComponents;
166     bool                bIsTransparent;
167     bool                bIsAlpha;
168 
169     void                ImpConstruct();
170 
171     bool            ImpDetectBMP( SvStream& rStm, bool bExtendedInfo );
172     bool            ImpDetectGIF( SvStream& rStm, bool bExtendedInfo );
173     bool            ImpDetectJPG( SvStream& rStm, bool bExtendedInfo );
174     bool            ImpDetectPCD( SvStream& rStm, bool bExtendedInfo );
175     bool            ImpDetectPCX( SvStream& rStm );
176     bool            ImpDetectPNG( SvStream& rStm, bool bExtendedInfo );
177     bool            ImpDetectTIF( SvStream& rStm, bool bExtendedInfo );
178     bool            ImpDetectXBM( SvStream& rStm, bool bExtendedInfo );
179     bool            ImpDetectXPM( SvStream& rStm, bool bExtendedInfo );
180     bool            ImpDetectPBM( SvStream& rStm, bool bExtendedInfo );
181     bool            ImpDetectPGM( SvStream& rStm, bool bExtendedInfo );
182     bool            ImpDetectPPM( SvStream& rStm, bool bExtendedInfo );
183     bool            ImpDetectRAS( SvStream& rStm, bool bExtendedInfo );
184     bool            ImpDetectTGA( SvStream& rStm, bool bExtendedInfo );
185     bool            ImpDetectPSD( SvStream& rStm, bool bExtendedInfo );
186     bool            ImpDetectEPS( SvStream& rStm, bool bExtendedInfo );
187     bool            ImpDetectDXF( SvStream& rStm, bool bExtendedInfo );
188     bool            ImpDetectMET( SvStream& rStm, bool bExtendedInfo );
189     bool            ImpDetectPCT( SvStream& rStm, bool bExtendedInfo );
190     bool            ImpDetectSVM( SvStream& rStm, bool bExtendedInfo );
191     bool            ImpDetectWMF( SvStream& rStm, bool bExtendedInfo );
192     bool            ImpDetectEMF( SvStream& rStm, bool bExtendedInfo );
193     bool            ImpDetectSVG( SvStream& rStm, bool bExtendedInfo );
194     GraphicDescriptor( const GraphicDescriptor& ) = delete;
195     GraphicDescriptor& operator=( const GraphicDescriptor& ) = delete;
196 
197 public:
198 
199     /** Ctor to set a filename
200 
201         Detect() must be called to identify the file
202         If the file has no unique header (Mtf's), the format
203         is determined from the extension */
204     GraphicDescriptor( const INetURLObject& rPath );
205 
206     /** Ctor using a stream
207 
208         Detect() must be called to identify the file
209         As some formats (Mtf's) do not have a unique header, it makes sense
210         to supply the file name (incl. ext.), so that the format can be
211         derived from the extension */
212     GraphicDescriptor( SvStream& rInStream, const OUString* pPath );
213 
214     ~GraphicDescriptor();
215 
216     /** starts the detection
217 
218         if bExtendedInfo == true the file header is used to derive
219         as many properties as possible (size, color, etc.) */
220     bool    Detect( bool bExtendedInfo = false );
221 
222     /** @return the file format, GraphicFileFormat::NOT if no format was recognized */
GetFileFormat() const223     GraphicFileFormat  GetFileFormat() const { return nFormat; }
224 
225     /** @return graphic size in pixels or 0 size */
GetSizePixel() const226     const Size&     GetSizePixel() const { return aPixSize; }
227 
228     /** @return the logical graphic size in 1/100mm or 0 size */
GetSize_100TH_MM() const229     const Size&     GetSize_100TH_MM() const { return aLogSize; }
230 
231     /**
232      * Returns the logic size, according to the map mode available via GetPreferredMapMode(). Prefer
233      * this size over GetSize_100TH_MM().
234      */
GetPreferredLogSize() const235     std::optional<Size> GetPreferredLogSize() const { return maPreferredLogSize; }
236 
237     /**
238      * If available, this returns the map mode the graphic prefers, which may be other than pixel or
239      * 100th mm. Prefer this map mode over just assuming MapUnit::Map100thMM.
240      */
GetPreferredMapMode() const241     std::optional<MapMode> GetPreferredMapMode() const { return maPreferredMapMode; }
242 
243     /** @return bits/pixel or 0 **/
GetBitsPerPixel() const244     sal_uInt16          GetBitsPerPixel() const { return nBitsPerPixel; }
245 
246     /** @return number of color channels */
GetNumberOfImageComponents() const247     sal_uInt8 GetNumberOfImageComponents() const { return mnNumberOfImageComponents; }
248 
249     /** @return whether image supports transparency */
IsTransparent() const250     bool IsTransparent() const { return bIsTransparent; }
251 
252     /** @return whether image supports alpha values for translucent colours */
IsAlpha() const253     bool IsAlpha() const { return bIsAlpha; }
254 
255     /** @return filter number that is needed by the GraphFilter to read this format */
256     static OUString GetImportFormatShortName( GraphicFileFormat nFormat );
257 };
258 
259 /** Information about errors during the GraphicFilter operation. */
260 struct FilterErrorEx
261 {
262     ErrCode   nStreamError;
263 
FilterErrorExFilterErrorEx264     FilterErrorEx() : nStreamError( ERRCODE_NONE ) {}
265 };
266 
267 /** Class to import and export graphic formats. */
268 class VCL_DLLPUBLIC GraphicFilter
269 {
270 public:
271                     GraphicFilter( bool bUseConfig = true );
272                     ~GraphicFilter();
273 
274     sal_uInt16      GetImportFormatCount() const;
275     sal_uInt16      GetImportFormatNumber( std::u16string_view rFormatName );
276     sal_uInt16      GetImportFormatNumberForShortName( std::u16string_view rShortName );
277     sal_uInt16      GetImportFormatNumberForTypeName( std::u16string_view rType );
278     OUString        GetImportFormatName( sal_uInt16 nFormat );
279     OUString        GetImportFormatTypeName( sal_uInt16 nFormat );
280 #ifdef _WIN32
281     OUString        GetImportFormatMediaType( sal_uInt16 nFormat );
282 #endif
283     OUString        GetImportFormatShortName( sal_uInt16 nFormat );
284     OUString        GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry );
285 
286     sal_uInt16      GetExportFormatCount() const;
287     sal_uInt16      GetExportFormatNumber( std::u16string_view rFormatName );
288     sal_uInt16      GetExportFormatNumberForMediaType( std::u16string_view rShortName );
289     sal_uInt16      GetExportFormatNumberForShortName( std::u16string_view rShortName );
290     OUString        GetExportInternalFilterName( sal_uInt16 nFormat );
291     sal_uInt16      GetExportFormatNumberForTypeName( std::u16string_view rType );
292     OUString        GetExportFormatName( sal_uInt16 nFormat );
293     OUString        GetExportFormatMediaType( sal_uInt16 nFormat );
294     OUString        GetExportFormatShortName( sal_uInt16 nFormat );
295     OUString        GetExportWildcard( sal_uInt16 nFormat );
296     bool            IsExportPixelFormat( sal_uInt16 nFormat );
297 
298     ErrCode             ExportGraphic( const Graphic& rGraphic, const INetURLObject& rPath,
299                                        sal_uInt16 nFormat,
300                                        const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr );
301     ErrCode             ExportGraphic( const Graphic& rGraphic, const OUString& rPath,
302                                        SvStream& rOStm, sal_uInt16 nFormat,
303                                        const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr );
304 
305     ErrCode             CanImportGraphic( const INetURLObject& rPath,
306                                       sal_uInt16 nFormat,
307                                       sal_uInt16 * pDeterminedFormat);
308 
309     ErrCode             ImportGraphic( Graphic& rGraphic, const INetURLObject& rPath,
310                                    sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
311                                    sal_uInt16 * pDeterminedFormat = nullptr, GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE );
312 
313     ErrCode             CanImportGraphic( const OUString& rPath, SvStream& rStream,
314                                       sal_uInt16 nFormat,
315                                       sal_uInt16 * pDeterminedFormat);
316 
317     ErrCode             ImportGraphic( Graphic& rGraphic, const OUString& rPath,
318                                    SvStream& rStream,
319                                    sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
320                                    sal_uInt16 * pDeterminedFormat = nullptr, GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE,
321                                    WmfExternal const *pExtHeader = nullptr );
322 
323     /// Imports multiple graphics.
324     ///
325     /// The resulting graphic is added to rGraphics on success, nullptr is added on failure.
326     void ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, std::vector< std::unique_ptr<SvStream> > vStreams);
327 
328     /**
329      Tries to ensure all Graphic objects are available (Graphic::isAvailable()). Only an optimization, may
330      not process all items.
331     */
332     void MakeGraphicsAvailableThreaded(std::vector< Graphic* >& rGraphics);
333 
334     ErrCode             ImportGraphic( Graphic& rGraphic, const OUString& rPath,
335                                    SvStream& rStream,
336                                    sal_uInt16 nFormat,
337                                    sal_uInt16 * pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
338                                    const css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
339                                    WmfExternal const *pExtHeader = nullptr );
340 
341     // Setting sizeLimit limits how much will be read from the stream.
342     Graphic ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit = 0, const Size* pSizeHint = nullptr);
343 
GetLastError() const344     const FilterErrorEx&    GetLastError() const { return *pErrorEx;}
345     void                    ResetLastError();
346 
347     Link<ConvertData&,bool> GetFilterCallback() const;
348     static GraphicFilter& GetGraphicFilter();
349     static ErrCode  LoadGraphic( const OUString& rPath, const OUString& rFilter,
350                      Graphic& rGraphic,
351                      GraphicFilter* pFilter = nullptr,
352                      sal_uInt16* pDeterminedFormat = nullptr );
353 
354     ErrCode         compressAsPNG(const Graphic& rGraphic, SvStream& rOutputStream);
355 
356     static ErrCode readGIF(SvStream& rStream, Graphic& rGraphic, GfxLinkType& rLinkType);
357     static ErrCode readPNG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
358                     std::unique_ptr<sal_uInt8[]> & rpGraphicContent, sal_Int32& rGraphicContentSize);
359     static ErrCode readJPEG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
360                     GraphicFilterImportFlags nImportFlags);
361     static ErrCode readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
362                     std::unique_ptr<sal_uInt8[]> & rpGraphicContent, sal_Int32& rGraphicContentSize);
363     static ErrCode readXBM(SvStream & rStream, Graphic & rGraphic);
364     static ErrCode readXPM(SvStream & rStream, Graphic & rGraphic);
365 
366     static ErrCode readWMF_EMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
367                         WmfExternal const* pExtHeader, VectorGraphicDataType eType);
368     static ErrCode readWMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, WmfExternal const* pExtHeader);
369     static ErrCode readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, WmfExternal const* pExtHeader);
370 
371     static ErrCode readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
372     static ErrCode readTIFF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
373     static ErrCode readWithTypeSerializer(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, OUString aFilterName);
374     static ErrCode readBMP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
375     static ErrCode readTGA(SvStream & rStream, Graphic & rGraphic);
376     static ErrCode readPICT(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
377     static ErrCode readMET(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
378     static ErrCode readRAS(SvStream & rStream, Graphic & rGraphic);
379     static ErrCode readPCX(SvStream & rStream, Graphic & rGraphic);
380     static ErrCode readEPS(SvStream & rStream, Graphic & rGraphic);
381     static ErrCode readPSD(SvStream & rStream, Graphic & rGraphic);
382     static ErrCode readPCD(SvStream & rStream, Graphic & rGraphic);
383     static ErrCode readPBM(SvStream & rStream, Graphic & rGraphic);
384     static ErrCode readDXF(SvStream & rStream, Graphic & rGraphic);
385 
386 private:
387     OUString        aFilterPath;
388     FilterConfigCache*  pConfig;
389 
390     void            ImplInit();
391     ErrCode         ImplSetError( ErrCode nError, const SvStream* pStm = nullptr );
392     ErrCode         ImpTestOrFindFormat( const OUString& rPath, SvStream& rStream, sal_uInt16& rFormat );
393 
394                     DECL_LINK( FilterCallback, ConvertData&, bool );
395 
396     std::unique_ptr<FilterErrorEx> pErrorEx;
397     bool                bUseConfig;
398 };
399 
400 #endif // INCLUDED_VCL_GRAPHICFILTER_HXX
401 
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
403