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>
41#include <sal/log.hxx>
42
45#include <rtl/ref.hxx>
46#include <vcl/dibtools.hxx>
48#include <memory>
49#include <string_view>
50
52
53using namespace com::sun::star;
54
55namespace {
56
57class GraphicProvider : public ::cppu::WeakImplHelper< css::graphic::XGraphicProvider2,
58 css::lang::XServiceInfo >
59{
60public:
61
62 GraphicProvider();
63
64protected:
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
83private:
84
85 static css::uno::Reference< css::graphic::XGraphic > implLoadMemory( std::u16string_view 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
91GraphicProvider::GraphicProvider()
92{
93}
94
95OUString SAL_CALL GraphicProvider::getImplementationName()
96{
97 return "com.sun.star.comp.graphic.GraphicProvider";
98}
99
100sal_Bool SAL_CALL GraphicProvider::supportsService( const OUString& ServiceName )
101{
102 return cppu::supportsService( this, ServiceName );
103}
104
105uno::Sequence< OUString > SAL_CALL GraphicProvider::getSupportedServiceNames()
106{
107 return { "com.sun.star.graphic.GraphicProvider" };
108}
109
110uno::Sequence< uno::Type > SAL_CALL GraphicProvider::getTypes()
111{
112 static const uno::Sequence< uno::Type > aTypes {
116 };
117 return aTypes;
118}
119
120uno::Sequence< sal_Int8 > SAL_CALL GraphicProvider::getImplementationId()
121{
122 return css::uno::Sequence<sal_Int8>();
123}
124
125uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadMemory( std::u16string_view rResourceURL )
126{
127 uno::Reference< ::graphic::XGraphic > xRet;
128 sal_Int32 nIndex = 0;
129
130 if( o3tl::getToken(rResourceURL, 0, '/', nIndex ) == u"private:memorygraphic" )
131 {
132 sal_Int64 nGraphicAddress = o3tl::toInt64(o3tl::getToken(rResourceURL, 0, '/', nIndex ));
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
146uno::Reference< ::graphic::XGraphic > GraphicProvider::implLoadRepositoryImage( std::u16string_view rResourceURL )
147{
148 uno::Reference< ::graphic::XGraphic > xRet;
149
150 std::u16string_view sPathName;
151 if( o3tl::starts_with(rResourceURL, u"private:graphicrepository/", &sPathName) )
152 {
153 BitmapEx aBitmap;
154 if ( vcl::ImageRepository::loadImage( OUString(sPathName), aBitmap ) )
155 {
156 Graphic aGraphic(aBitmap);
157 aGraphic.setOriginURL(OUString(rResourceURL));
158 xRet = aGraphic.GetXGraphic();
159 }
160 }
161 return xRet;
162}
163
164uno::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
192uno::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
224uno::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
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
294uno::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
367
368 std::unique_ptr<SvStream> pIStm;
369
370 if( xIStm.is() )
371 {
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 if ( nExtMapMode > 0 )
405 {
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, nullptr, GraphicFilterImportFlags::NONE);
418
419 if( (error == ERRCODE_NONE ) &&
420 ( aVCLGraphic.GetType() != GraphicType::NONE ) )
421 {
422 if (!aPath.isEmpty() && bLoadAsLink)
423 aVCLGraphic.setOriginURL(aPath);
424
425 rtl::Reference<::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 for:" << aPath << " error: " << error);
432 }
433 }
434 }
435
436 return xRet;
437}
438
439uno::Sequence< uno::Reference<graphic::XGraphic> > SAL_CALL GraphicProvider::queryGraphics(const uno::Sequence< uno::Sequence<beans::PropertyValue> >& rMediaPropertiesSeq)
440{
441 // Turn properties into streams.
442 std::vector< std::unique_ptr<SvStream> > aStreams;
443 for (const auto& rMediaProperties : rMediaPropertiesSeq)
444 {
445 std::unique_ptr<SvStream> pStream;
446 uno::Reference<io::XInputStream> xStream;
447
448 auto pProp = std::find_if(rMediaProperties.begin(), rMediaProperties.end(),
449 [](const beans::PropertyValue& rProp) { return rProp.Name == "InputStream"; });
450 if (pProp != rMediaProperties.end())
451 {
452 pProp->Value >>= xStream;
453 if (xStream.is())
454 pStream = utl::UcbStreamHelper::CreateStream(xStream);
455 }
456
457 aStreams.push_back(std::move(pStream));
458 }
459
460 // Import: streams to graphics.
461 std::vector< std::shared_ptr<Graphic> > aGraphics;
463 rFilter.ImportGraphics(aGraphics, std::move(aStreams));
464
465 // Returning: graphics to UNO objects.
466 std::vector< uno::Reference<graphic::XGraphic> > aRet;
467 for (const auto& pGraphic : aGraphics)
468 {
469 uno::Reference<graphic::XGraphic> xGraphic;
470
471 if (pGraphic)
472 {
474 pUnoGraphic->init(*pGraphic);
475 xGraphic = pUnoGraphic;
476 }
477
478 aRet.push_back(xGraphic);
479 }
480
482}
483
484void ImplCalculateCropRect( ::Graphic const & rGraphic, const text::GraphicCrop& rGraphicCropLogic, tools::Rectangle& rGraphicCropPixel )
485{
486 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
487 return;
488
489 Size aSourceSizePixel( rGraphic.GetSizePixel() );
490 if ( !(aSourceSizePixel.Width() && aSourceSizePixel.Height()) )
491 return;
492
493 if ( !(rGraphicCropLogic.Left || rGraphicCropLogic.Top || rGraphicCropLogic.Right || rGraphicCropLogic.Bottom) )
494 return;
495
496 Size aSize100thMM( 0, 0 );
497 if( rGraphic.GetPrefMapMode().GetMapUnit() != MapUnit::MapPixel )
498 {
499 aSize100thMM = OutputDevice::LogicToLogic(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
500 }
501 else
502 {
503 aSize100thMM = Application::GetDefaultDevice()->PixelToLogic(rGraphic.GetPrefSize(), MapMode(MapUnit::Map100thMM));
504 }
505 if ( aSize100thMM.Width() && aSize100thMM.Height() )
506 {
507 double fSourceSizePixelWidth = static_cast<double>(aSourceSizePixel.Width());
508 double fSourceSizePixelHeight= static_cast<double>(aSourceSizePixel.Height());
509 rGraphicCropPixel.SetLeft( static_cast< sal_Int32 >((fSourceSizePixelWidth * rGraphicCropLogic.Left ) / aSize100thMM.Width()) );
510 rGraphicCropPixel.SetTop( static_cast< sal_Int32 >((fSourceSizePixelHeight * rGraphicCropLogic.Top ) / aSize100thMM.Height()) );
511 rGraphicCropPixel.SetRight( static_cast< sal_Int32 >(( fSourceSizePixelWidth * ( aSize100thMM.Width() - rGraphicCropLogic.Right ) ) / aSize100thMM.Width() ) );
512 rGraphicCropPixel.SetBottom( static_cast< sal_Int32 >(( fSourceSizePixelHeight * ( aSize100thMM.Height() - rGraphicCropLogic.Bottom ) ) / aSize100thMM.Height() ) );
513 }
514}
515
516void ImplApplyBitmapScaling( ::Graphic& rGraphic, sal_Int32 nPixelWidth, sal_Int32 nPixelHeight )
517{
518 if ( nPixelWidth && nPixelHeight )
519 {
520 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
521 MapMode aPrefMapMode( aBmpEx.GetPrefMapMode() );
522 Size aPrefSize( aBmpEx.GetPrefSize() );
523 aBmpEx.Scale( Size( nPixelWidth, nPixelHeight ) );
524 aBmpEx.SetPrefMapMode( aPrefMapMode );
525 aBmpEx.SetPrefSize( aPrefSize );
526 rGraphic = aBmpEx;
527 }
528}
529
530void ImplApplyBitmapResolution( ::Graphic& rGraphic, sal_Int32 nImageResolution, const Size& rVisiblePixelSize, const awt::Size& rLogicalSize )
531{
532 if ( !(nImageResolution && rLogicalSize.Width && rLogicalSize.Height) )
533 return;
534
535 const double fImageResolution = static_cast<double>( nImageResolution );
536 const double fSourceDPIX = ( static_cast<double>(rVisiblePixelSize.Width()) * 2540.0 ) / static_cast<double>(rLogicalSize.Width);
537 const double fSourceDPIY = ( static_cast<double>(rVisiblePixelSize.Height()) * 2540.0 ) / static_cast<double>(rLogicalSize.Height);
538 const sal_Int32 nSourcePixelWidth( rGraphic.GetSizePixel().Width() );
539 const sal_Int32 nSourcePixelHeight( rGraphic.GetSizePixel().Height() );
540 const double fSourcePixelWidth = static_cast<double>( nSourcePixelWidth );
541 const double fSourcePixelHeight= static_cast<double>( nSourcePixelHeight );
542
543 sal_Int32 nDestPixelWidth = nSourcePixelWidth;
544 sal_Int32 nDestPixelHeight = nSourcePixelHeight;
545
546 // check, if the bitmap DPI exceeds the maximum DPI
547 if( fSourceDPIX > fImageResolution )
548 {
549 nDestPixelWidth = static_cast<sal_Int32>(( fSourcePixelWidth * fImageResolution ) / fSourceDPIX);
550 if ( !nDestPixelWidth || ( nDestPixelWidth > nSourcePixelWidth ) )
551 nDestPixelWidth = nSourcePixelWidth;
552 }
553 if ( fSourceDPIY > fImageResolution )
554 {
555 nDestPixelHeight= static_cast<sal_Int32>(( fSourcePixelHeight* fImageResolution ) / fSourceDPIY);
556 if ( !nDestPixelHeight || ( nDestPixelHeight > nSourcePixelHeight ) )
557 nDestPixelHeight = nSourcePixelHeight;
558 }
559 if ( ( nDestPixelWidth != nSourcePixelWidth ) || ( nDestPixelHeight != nSourcePixelHeight ) )
560 ImplApplyBitmapScaling( rGraphic, nDestPixelWidth, nDestPixelHeight );
561}
562
563void ImplApplyFilterData( ::Graphic& rGraphic, const uno::Sequence< beans::PropertyValue >& rFilterData )
564{
565 /* this method applies following attributes to the graphic, in the first step the
566 cropping area (logical size in 100thmm) is applied, in the second step the resolution
567 is applied, in the third step the graphic is scaled to the corresponding pixelsize.
568 if a parameter value is zero or not available the corresponding step will be skipped */
569
570 sal_Int32 nPixelWidth = 0;
571 sal_Int32 nPixelHeight= 0;
572 sal_Int32 nImageResolution = 0;
573 awt::Size aLogicalSize( 0, 0 );
574 text::GraphicCrop aCropLogic( 0, 0, 0, 0 );
575 bool bRemoveCropArea = true;
576
577 for( const auto& rProp : rFilterData )
578 {
579 const OUString aName( rProp.Name );
580 const uno::Any aValue( rProp.Value );
581
582 if (aName == "PixelWidth")
583 aValue >>= nPixelWidth;
584 else if (aName == "PixelHeight")
585 aValue >>= nPixelHeight;
586 else if (aName == "LogicalSize")
587 aValue >>= aLogicalSize;
588 else if (aName == "GraphicCropLogic")
589 aValue >>= aCropLogic;
590 else if (aName == "RemoveCropArea")
591 aValue >>= bRemoveCropArea;
592 else if (aName == "ImageResolution")
593 aValue >>= nImageResolution;
594 }
595 if ( rGraphic.GetType() == GraphicType::Bitmap )
596 {
597 if(rGraphic.getVectorGraphicData())
598 {
599 // embedded Vector Graphic Data, no need to scale. Also no method to apply crop data currently
600 }
601 else
602 {
603 tools::Rectangle aCropPixel( Point( 0, 0 ), rGraphic.GetSizePixel() );
604 ImplCalculateCropRect( rGraphic, aCropLogic, aCropPixel );
605 if ( bRemoveCropArea )
606 {
607 BitmapEx aBmpEx( rGraphic.GetBitmapEx() );
608 aBmpEx.Crop( aCropPixel );
609 rGraphic = aBmpEx;
610 }
611 Size aVisiblePixelSize( bRemoveCropArea ? rGraphic.GetSizePixel() : aCropPixel.GetSize() );
612 ImplApplyBitmapResolution( rGraphic, nImageResolution, aVisiblePixelSize, aLogicalSize );
613 ImplApplyBitmapScaling( rGraphic, nPixelWidth, nPixelHeight );
614 }
615 }
616 else if ( ( rGraphic.GetType() == GraphicType::GdiMetafile ) && nImageResolution )
617 {
619 GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
620 Size aMtfSize( OutputDevice::LogicToLogic(aMtf.GetPrefSize(), aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
621 if ( aMtfSize.Width() && aMtfSize.Height() )
622 {
623 MapMode aNewMapMode( MapUnit::Map100thMM );
624 aNewMapMode.SetScaleX( Fraction( aLogicalSize.Width, aMtfSize.Width() ) );
625 aNewMapMode.SetScaleY( Fraction( aLogicalSize.Height, aMtfSize.Height() ) );
626 aDummyVDev->EnableOutput( false );
627 aDummyVDev->SetMapMode( aNewMapMode );
628
629 for( size_t i = 0, nObjCount = aMtf.GetActionSize(); i < nObjCount; i++ )
630 {
631 MetaAction* pAction = aMtf.GetAction( i );
632 switch( pAction->GetType() )
633 {
634 // only optimizing common bitmap actions:
636 {
637 pAction->Execute( aDummyVDev.get() );
638 break;
639 }
641 {
642 const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
643 aDummyVDev->Push( pA->GetFlags() );
644 break;
645 }
647 {
648 aDummyVDev->Pop();
649 break;
650 }
653 {
654 BitmapEx aBmpEx;
655 Point aPos;
656 Size aSize;
657 if ( pAction->GetType() == MetaActionType::BMPSCALE )
658 {
659 MetaBmpScaleAction* pScaleAction = dynamic_cast< MetaBmpScaleAction* >( pAction );
660 assert(pScaleAction);
661 aBmpEx = pScaleAction->GetBitmap();
662 aPos = pScaleAction->GetPoint();
663 aSize = pScaleAction->GetSize();
664 }
665 else
666 {
667 MetaBmpExScaleAction* pScaleAction = dynamic_cast< MetaBmpExScaleAction* >( pAction );
668 assert(pScaleAction);
669 aBmpEx = pScaleAction->GetBitmapEx();
670 aPos = pScaleAction->GetPoint();
671 aSize = pScaleAction->GetSize();
672 }
673 ::Graphic aGraphic( aBmpEx );
674 const Size aSize100thmm( aDummyVDev->LogicToPixel( aSize ) );
675 Size aSize100thmm2( aDummyVDev->PixelToLogic(aSize100thmm, MapMode(MapUnit::Map100thMM)) );
676
677 ImplApplyBitmapResolution( aGraphic, nImageResolution,
678 aGraphic.GetSizePixel(), awt::Size( aSize100thmm2.Width(), aSize100thmm2.Height() ) );
679
680 rtl::Reference<MetaAction> pNewAction = new MetaBmpExScaleAction( aPos, aSize, aGraphic.GetBitmapEx() );
681 aMtf.ReplaceAction( pNewAction, i );
682 break;
683 }
684 default:
691 break;
692 }
693 }
694 rGraphic = aMtf;
695 }
696 }
697}
698
699
700void SAL_CALL GraphicProvider::storeGraphic( const uno::Reference< ::graphic::XGraphic >& rxGraphic, const uno::Sequence< beans::PropertyValue >& rMediaProperties )
701{
702 std::unique_ptr<SvStream> pOStm;
703 OUString aPath;
704
705 for( const auto& rMediaProperty : rMediaProperties )
706 {
707 const OUString aName( rMediaProperty.Name );
708 const uno::Any aValue( rMediaProperty.Value );
709
710 if (aName == "URL")
711 {
712 OUString aURL;
713
714 aValue >>= aURL;
715 pOStm = ::utl::UcbStreamHelper::CreateStream( aURL, StreamMode::WRITE | StreamMode::TRUNC );
716 aPath = aURL;
717 }
718 else if (aName == "OutputStream")
719 {
720 uno::Reference< io::XStream > xOStm;
721
722 aValue >>= xOStm;
723
724 if( xOStm.is() )
726 }
727
728 if( pOStm )
729 break;
730 }
731
732 if( !pOStm )
733 return;
734
735 uno::Sequence< beans::PropertyValue > aFilterDataSeq;
736 OUString sFilterShortName;
737
738 for( const auto& rMediaProperty : rMediaProperties )
739 {
740 const OUString aName( rMediaProperty.Name );
741 const uno::Any aValue( rMediaProperty.Value );
742
743 if (aName == "FilterData")
744 {
745 aValue >>= aFilterDataSeq;
746 }
747 else if (aName == "MimeType")
748 {
749 OUString aMimeType;
750
751 aValue >>= aMimeType;
752
753 if (aMimeType == MIMETYPE_BMP)
754 sFilterShortName = "bmp";
755 else if (aMimeType == MIMETYPE_EPS)
756 sFilterShortName = "eps";
757 else if (aMimeType == MIMETYPE_GIF)
758 sFilterShortName = "gif";
759 else if (aMimeType == MIMETYPE_JPG)
760 sFilterShortName = "jpg";
761 else if (aMimeType == MIMETYPE_MET)
762 sFilterShortName = "met";
763 else if (aMimeType == MIMETYPE_PNG)
764 sFilterShortName = "png";
765 else if (aMimeType == MIMETYPE_PCT)
766 sFilterShortName = "pct";
767 else if (aMimeType == MIMETYPE_PBM)
768 sFilterShortName = "pbm";
769 else if (aMimeType == MIMETYPE_PGM)
770 sFilterShortName = "pgm";
771 else if (aMimeType == MIMETYPE_PPM)
772 sFilterShortName = "ppm";
773 else if (aMimeType == MIMETYPE_RAS)
774 sFilterShortName = "ras";
775 else if (aMimeType == MIMETYPE_SVM)
776 sFilterShortName = "svm";
777 else if (aMimeType == MIMETYPE_TIF)
778 sFilterShortName = "tif";
779 else if (aMimeType == MIMETYPE_EMF)
780 sFilterShortName = "emf";
781 else if (aMimeType == MIMETYPE_WMF)
782 sFilterShortName = "wmf";
783 else if (aMimeType == MIMETYPE_XPM)
784 sFilterShortName = "xpm";
785 else if (aMimeType == MIMETYPE_SVG)
786 sFilterShortName = "svg";
787 else if (aMimeType == MIMETYPE_VCLGRAPHIC)
788 sFilterShortName = MIMETYPE_VCLGRAPHIC;
789 }
790 }
791
792 if( sFilterShortName.isEmpty() )
793 return;
794
796
797 {
798 const uno::Reference< XInterface > xIFace( rxGraphic, uno::UNO_QUERY );
799 const ::unographic::Graphic* pUnoGraphic = dynamic_cast<::unographic::Graphic*>(xIFace.get());
800 const ::Graphic* pGraphic = pUnoGraphic ? &pUnoGraphic->GetGraphic() : nullptr;
801
802 if( pGraphic && ( pGraphic->GetType() != GraphicType::NONE ) )
803 {
804 ::Graphic aGraphic( *pGraphic );
805 ImplApplyFilterData( aGraphic, aFilterDataSeq );
806
807 /* sj: using a temporary memory stream, because some graphic filters are seeking behind
808 stream end (which leads to an invalid argument exception then). */
809 SvMemoryStream aMemStrm;
810 aMemStrm.SetVersion( SOFFICE_FILEFORMAT_CURRENT );
811 if( sFilterShortName == MIMETYPE_VCLGRAPHIC )
812 {
813 TypeSerializer aSerializer(aMemStrm);
814 aSerializer.writeGraphic(aGraphic);
815 }
816 else
817 {
818 rFilter.ExportGraphic( aGraphic, aPath, aMemStrm,
819 rFilter.GetExportFormatNumberForShortName( sFilterShortName ),
820 ( aFilterDataSeq.hasElements() ? &aFilterDataSeq : nullptr ) );
821 }
822 pOStm->WriteBytes( aMemStrm.GetData(), aMemStrm.TellEnd() );
823 }
824 }
825}
826
827}
828
829extern "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: */
constexpr OUStringLiteral MIMETYPE_MET
constexpr OUStringLiteral MIMETYPE_TIF
constexpr OUStringLiteral MIMETYPE_EPS
constexpr OUStringLiteral MIMETYPE_JPG
constexpr OUStringLiteral MIMETYPE_XPM
constexpr OUStringLiteral MIMETYPE_SVG
constexpr OUStringLiteral MIMETYPE_WMF
constexpr OUStringLiteral MIMETYPE_RAS
constexpr OUStringLiteral MIMETYPE_PNG
constexpr OUStringLiteral MIMETYPE_VCLGRAPHIC
constexpr OUStringLiteral MIMETYPE_PBM
constexpr OUStringLiteral MIMETYPE_PGM
constexpr OUStringLiteral MIMETYPE_EMF
constexpr OUStringLiteral MIMETYPE_PPM
constexpr OUStringLiteral MIMETYPE_BMP
constexpr OUStringLiteral MIMETYPE_GIF
constexpr OUStringLiteral MIMETYPE_PCT
constexpr OUStringLiteral MIMETYPE_SVM
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_graphic_GraphicProvider_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Reference< XInputStream > xStream
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1043
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:305
void SetPrefMapMode(const MapMode &rPrefMapMode)
Definition: bitmapex.hxx:80
void SetPrefSize(const Size &rPrefSize)
Definition: bitmapex.hxx:77
bool IsEmpty() const
Definition: BitmapEx.cxx:186
const MapMode & GetPrefMapMode() const
Definition: bitmapex.hxx:79
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:363
const Size & GetPrefSize() const
Definition: bitmapex.hxx:76
Class to import and export graphic formats.
sal_uInt16 GetExportFormatNumberForShortName(std::u16string_view rShortName)
Graphic ImportUnloadedGraphic(SvStream &rIStream, sal_uInt64 sizeLimit=0, const Size *pSizeHint=nullptr)
static GraphicFilter & GetGraphicFilter()
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
void ImportGraphics(std::vector< std::shared_ptr< Graphic > > &rGraphics, std::vector< std::unique_ptr< SvStream > > vStreams)
Imports multiple graphics.
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
Definition: graph.cxx:350
Size GetPrefSize() const
Definition: graph.cxx:364
const GDIMetaFile & GetGDIMetaFile() const
Definition: graph.cxx:340
GraphicType GetType() const
Definition: graph.cxx:294
bool IsNone() const
Definition: graph.cxx:283
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
MapMode GetPrefMapMode() const
Definition: graph.cxx:375
Size GetSizePixel(const OutputDevice *pRefDevice=nullptr) const
Definition: graph.cxx:412
const std::shared_ptr< VectorGraphicData > & getVectorGraphicData() const
Definition: graph.cxx:525
void setOriginURL(OUString const &rOriginURL)
Definition: graph.cxx:544
MapUnit GetMapUnit() const
Definition: mapmod.cxx:181
MetaActionType GetType() const
Definition: metaact.hxx:96
virtual void Execute(OutputDevice *pOut)
Definition: metaact.cxx:99
const Size & GetSize() const
Definition: metaact.hxx:833
const Point & GetPoint() const
Definition: metaact.hxx:832
const BitmapEx & GetBitmapEx() const
Definition: metaact.hxx:831
const Point & GetPoint() const
Definition: metaact.hxx:726
const Size & GetSize() const
Definition: metaact.hxx:727
const Bitmap & GetBitmap() const
Definition: metaact.hxx:725
vcl::PushFlags GetFlags() const
Definition: metaact.hxx:1497
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1110
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
Definition: map.cxx:1580
constexpr tools::Long Height() const
constexpr tools::Long Width() const
const void * GetData()
virtual sal_uInt64 TellEnd() override
void SetVersion(sal_Int32 n)
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
css::uno::Type const & get()
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr void SetRight(tools::Long v)
constexpr void SetBottom(tools::Long v)
const ::Graphic & GetGraphic() const
Definition: UnoGraphic.hxx:45
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
static bool loadImage(const OUString &_rName, BitmapEx &_out_rImage)
loads an image from the application's image repository
bool ReadDIB(Bitmap &rTarget, SvStream &rIStm, bool bFileHeader, bool bMSOFormat)
Definition: dibtools.cxx:1614
URL aURL
#define ERRCODE_NONE
#define GRFILTER_FORMAT_DONTKNOW
sal_Int32 nIndex
OUString aName
#define SAL_WARN(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix=10)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
BitmapEx GetBitmapEx(BitmapEx const &rBitmapEx, DrawModeFlags nDrawMode)
Definition: drawmode.cxx:242
const sal_Unicode *const aMimeType[]
Image const & GetStandardInfoBoxImage()
Definition: stdtext.cxx:49
Image const & GetStandardWarningBoxImage()
Definition: stdtext.cxx:60
Image const & GetStandardErrorBoxImage()
Definition: stdtext.cxx:71
Image const & GetStandardQueryBoxImage()
Definition: stdtext.cxx:82
sal_uInt16 yExt
Definition: wmfexternal.hxx:34
sal_uInt16 mapMode
One of the following values:
Definition: wmfexternal.hxx:50
sal_uInt16 xExt
Definition: wmfexternal.hxx:33
unsigned char sal_Bool
const SvXMLTokenMapEntry aTypes[]