LibreOffice Module vcl (master)  1
UnoGraphicProvider.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 <o3tl/string_view.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/image.hxx>
23 #include <vcl/metaact.hxx>
24 #include <imagerepository.hxx>
25 #include <tools/fract.hxx>
27 #include <vcl/graphicfilter.hxx>
28 #include <vcl/stdtext.hxx>
29 #include <vcl/wmfexternal.hxx>
30 #include <vcl/virdev.hxx>
31 #include <com/sun/star/awt/XBitmap.hpp>
32 #include <com/sun/star/graphic/XGraphicProvider2.hpp>
33 #include <com/sun/star/io/XStream.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/text/GraphicCrop.hpp>
36 #include <com/sun/star/uno/XComponentContext.hpp>
37 #include <comphelper/fileformat.h>
39 #include <cppuhelper/implbase.hxx>
41 #include <sal/log.hxx>
42 
44 #include <graphic/UnoGraphic.hxx>
45 #include <rtl/ref.hxx>
46 #include <vcl/dibtools.hxx>
47 #include <comphelper/sequence.hxx>
48 #include <memory>
49 #include <string_view>
50 
51 #include <vcl/TypeSerializer.hxx>
52 
53 using namespace com::sun::star;
54 
55 namespace {
56 
57 class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2,
58  css::lang::XServiceInfo >
59 {
60 public:
61 
62  GraphicProvider();
63 
64 protected:
65 
66  // XServiceInfo
67  virtual OUString SAL_CALL getImplementationName() override;
68  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
69  virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
70 
71  // XTypeProvider
72  virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
73  virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
74 
75  // XGraphicProvider
76  virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL queryGraphicDescriptor( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
77  virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL queryGraphic( const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
78  virtual void SAL_CALL storeGraphic( const css::uno::Reference< css::graphic::XGraphic >& Graphic, const css::uno::Sequence< css::beans::PropertyValue >& MediaProperties ) override;
79 
80  // XGraphicProvider2
81  uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& MediaPropertiesSeq ) override;
82 
83 private:
84 
85  static css::uno::Reference< css::graphic::XGraphic > implLoadMemory( const OUString& rResourceURL );
86  static css::uno::Reference< css::graphic::XGraphic > implLoadRepositoryImage( std::u16string_view rResourceURL );
87  static css::uno::Reference< css::graphic::XGraphic > implLoadBitmap( const css::uno::Reference< css::awt::XBitmap >& rBitmap );
88  static css::uno::Reference< css::graphic::XGraphic > implLoadStandardImage( std::u16string_view rResourceURL );
89 };
90 
91 GraphicProvider::GraphicProvider()
92 {
93 }
94 
95 OUString SAL_CALL GraphicProvider::getImplementationName()
96 {
97  return "com.sun.star.comp.graphic.GraphicProvider";
98 }
99 
100 sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
101 {
102  return cppu::supportsService( this, ServiceName );
103 }
104 
105 uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
106 {
107  return { "com.sun.star.graphic.GraphicProvider" };
108 }
109 
110 uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
111 {
112  static const uno::Sequence< uno::Type > aTypes {
116  };
117  return aTypes;
118 }
119 
120 uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
121 {
122  return css::uno::Sequence<sal_Int8>();
123 }
124 
125 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( const OUString& rResourceURL )
126 {
127  uno::Reference< ::graphic::XGraphic > xRet;
128  sal_Int32 nIndex = 0;
129 
130  if( rResourceURL.getToken( 0, '/', nIndex ) == "private:memorygraphic" )
131  {
132  sal_Int64 nGraphicAddress = rResourceURL.getToken( 0, '/', nIndex ).toInt64();
133 
134  if( nGraphicAddress )
135  {
136  rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic;
137 
138  pUnoGraphic->init( *reinterpret_cast< ::Graphic* >( nGraphicAddress ) );
139  xRet = pUnoGraphic;
140  }
141  }
142 
143  return xRet;
144 }
145 
146 
147 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( std::u16string_view rResourceURL )
148 {
149  uno::Reference< ::graphic::XGraphic > xRet;
150 
151  std::u16string_view sPathName;
152  if( o3tl::starts_with(rResourceURL, u"private:graphicrepository/", &sPathName) )
153  {
154  BitmapEx aBitmap;
155  if ( vcl::ImageRepository::loadImage( OUString(sPathName), aBitmap ) )
156  {
157  xRet = Graphic(aBitmap).GetXGraphic();
158  }
159  }
160  return xRet;
161 }
162 
163 
164 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadStandardImage( std::u16string_view rResourceURL )
165 {
166  uno::Reference< ::graphic::XGraphic > xRet;
167 
168  std::u16string_view sImageName;
169  if( o3tl::starts_with(rResourceURL, u"private:standardimage/", &sImageName) )
170  {
171  if ( sImageName == u"info" )
172  {
174  }
175  else if ( sImageName == u"warning" )
176  {
178  }
179  else if ( sImageName == u"error" )
180  {
182  }
183  else if ( sImageName == u"query" )
184  {
186  }
187  }
188  return xRet;
189 }
190 
191 
192 uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadBitmap( const uno::Reference< awt::XBitmap >& xBtm )
193 {
194  uno::Reference< ::graphic::XGraphic > xRet;
195  uno::Sequence< sal_Int8 > aBmpSeq( xBtm->getDIB() );
196  uno::Sequence< sal_Int8 > aMaskSeq( xBtm->getMaskDIB() );
197  SvMemoryStream aBmpStream( aBmpSeq.getArray(), aBmpSeq.getLength(), StreamMode::READ );
198  Bitmap aBmp;
199  BitmapEx aBmpEx;
200 
201  ReadDIB(aBmp, aBmpStream, true);
202 
203  if( aMaskSeq.hasElements() )
204  {
205  SvMemoryStream aMaskStream( aMaskSeq.getArray(), aMaskSeq.getLength(), StreamMode::READ );
206  Bitmap aMask;
207 
208  ReadDIB(aMask, aMaskStream, true);
209  aBmpEx = BitmapEx( aBmp, aMask );
210  }
211  else
212  aBmpEx = BitmapEx( aBmp );
213 
214  if( !aBmpEx.IsEmpty() )
215  {
216  rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic;
217 
218  pUnoGraphic->init( aBmpEx );
219  xRet = pUnoGraphic;
220  }
221  return xRet;
222 }
223 
224 uno::Reference< beans::XPropertySet > SAL_CALL GraphicProvider::queryGraphicDescriptor( const uno::Sequence< beans::PropertyValue >& rMediaProperties )
225 {
226  uno::Reference< beans::XPropertySet > xRet;
227 
228  OUString aURL;
229  uno::Reference< io::XInputStream > xIStm;
230  uno::Reference< awt::XBitmap >xBtm;
231 
232  for( const auto& rMediaProperty : rMediaProperties )
233  {
234  if (xRet.is())
235  break;
236 
237  const OUString aName( rMediaProperty.Name );
238  const uno::Any aValue( rMediaProperty.Value );
239 
240  if (aName == "URL")
241  {
242  aValue >>= aURL;
243  }
244  else if (aName == "InputStream")
245  {
246  aValue >>= xIStm;
247  }
248  else if (aName == "Bitmap")
249  {
250  aValue >>= xBtm;
251  }
252  }
253 
254  SolarMutexGuard g;
255 
256  if( xIStm.is() )
257  {
259  pDescriptor->init( xIStm, aURL );
260  xRet = pDescriptor;
261  }
262  else if( !aURL.isEmpty() )
263  {
264  uno::Reference< ::graphic::XGraphic > xGraphic( implLoadMemory( aURL ) );
265 
266  if ( !xGraphic.is() )
267  xGraphic = implLoadRepositoryImage( aURL );
268 
269  if ( !xGraphic.is() )
270  xGraphic = implLoadStandardImage( aURL );
271 
272  if( xGraphic.is() )
273  {
274  xRet.set( xGraphic, uno::UNO_QUERY );
275  }
276  else
277  {
279  pDescriptor->init( aURL );
280  xRet = pDescriptor;
281  }
282  }
283  else if( xBtm.is() )
284  {
285  uno::Reference< ::graphic::XGraphic > xGraphic( implLoadBitmap( xBtm ) );
286  if( xGraphic.is() )
287  xRet.set( xGraphic, uno::UNO_QUERY );
288  }
289 
290  return xRet;
291 }
292 
293 
294 uno::Reference< ::graphic::XGraphic > SAL_CALL GraphicProvider::queryGraphic( const uno::Sequence< ::beans::PropertyValue >& rMediaProperties )
295 {
296  uno::Reference< ::graphic::XGraphic > xRet;
297  OUString aPath;
298 
299  uno::Reference< io::XInputStream > xIStm;
300  uno::Reference< awt::XBitmap >xBtm;
301 
302  uno::Sequence< ::beans::PropertyValue > aFilterData;
303 
304  bool bLazyRead = false;
305  bool bLoadAsLink = false;
306 
307  for (const auto& rMediaProperty : rMediaProperties)
308  {
309  if (xRet.is())
310  break;
311 
312  const OUString aName( rMediaProperty.Name );
313  const uno::Any aValue( rMediaProperty.Value );
314 
315  if (aName == "URL")
316  {
317  OUString aURL;
318  aValue >>= aURL;
319  aPath = aURL;
320  }
321  else if (aName == "InputStream")
322  {
323  aValue >>= xIStm;
324  }
325  else if (aName == "Bitmap")
326  {
327  aValue >>= xBtm;
328  }
329  else if (aName == "FilterData")
330  {
331  aValue >>= aFilterData;
332  }
333  else if (aName == "LazyRead")
334  {
335  aValue >>= bLazyRead;
336  }
337  else if (aName == "LoadAsLink")
338  {
339  aValue >>= bLoadAsLink;
340  }
341  }
342 
343  // Check for the goal width and height if they are defined
344  sal_uInt16 nExtWidth = 0;
345  sal_uInt16 nExtHeight = 0;
346  sal_uInt16 nExtMapMode = 0;
347  for( const auto& rProp : std::as_const(aFilterData) )
348  {
349  const OUString aName( rProp.Name );
350  const uno::Any aValue( rProp.Value );
351 
352  if (aName == "ExternalWidth")
353  {
354  aValue >>= nExtWidth;
355  }
356  else if (aName == "ExternalHeight")
357  {
358  aValue >>= nExtHeight;
359  }
360  else if (aName == "ExternalMapMode")
361  {
362  aValue >>= nExtMapMode;
363  }
364  }
365 
366  SolarMutexGuard g;
367 
368  std::unique_ptr<SvStream> pIStm;
369 
370  if( xIStm.is() )
371  {
372  pIStm = ::utl::UcbStreamHelper::CreateStream( xIStm );
373  }
374  else if( !aPath.isEmpty() )
375  {
376  xRet = implLoadMemory( aPath );
377 
378  if ( !xRet.is() )
379  xRet = implLoadRepositoryImage( aPath );
380 
381  if ( !xRet.is() )
382  xRet = implLoadStandardImage( aPath );
383 
384  if( !xRet.is() )
385  pIStm = ::utl::UcbStreamHelper::CreateStream( aPath, StreamMode::READ );
386  }
387  else if( xBtm.is() )
388  {
389  xRet = implLoadBitmap( xBtm );
390  }
391 
392  if( pIStm )
393  {
395 
396  {
397  Graphic aVCLGraphic;
398 
399  // Define APM Header if goal height and width are defined
400  WmfExternal aExtHeader;
401  aExtHeader.xExt = nExtWidth;
402  aExtHeader.yExt = nExtHeight;
403  aExtHeader.mapMode = nExtMapMode;
404  WmfExternal *pExtHeader = nullptr;
405  if ( nExtMapMode > 0 )
406  {
407  pExtHeader = &aExtHeader;
408  bLazyRead = false;
409  }
410 
411  ErrCode error = ERRCODE_NONE;
412  if (bLazyRead)
413  {
414  Graphic aGraphic = rFilter.ImportUnloadedGraphic(*pIStm);
415  if (!aGraphic.IsNone())
416  aVCLGraphic = aGraphic;
417  }
418  if (aVCLGraphic.IsNone())
419  error = rFilter.ImportGraphic(aVCLGraphic, aPath, *pIStm, GRFILTER_FORMAT_DONTKNOW,
420  nullptr, GraphicFilterImportFlags::NONE, pExtHeader);
421 
422  if( (error == ERRCODE_NONE ) &&
423  ( aVCLGraphic.GetType() != GraphicType::NONE ) )
424  {
425  if (!aPath.isEmpty() && bLoadAsLink)
426  aVCLGraphic.setOriginURL(aPath);
427 
428  rtl::Reference<::unographic::Graphic> pUnoGraphic = new ::unographic::Graphic;
429 
430  pUnoGraphic->init( aVCLGraphic );
431  xRet = pUnoGraphic;
432  }
433  else{
434  SAL_WARN("svtools", "Could not create graphic for:" << aPath << " error: " << error);
435  }
436  }
437  }
438 
439  return xRet;
440 }
441 
442 uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL GraphicProvider::queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& rMediaPropertiesSeq)
443 {
444  SolarMutexGuard aGuard;
445 
446  // Turn properties into streams.
447  std::vector< std::unique_ptr<SvStream> > aStreams;
448  for (const auto& rMediaProperties : rMediaPropertiesSeq)
449  {
450  std::unique_ptr<SvStream> pStream;
451  uno::Reference<io::XInputStream> xStream;
452 
453  auto pProp = std::find_if(rMediaProperties.begin(), rMediaProperties.end(),
454  [](const beans::PropertyValue& rProp) { return rProp.Name == "InputStream"; });
455  if (pProp != rMediaProperties.end())
456  {
457  pProp->Value >>= xStream;
458  if (xStream.is())
459  pStream = utl::UcbStreamHelper::CreateStream(xStream);
460  }
461 
462  aStreams.push_back(std::move(pStream));
463  }
464 
465  // Import: streams to graphics.
466  std::vector< std::shared_ptr<Graphic> > aGraphics;
468  rFilter.ImportGraphics(aGraphics, std::move(aStreams));
469 
470  // Returning: graphics to UNO objects.
471  std::vector< uno::Reference<graphic::XGraphic> > aRet;
472  for (const auto& pGraphic : aGraphics)
473  {
474  uno::Reference<graphic::XGraphic> xGraphic;
475 
476  if (pGraphic)
477  {
479  pUnoGraphic->init(*pGraphic);
480  xGraphic = pUnoGraphic;
481  }
482 
483  aRet.push_back(xGraphic);
484  }
485 
486  return comphelper::containerToSequence(aRet);
487 }
488 
489 void ImplCalculateCropRect( ::Graphic const & rGraphic, const text::GraphicCrop& rGraphicCropLogic, tools::Rectangle& rGraphicCropPixel )
490 {
491  if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
492  return;
493 
494  Size aSourceSizePixel( rGraphic.GetSizePixel() );
495  if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) )
496  return;
497 
498  if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
499  return;
500 
501  Size aSize100thMM( 0, 0 );
502  if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
503  {
504  aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
505  }
506  else
507  {
508  aSize100thMM = Application::GetDefaultDevice()->PixelToLogic(rGraphic.GetPrefSize(), MapMode(MapUnit::Map100thMM));
509  }
510  if ( aSize100thMM.Width() && aSize100thMM.Height() )
511  {
512  double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
513  double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
514  rGraphicCropPixel.SetLeft( static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()) );
515  rGraphicCropPixel.SetTop( static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()) );
516  rGraphicCropPixel.SetRight( static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ) );
517  rGraphicCropPixel.SetBottom( static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ) );
518  }
519 }
520 
521 void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
522 {
523  if ( nPixelWidth && nPixelHeight )
524  {
525  BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
526  MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
527  Size aPrefSize( aBmpEx.GetPrefSize() );
528  aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
529  aBmpEx.SetPrefMapMode( aPrefMapMode );
530  aBmpEx.SetPrefSize( aPrefSize );
531  rGraphic = aBmpEx;
532  }
533 }
534 
535 void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
536 {
537  if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) )
538  return;
539 
540  const double fImageResolution = static_cast<double>( nImageResolution );
541  const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
542  const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
543  const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
544  const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
545  const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
546  const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
547 
548  sal_Int32 nDestPixelWidth = nSourcePixelWidth;
549  sal_Int32 nDestPixelHeight = nSourcePixelHeight;
550 
551  // check, if the bitmap DPI exceeds the maximum DPI
552  if( fSourceDPIX > fImageResolution )
553  {
554  nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
555  if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
556  nDestPixelWidth = nSourcePixelWidth;
557  }
558  if ( fSourceDPIY > fImageResolution )
559  {
560  nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
561  if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
562  nDestPixelHeight = nSourcePixelHeight;
563  }
564  if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
565  ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
566 }
567 
568 void ImplApplyFilterData( ::Graphic& rGraphic, const uno::Sequence< beans::PropertyValue >& rFilterData )
569 {
570  /* this method applies following attributes to the graphic, in the first step the
571  cropping area (logical size in 100thmm) is applied, in the second step the resolution
572  is applied, in the third step the graphic is scaled to the corresponding pixelsize.
573  if a parameter value is zero or not available the corresponding step will be skipped */
574 
575  sal_Int32 nPixelWidth = 0;
576  sal_Int32 nPixelHeight= 0;
577  sal_Int32 nImageResolution = 0;
578  awt::Size aLogicalSize( 0, 0 );
579  text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
580  bool bRemoveCropArea = true;
581 
582  for( const auto& rProp : rFilterData )
583  {
584  const OUString aName( rProp.Name );
585  const uno::Any aValue( rProp.Value );
586 
587  if (aName == "PixelWidth")
588  aValue >>= nPixelWidth;
589  else if (aName == "PixelHeight")
590  aValue >>= nPixelHeight;
591  else if (aName == "LogicalSize")
592  aValue >>= aLogicalSize;
593  else if (aName == "GraphicCropLogic")
594  aValue >>= aCropLogic;
595  else if (aName == "RemoveCropArea")
596  aValue >>= bRemoveCropArea;
597  else if (aName == "ImageResolution")
598  aValue >>= nImageResolution;
599  }
600  if ( rGraphic.GetType() == GraphicType::Bitmap )
601  {
602  if(rGraphic.getVectorGraphicData())
603  {
604  // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently
605  }
606  else
607  {
608  tools::Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
609  ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
610  if ( bRemoveCropArea )
611  {
612  BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
613  aBmpEx.Crop( aCropPixel );
614  rGraphic = aBmpEx;
615  }
616  Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
617  ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
618  ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
619  }
620  }
621  else if ( ( rGraphic.GetType() == GraphicType::GdiMetafile ) && nImageResolution )
622  {
624  GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
625  Size aMtfSize( OutputDevice::LogicToLogic(aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
626  if ( aMtfSize.Width() && aMtfSize.Height() )
627  {
628  MapMode aNewMapMode( MapUnit::Map100thMM );
629  aNewMapMode.SetScaleX( Fraction( aLogicalSize.Width, aMtfSize.Width() ) );
630  aNewMapMode.SetScaleY( Fraction( aLogicalSize.Height, aMtfSize.Height() ) );
631  aDummyVDev->EnableOutput( false );
632  aDummyVDev->SetMapMode( aNewMapMode );
633 
634  for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
635  {
636  MetaAction* pAction = aMtf.GetAction( i );
637  switch( pAction->GetType() )
638  {
639  // only optimizing common bitmap actions:
641  {
642  pAction->Execute( aDummyVDev.get() );
643  break;
644  }
646  {
647  const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
648  aDummyVDev->Push( pA->GetFlags() );
649  break;
650  }
651  case MetaActionType::POP:
652  {
653  aDummyVDev->Pop();
654  break;
655  }
658  {
659  BitmapEx aBmpEx;
660  Point aPos;
661  Size aSize;
662  if ( pAction->GetType() == MetaActionType::BMPSCALE )
663  {
664  MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
665  assert(pScaleAction);
666  aBmpEx = pScaleAction->GetBitmap();
667  aPos = pScaleAction->GetPoint();
668  aSize = pScaleAction->GetSize();
669  }
670  else
671  {
672  MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
673  assert(pScaleAction);
674  aBmpEx = pScaleAction->GetBitmapEx();
675  aPos = pScaleAction->GetPoint();
676  aSize = pScaleAction->GetSize();
677  }
678  ::Graphic aGraphic( aBmpEx );
679  const Size aSize100thmm( aDummyVDev->LogicToPixel( aSize ) );
680  Size aSize100thmm2( aDummyVDev->PixelToLogic(aSize100thmm, MapMode(MapUnit::Map100thMM)) );
681 
682  ImplApplyBitmapResolution( aGraphic, nImageResolution,
683  aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
684 
685  rtl::Reference<MetaAction> pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
686  aMtf.ReplaceAction( pNewAction, i );
687  break;
688  }
689  default:
690  case MetaActionType::BMP:
696  break;
697  }
698  }
699  rGraphic = aMtf;
700  }
701  }
702 }
703 
704 
705 void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
706 {
707  SolarMutexGuard g;
708 
709  std::unique_ptr<SvStream> pOStm;
710  OUString aPath;
711 
712  for( const auto& rMediaProperty : rMediaProperties )
713  {
714  const OUString aName( rMediaProperty.Name );
715  const uno::Any aValue( rMediaProperty.Value );
716 
717  if (aName == "URL")
718  {
719  OUString aURL;
720 
721  aValue >>= aURL;
722  pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC );
723  aPath = aURL;
724  }
725  else if (aName == "OutputStream")
726  {
727  uno::Reference< io::XStream > xOStm;
728 
729  aValue >>= xOStm;
730 
731  if( xOStm.is() )
732  pOStm = ::utl::UcbStreamHelper::CreateStream( xOStm );
733  }
734 
735  if( pOStm )
736  break;
737  }
738 
739  if( !pOStm )
740  return;
741 
742  uno::Sequence< beans::PropertyValue > aFilterDataSeq;
743  const char* pFilterShortName = nullptr;
744 
745  for( const auto& rMediaProperty : rMediaProperties )
746  {
747  const OUString aName( rMediaProperty.Name );
748  const uno::Any aValue( rMediaProperty.Value );
749 
750  if (aName == "FilterData")
751  {
752  aValue >>= aFilterDataSeq;
753  }
754  else if (aName == "MimeType")
755  {
756  OUString aMimeType;
757 
758  aValue >>= aMimeType;
759 
760  if (aMimeType == MIMETYPE_BMP)
761  pFilterShortName = "bmp";
762  else if (aMimeType == MIMETYPE_EPS)
763  pFilterShortName = "eps";
764  else if (aMimeType == MIMETYPE_GIF)
765  pFilterShortName = "gif";
766  else if (aMimeType == MIMETYPE_JPG)
767  pFilterShortName = "jpg";
768  else if (aMimeType == MIMETYPE_MET)
769  pFilterShortName = "met";
770  else if (aMimeType == MIMETYPE_PNG)
771  pFilterShortName = "png";
772  else if (aMimeType == MIMETYPE_PCT)
773  pFilterShortName = "pct";
774  else if (aMimeType == MIMETYPE_PBM)
775  pFilterShortName = "pbm";
776  else if (aMimeType == MIMETYPE_PGM)
777  pFilterShortName = "pgm";
778  else if (aMimeType == MIMETYPE_PPM)
779  pFilterShortName = "ppm";
780  else if (aMimeType == MIMETYPE_RAS)
781  pFilterShortName = "ras";
782  else if (aMimeType == MIMETYPE_SVM)
783  pFilterShortName = "svm";
784  else if (aMimeType == MIMETYPE_TIF)
785  pFilterShortName = "tif";
786  else if (aMimeType == MIMETYPE_EMF)
787  pFilterShortName = "emf";
788  else if (aMimeType == MIMETYPE_WMF)
789  pFilterShortName = "wmf";
790  else if (aMimeType == MIMETYPE_XPM)
791  pFilterShortName = "xpm";
792  else if (aMimeType == MIMETYPE_SVG)
793  pFilterShortName = "svg";
794  else if (aMimeType == MIMETYPE_VCLGRAPHIC)
795  pFilterShortName = MIMETYPE_VCLGRAPHIC;
796  }
797  }
798 
799  if( !pFilterShortName )
800  return;
801 
803 
804  {
805  const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
806  const ::Graphic* pGraphic = comphelper::getFromUnoTunnel<::Graphic>( xIFace );
807 
808  if( pGraphic && ( pGraphic->GetType() != GraphicType::NONE ) )
809  {
810  ::Graphic aGraphic( *pGraphic );
811  ImplApplyFilterData( aGraphic, aFilterDataSeq );
812 
813  /* sj: using a temporary memory stream, because some graphic filters are seeking behind
814  stream end (which leads to an invalid argument exception then). */
815  SvMemoryStream aMemStrm;
816  aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
817  if( 0 == strcmp( pFilterShortName, MIMETYPE_VCLGRAPHIC ) )
818  {
819  TypeSerializer aSerializer(aMemStrm);
820  aSerializer.writeGraphic(aGraphic);
821  }
822  else
823  {
824  rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
825  rFilter.GetExportFormatNumberForShortName( OUString::createFromAscii( pFilterShortName ) ),
826  ( aFilterDataSeq.hasElements() ? &aFilterDataSeq : nullptr ) );
827  }
828  pOStm->WriteBytes( aMemStrm.GetData(), aMemStrm.TellEnd() );
829  }
830  }
831 }
832 
833 }
834 
835 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
837  css::uno::XComponentContext *,
838  css::uno::Sequence<css::uno::Any> const &)
839 {
840  return cppu::acquire(new GraphicProvider);
841 }
842 
843 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MIMETYPE_BMP
BitmapEx GetBitmapEx(BitmapEx const &rBitmapEx, DrawModeFlags nDrawMode)
Definition: drawmode.cxx:224
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:97
Image const & GetStandardInfoBoxImage()
Definition: stdtext.cxx:49
URL aURL
Image const & GetStandardWarningBoxImage()
Definition: stdtext.cxx:60
sal_Int32 nIndex
#define MIMETYPE_XPM
#define MIMETYPE_PCT
const Point & GetPoint() const
Definition: metaact.hxx:714
bool ReadDIB(Bitmap &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1695
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
#define MIMETYPE_EMF
const MapMode & GetPrefMapMode() const
Definition: bitmapex.hxx:79
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1564
bool IsNone() const
Definition: graph.cxx:282
Size GetSizePixel(const OutputDevice *pRefDevice=nullptr) const
Definition: graph.cxx:411
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:296
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: bitmapex.hxx:80
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_graphic_GraphicProvider_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
#define MIMETYPE_PGM
void setOriginURL(OUString const &rOriginURL)
Definition: graph.cxx:543
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
const Size & GetSize() const
Definition: metaact.hxx:715
Class to import and export graphic formats.
#define MIMETYPE_PNG
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
virtual sal_uInt64 TellEnd() override
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1069
Graphic ImportUnloadedGraphic(SvStream &rIStream, sal_uInt64 sizeLimit=0, const Size *pSizeHint=nullptr)
constexpr tools::Long Width() const
#define MIMETYPE_PPM
const Point & GetPoint() const
Definition: metaact.hxx:820
Reference< XInputStream > xStream
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1485
const Size & GetPrefSize() const
Definition: bitmapex.hxx:76
#define MIMETYPE_WMF
#define MIMETYPE_SVG
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void ImportGraphics(std::vector< std::shared_ptr< Graphic > > &rGraphics, std::vector< std::unique_ptr< SvStream > > vStreams)
Imports multiple graphics.
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:339
const Size & GetSize() const
Definition: metaact.hxx:821
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
sal_uInt16 mapMode
One of the following values:
Definition: wmfexternal.hxx:50
constexpr void SetLeft(tools::Long v)
bool IsEmpty() const
Definition: BitmapEx.cxx:177
int i
GraphicType GetType() const
Definition: graph.cxx:293
static bool loadImage(const OUString &_rName, BitmapEx &_out_rImage)
loads an image from the application's image repository
#define MIMETYPE_EPS
Image const & GetStandardErrorBoxImage()
Definition: stdtext.cxx:71
const char *const aMimeType[]
unsigned char sal_Bool
#define GRFILTER_FORMAT_DONTKNOW
css::uno::Type const & get()
constexpr void SetRight(tools::Long v)
MapUnit GetMapUnit() const
Definition: mapmod.cxx:138
constexpr void SetBottom(tools::Long v)
#define MIMETYPE_GIF
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:329
void SetVersion(sal_Int32 n)
#define MIMETYPE_TIF
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
const SvXMLTokenMapEntry aTypes[]
constexpr void SetTop(tools::Long v)
sal_uInt16 xExt
Definition: wmfexternal.hxx:33
#define MIMETYPE_SVM
const Bitmap & GetBitmap() const
Definition: metaact.hxx:713
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1109
Size GetPrefSize() const
Definition: graph.cxx:363
#define MIMETYPE_RAS
#define MIMETYPE_PBM
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:819
sal_uInt16 yExt
Definition: wmfexternal.hxx:34
#define ERRCODE_NONE
Definition: errcode.hxx:196
MapMode GetPrefMapMode() const
Definition: graph.cxx:374
constexpr tools::Long Height() const
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString aName
void SetPrefSize(const Size &rPrefSize)
Definition: bitmapex.hxx:77
MetaActionType GetType() const
Definition: metaact.hxx:93
#define MIMETYPE_JPG
#define MIMETYPE_VCLGRAPHIC
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
Definition: graph.cxx:349
static GraphicFilter & GetGraphicFilter()
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
#define SAL_WARN(area, stream)
#define MIMETYPE_MET
Image const & GetStandardQueryBoxImage()
Definition: stdtext.cxx:82
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:524
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:354
const void * GetData()