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