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 <graphic/UnoGraphicDescriptor.hxx>
21 
22 #include <unotools/ucbstreamhelper.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <cppuhelper/supportsservice.hxx>
25 
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <com/sun/star/awt/Size.hpp>
28 #include <com/sun/star/graphic/GraphicType.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 
31 #include <vcl/outdev.hxx>
32 #include <vcl/graph.hxx>
33 #include <vcl/svapp.hxx>
34 #include <memory>
35 
36 namespace {
37 
38 enum class UnoGraphicProperty
39 {
40       GraphicType = 1
41     , MimeType = 2
42     , SizePixel = 3
43     , Size100thMM = 4
44     , BitsPerPixel = 5
45     , Transparent = 6
46     , Alpha = 7
47     , Animated = 8
48     , Linked = 9
49     , OriginURL = 10
50 };
51 
52 }
53 
54 using namespace ::com::sun::star;
55 
56 namespace unographic {
57 
58 
59 GraphicDescriptor::GraphicDescriptor() :
60     ::comphelper::PropertySetHelper( createPropertySetInfo() ),
61     mpGraphic( nullptr ),
62     meType( GraphicType::NONE ),
63     mnBitsPerPixel ( 0 ),
64     mbTransparent ( false )
65 {
66 }
67 
68 GraphicDescriptor::~GraphicDescriptor()
69     noexcept
70 {
71 }
72 
73 void GraphicDescriptor::init( const ::Graphic& rGraphic )
74 {
75     mpGraphic = &rGraphic;
76 }
77 
78 void GraphicDescriptor::init( const OUString& rURL )
79 {
80     std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( rURL, StreamMode::READ ));
81 
82     if( pIStm )
83         implCreate( *pIStm, &rURL );
84 }
85 
86 void GraphicDescriptor::init( const uno::Reference< io::XInputStream >& rxIStm, const OUString& rURL )
87 {
88     std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( rxIStm ));
89 
90     if( pIStm )
91         implCreate( *pIStm, &rURL );
92 }
93 
94 void GraphicDescriptor::implCreate( SvStream& rIStm, const OUString* pURL )
95 {
96     OUString aURL;
97     if( pURL )
98         aURL = *pURL;
99     ::GraphicDescriptor aDescriptor( rIStm, &aURL );
100 
101     mpGraphic = nullptr;
102     maMimeType.clear();
103     meType = GraphicType::NONE;
104     mnBitsPerPixel = 0;
105     mbTransparent = false;
106 
107     if( !(aDescriptor.Detect( true ) && aDescriptor.GetFileFormat() != GraphicFileFormat::NOT) )
108         return;
109 
110     const char*             pMimeType = nullptr;
111     sal_uInt8               cType = graphic::GraphicType::EMPTY;
112 
113     switch( aDescriptor.GetFileFormat() )
114     {
115         case GraphicFileFormat::BMP: pMimeType = MIMETYPE_BMP; cType = graphic::GraphicType::PIXEL; break;
116         case GraphicFileFormat::GIF: pMimeType = MIMETYPE_GIF; cType = graphic::GraphicType::PIXEL; break;
117         case GraphicFileFormat::JPG: pMimeType = MIMETYPE_JPG; cType = graphic::GraphicType::PIXEL; break;
118         case GraphicFileFormat::PCD: pMimeType = MIMETYPE_PCD; cType = graphic::GraphicType::PIXEL; break;
119         case GraphicFileFormat::PCX: pMimeType = MIMETYPE_PCX; cType = graphic::GraphicType::PIXEL; break;
120         case GraphicFileFormat::PNG: pMimeType = MIMETYPE_PNG; cType = graphic::GraphicType::PIXEL; break;
121         case GraphicFileFormat::TIF: pMimeType = MIMETYPE_TIF; cType = graphic::GraphicType::PIXEL; break;
122         case GraphicFileFormat::XBM: pMimeType = MIMETYPE_XBM; cType = graphic::GraphicType::PIXEL; break;
123         case GraphicFileFormat::XPM: pMimeType = MIMETYPE_XPM; cType = graphic::GraphicType::PIXEL; break;
124         case GraphicFileFormat::PBM: pMimeType = MIMETYPE_PBM; cType = graphic::GraphicType::PIXEL; break;
125         case GraphicFileFormat::PGM: pMimeType = MIMETYPE_PGM; cType = graphic::GraphicType::PIXEL; break;
126         case GraphicFileFormat::PPM: pMimeType = MIMETYPE_PPM; cType = graphic::GraphicType::PIXEL; break;
127         case GraphicFileFormat::RAS: pMimeType = MIMETYPE_RAS; cType = graphic::GraphicType::PIXEL; break;
128         case GraphicFileFormat::TGA: pMimeType = MIMETYPE_TGA; cType = graphic::GraphicType::PIXEL; break;
129         case GraphicFileFormat::PSD: pMimeType = MIMETYPE_PSD; cType = graphic::GraphicType::PIXEL; break;
130         case GraphicFileFormat::WEBP: pMimeType = MIMETYPE_WEBP; cType = graphic::GraphicType::PIXEL; break;
131 
132         case GraphicFileFormat::EPS: pMimeType = MIMETYPE_EPS; cType = graphic::GraphicType::VECTOR; break;
133         case GraphicFileFormat::DXF: pMimeType = MIMETYPE_DXF; cType = graphic::GraphicType::VECTOR; break;
134         case GraphicFileFormat::MET: pMimeType = MIMETYPE_MET; cType = graphic::GraphicType::VECTOR; break;
135         case GraphicFileFormat::PCT: pMimeType = MIMETYPE_PCT; cType = graphic::GraphicType::VECTOR; break;
136         case GraphicFileFormat::SVM: pMimeType = MIMETYPE_SVM; cType = graphic::GraphicType::VECTOR; break;
137         case GraphicFileFormat::WMF: pMimeType = MIMETYPE_WMF; cType = graphic::GraphicType::VECTOR; break;
138         case GraphicFileFormat::EMF: pMimeType = MIMETYPE_EMF; cType = graphic::GraphicType::VECTOR; break;
139         case GraphicFileFormat::SVG: pMimeType = MIMETYPE_SVG; cType = graphic::GraphicType::VECTOR; break;
140 
141         default:
142         break;
143     }
144 
145     if( graphic::GraphicType::EMPTY != cType )
146     {
147         meType = ( ( graphic::GraphicType::PIXEL == cType ) ? GraphicType::Bitmap : GraphicType::GdiMetafile );
148         maMimeType = OUString( pMimeType, strlen(pMimeType), RTL_TEXTENCODING_ASCII_US );
149         maSizePixel = aDescriptor.GetSizePixel();
150         maSize100thMM = aDescriptor.GetSize_100TH_MM();
151         mnBitsPerPixel = aDescriptor.GetBitsPerPixel();
152         mbTransparent = ( graphic::GraphicType::VECTOR == cType );
153     }
154 }
155 
156 
157 uno::Any SAL_CALL GraphicDescriptor::queryAggregation( const uno::Type & rType )
158 {
159     uno::Any aAny;
160 
161     if( rType == cppu::UnoType<lang::XServiceInfo>::get())
162         aAny <<= uno::Reference< lang::XServiceInfo >(this);
163     else if( rType == cppu::UnoType<lang::XTypeProvider>::get())
164         aAny <<= uno::Reference< lang::XTypeProvider >(this);
165     else if( rType == cppu::UnoType<beans::XPropertySet>::get())
166         aAny <<= uno::Reference< beans::XPropertySet >(this);
167     else if( rType == cppu::UnoType<beans::XPropertyState>::get())
168         aAny <<= uno::Reference< beans::XPropertyState >(this);
169     else if( rType == cppu::UnoType<beans::XMultiPropertySet>::get())
170         aAny <<= uno::Reference< beans::XMultiPropertySet >(this);
171     else
172         aAny = OWeakAggObject::queryAggregation( rType );
173 
174     return aAny;
175 }
176 
177 
178 uno::Any SAL_CALL GraphicDescriptor::queryInterface( const uno::Type & rType )
179 {
180     return OWeakAggObject::queryInterface( rType );
181 }
182 
183 
184 void SAL_CALL GraphicDescriptor::acquire()
185     noexcept
186 {
187     OWeakAggObject::acquire();
188 }
189 
190 
191 void SAL_CALL GraphicDescriptor::release()
192     noexcept
193 {
194     OWeakAggObject::release();
195 }
196 
197 
198 OUString SAL_CALL GraphicDescriptor::getImplementationName()
199 {
200     return "com.sun.star.comp.graphic.GraphicDescriptor";
201 }
202 
203 sal_Bool SAL_CALL GraphicDescriptor::supportsService( const OUString& ServiceName )
204 {
205     return cppu::supportsService(this, ServiceName);
206 }
207 
208 
209 uno::Sequence< OUString > SAL_CALL GraphicDescriptor::getSupportedServiceNames()
210 {
211     return { "com.sun.star.graphic.GraphicDescriptor" };
212 }
213 
214 
215 uno::Sequence< uno::Type > SAL_CALL GraphicDescriptor::getTypes()
216 {
217     static const uno::Sequence< uno::Type > aTypes {
218         cppu::UnoType<uno::XAggregation>::get(),
219         cppu::UnoType<lang::XServiceInfo>::get(),
220         cppu::UnoType<lang::XTypeProvider>::get(),
221         cppu::UnoType<beans::XPropertySet>::get(),
222         cppu::UnoType<beans::XPropertyState>::get(),
223         cppu::UnoType<beans::XMultiPropertySet>::get() };
224     return aTypes;
225 }
226 
227 uno::Sequence< sal_Int8 > SAL_CALL GraphicDescriptor::getImplementationId()
228 {
229     return css::uno::Sequence<sal_Int8>();
230 }
231 
232 
233 rtl::Reference<::comphelper::PropertySetInfo> GraphicDescriptor::createPropertySetInfo()
234 {
235     static ::comphelper::PropertyMapEntry const aEntries[] =
236     {
237         { OUString( "GraphicType" ), static_cast< sal_Int32 >( UnoGraphicProperty::GraphicType ), cppu::UnoType< sal_Int8 >::get(), beans::PropertyAttribute::READONLY, 0 },
238         { OUString( "MimeType" ), static_cast< sal_Int32 >( UnoGraphicProperty::MimeType ), cppu::UnoType< OUString >::get(), beans::PropertyAttribute::READONLY, 0 },
239         { OUString( "SizePixel" ), static_cast< sal_Int32 >( UnoGraphicProperty::SizePixel ), cppu::UnoType< awt::Size >::get(), beans::PropertyAttribute::READONLY, 0 },
240         { OUString( "Size100thMM" ), static_cast< sal_Int32 >( UnoGraphicProperty::Size100thMM ), cppu::UnoType< awt::Size >::get(), beans::PropertyAttribute::READONLY, 0 },
241         { OUString( "BitsPerPixel" ), static_cast< sal_Int32 >( UnoGraphicProperty::BitsPerPixel ), cppu::UnoType< sal_uInt8 >::get(), beans::PropertyAttribute::READONLY, 0 },
242         { OUString( "Transparent" ), static_cast< sal_Int32 >( UnoGraphicProperty::Transparent ), cppu::UnoType< sal_Bool >::get(), beans::PropertyAttribute::READONLY, 0 },
243         { OUString( "Alpha" ), static_cast< sal_Int32 >( UnoGraphicProperty::Alpha ), cppu::UnoType< sal_Bool >::get(), beans::PropertyAttribute::READONLY, 0 },
244         { OUString( "Animated" ), static_cast< sal_Int32 >( UnoGraphicProperty::Animated ), cppu::UnoType< sal_Bool >::get(), beans::PropertyAttribute::READONLY, 0 },
245         { OUString("Linked"), sal_Int32(UnoGraphicProperty::Linked), cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY, 0 },
246         { OUString("OriginURL"), sal_Int32(UnoGraphicProperty::OriginURL), cppu::UnoType<OUString>::get(), beans::PropertyAttribute::READONLY, 0 },
247     };
248 
249     return rtl::Reference<::comphelper::PropertySetInfo>( new ::comphelper::PropertySetInfo(aEntries) );
250 }
251 
252 
253 void GraphicDescriptor::_setPropertyValues( const comphelper::PropertyMapEntry** /*ppEntries*/, const uno::Any* /*pValues*/ )
254 {
255     // we only have readonly attributes
256 }
257 
258 
259 void GraphicDescriptor::_getPropertyValues( const comphelper::PropertyMapEntry** ppEntries, uno::Any* pValues )
260 {
261     SolarMutexGuard aGuard;
262 
263     while( *ppEntries )
264     {
265         UnoGraphicProperty theProperty = static_cast< UnoGraphicProperty >( (*ppEntries)->mnHandle );
266         switch( theProperty )
267         {
268             case UnoGraphicProperty::GraphicType:
269             {
270                 const GraphicType eType( mpGraphic ? mpGraphic->GetType() : meType );
271 
272                 *pValues <<= ( eType == GraphicType::Bitmap ? graphic::GraphicType::PIXEL :
273                                 ( eType == GraphicType::GdiMetafile ? graphic::GraphicType::VECTOR :
274                                 graphic::GraphicType::EMPTY ) );
275             }
276             break;
277 
278             case UnoGraphicProperty::MimeType:
279             {
280                 OUString aMimeType;
281 
282                 if( mpGraphic )
283                 {
284                     if( mpGraphic->IsGfxLink() )
285                     {
286                         const char* pMimeType;
287 
288                         switch( mpGraphic->GetGfxLink().GetType() )
289                         {
290                             case GfxLinkType::NativeGif: pMimeType = MIMETYPE_GIF; break;
291 
292                             // #i15508# added BMP type for better exports (checked, works)
293                             case GfxLinkType::NativeBmp: pMimeType = MIMETYPE_BMP; break;
294 
295                             case GfxLinkType::NativeJpg: pMimeType = MIMETYPE_JPG; break;
296                             case GfxLinkType::NativePng: pMimeType = MIMETYPE_PNG; break;
297                             case GfxLinkType::NativeWmf: pMimeType = MIMETYPE_WMF; break;
298                             case GfxLinkType::NativeMet: pMimeType = MIMETYPE_MET; break;
299                             case GfxLinkType::NativePct: pMimeType = MIMETYPE_PCT; break;
300                             case GfxLinkType::NativeWebp: pMimeType = MIMETYPE_WEBP; break;
301 
302                             // added Svg mimetype support
303                             case GfxLinkType::NativeSvg: pMimeType = MIMETYPE_SVG; break;
304                             case GfxLinkType::NativePdf: pMimeType = MIMETYPE_PDF; break;
305 
306                             default:
307                                 pMimeType = nullptr;
308                             break;
309                         }
310 
311                         if( pMimeType )
312                             aMimeType = OUString::createFromAscii( pMimeType );
313                     }
314 
315                     if( aMimeType.isEmpty() && ( mpGraphic->GetType() != GraphicType::NONE ) )
316                         aMimeType = MIMETYPE_VCLGRAPHIC;
317                 }
318                 else
319                     aMimeType = maMimeType;
320 
321                 *pValues <<= aMimeType;
322             }
323             break;
324 
325             case UnoGraphicProperty::SizePixel:
326             {
327                 awt::Size aAWTSize( 0, 0 );
328 
329                 if( mpGraphic )
330                 {
331                     if( mpGraphic->GetType() == GraphicType::Bitmap )
332                     {
333                         const Size aSizePix( mpGraphic->GetSizePixel() );
334                         aAWTSize = awt::Size( aSizePix.Width(), aSizePix.Height() );
335                     }
336                 }
337                 else
338                     aAWTSize = awt::Size( maSizePixel.Width(), maSizePixel.Height() );
339 
340                 *pValues <<= aAWTSize;
341             }
342             break;
343 
344             case UnoGraphicProperty::Size100thMM:
345             {
346                 awt::Size aAWTSize( 0, 0 );
347 
348                 if( mpGraphic )
349                 {
350                     if( mpGraphic->GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
351                     {
352                         const Size aSizeLog( OutputDevice::LogicToLogic(
353                             mpGraphic->GetPrefSize(),
354                             mpGraphic->GetPrefMapMode(),
355                             MapMode(MapUnit::Map100thMM)) );
356                         aAWTSize = awt::Size( aSizeLog.Width(), aSizeLog.Height() );
357                     }
358                 }
359                 else
360                     aAWTSize = awt::Size( maSize100thMM.Width(), maSize100thMM.Height() );
361 
362                 *pValues <<= aAWTSize;
363             }
364             break;
365 
366             case UnoGraphicProperty::BitsPerPixel:
367             {
368                 sal_uInt16 nBitsPerPixel = 0;
369 
370                 if( mpGraphic )
371                 {
372                     if( mpGraphic->GetType() == GraphicType::Bitmap )
373                     {
374                         auto ePixelFormat = mpGraphic->GetBitmapEx().GetBitmap().getPixelFormat();
375                         nBitsPerPixel = vcl::pixelFormatBitCount(ePixelFormat);
376                     }
377                 }
378                 else
379                     nBitsPerPixel = mnBitsPerPixel;
380 
381                 *pValues <<= sal::static_int_cast< sal_Int8 >(nBitsPerPixel);
382             }
383             break;
384 
385             case UnoGraphicProperty::Transparent:
386             {
387                 *pValues <<= mpGraphic ? mpGraphic->IsTransparent() : mbTransparent;
388             }
389             break;
390 
391             case UnoGraphicProperty::Alpha:
392             {
393                 *pValues <<= mpGraphic && mpGraphic->IsAlpha();
394             }
395             break;
396 
397             case UnoGraphicProperty::Animated:
398             {
399                 *pValues <<= mpGraphic && mpGraphic->IsAnimated();
400             }
401             break;
402 
403             case UnoGraphicProperty::Linked:
404             {
405                 *pValues <<= mpGraphic && !mpGraphic->getOriginURL().isEmpty();
406             }
407             break;
408 
409             case UnoGraphicProperty::OriginURL:
410             {
411                 OUString aOriginURL;
412                 if (mpGraphic)
413                     aOriginURL = mpGraphic->getOriginURL();
414 
415                 *pValues <<= aOriginURL;
416             }
417             break;
418         }
419 
420         ++ppEntries;
421         ++pValues;
422     }
423 }
424 
425 }
426 
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
428