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