1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/fract.hxx>
21 #include <vcl/outdev.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/graph.hxx>
24 #include <vcl/metaact.hxx>
25 #include <impgraph.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/graphic/GraphicProvider.hpp>
29 #include <com/sun/star/graphic/XGraphicProvider.hpp>
30 #include <com/sun/star/lang/XUnoTunnel.hpp>
31 #include <com/sun/star/lang/XTypeProvider.hpp>
32 #include <com/sun/star/graphic/XGraphic.hpp>
33 #include <cppuhelper/typeprovider.hxx>
35 using namespace ::com::sun::star
;
40 void ImplDrawDefault( OutputDevice
* pOutDev
, const OUString
* pText
,
41 vcl::Font
* pFont
, const Bitmap
* pBitmap
, const BitmapEx
* pBitmapEx
,
42 const Point
& rDestPt
, const Size
& rDestSize
)
44 sal_uInt16 nPixel
= (sal_uInt16
) pOutDev
->PixelToLogic( Size( 1, 1 ) ).Width();
45 sal_uInt16 nPixelWidth
= nPixel
;
46 Point
aPoint( rDestPt
.X() + nPixelWidth
, rDestPt
.Y() + nPixelWidth
);
47 Size
aSize( rDestSize
.Width() - ( nPixelWidth
<< 1 ), rDestSize
.Height() - ( nPixelWidth
<< 1 ) );
48 bool bFilled
= ( pBitmap
!= nullptr || pBitmapEx
!= nullptr || pFont
!= nullptr );
49 tools::Rectangle
aBorderRect( aPoint
, aSize
);
53 pOutDev
->SetFillColor();
55 // On the printer a black rectangle and on the screen one with 3D effect
56 if ( pOutDev
->GetOutDevType() == OUTDEV_PRINTER
)
57 pOutDev
->SetLineColor( COL_BLACK
);
60 aBorderRect
.Left() += nPixel
;
61 aBorderRect
.Top() += nPixel
;
63 pOutDev
->SetLineColor( COL_LIGHTGRAY
);
64 pOutDev
->DrawRect( aBorderRect
);
66 aBorderRect
.Left() -= nPixel
;
67 aBorderRect
.Top() -= nPixel
;
68 aBorderRect
.Right() -= nPixel
;
69 aBorderRect
.Bottom() -= nPixel
;
70 pOutDev
->SetLineColor( COL_GRAY
);
73 pOutDev
->DrawRect( aBorderRect
);
75 aPoint
.X() += nPixelWidth
+ 2*nPixel
;
76 aPoint
.Y() += nPixelWidth
+ 2*nPixel
;
77 aSize
.Width() -= 2*nPixelWidth
+ 4*nPixel
;
78 aSize
.Height() -= 2*nPixelWidth
+ 4*nPixel
;
80 if( aSize
.Width() > 0 && aSize
.Height() > 0
81 && ( ( pBitmap
&& !!*pBitmap
) || ( pBitmapEx
&& !!*pBitmapEx
) ) )
83 Size
aBitmapSize( pOutDev
->PixelToLogic( pBitmap
? pBitmap
->GetSizePixel() : pBitmapEx
->GetSizePixel() ) );
85 if( aSize
.Height() > aBitmapSize
.Height() && aSize
.Width() > aBitmapSize
.Width() )
88 pOutDev
->DrawBitmap( aPoint
, *pBitmap
);
90 pOutDev
->DrawBitmapEx( aPoint
, *pBitmapEx
);
91 aPoint
.X() += aBitmapSize
.Width() + 2*nPixel
;
92 aSize
.Width() -= aBitmapSize
.Width() + 2*nPixel
;
96 if ( aSize
.Width() > 0 && aSize
.Height() > 0 && pFont
&& pText
&& pText
->getLength()
97 && !(!pOutDev
->IsOutputEnabled() /*&& pOutDev->GetConnectMetaFile() */) )
99 MapMode
aMapMode( MapUnit::MapPoint
);
100 Size aSz
= pOutDev
->LogicToLogic( Size( 0, 12 ), &aMapMode
, nullptr );
101 long nThreshold
= aSz
.Height() / 2;
102 long nStep
= nThreshold
/ 3;
105 nStep
= aSz
.Height() - nThreshold
;
107 for(;; aSz
.Height() -= nStep
)
109 pFont
->SetFontSize( aSz
);
110 pOutDev
->SetFont( *pFont
);
112 long nTextHeight
= pOutDev
->GetTextHeight();
113 long nTextWidth
= pOutDev
->GetTextWidth( *pText
);
116 // The approximation does not respect imprecisions caused
118 long nLines
= aSize
.Height() / nTextHeight
;
119 long nWidth
= aSize
.Width() * nLines
; // Approximation!!!
121 if ( nTextWidth
<= nWidth
|| aSz
.Height() <= nThreshold
)
123 sal_Int32 nStart
= 0;
126 while( nStart
< pText
->getLength() && (*pText
)[nStart
] == ' ' )
128 while( nStart
+nLen
< pText
->getLength() && (*pText
)[nStart
+nLen
] != ' ' )
130 while( nStart
< pText
->getLength() && nLines
-- )
132 sal_Int32 nNext
= nLen
;
135 while ( nStart
+nNext
< pText
->getLength() && (*pText
)[nStart
+nNext
] == ' ' )
137 while ( nStart
+nNext
< pText
->getLength() && (*pText
)[nStart
+nNext
] != ' ' )
139 nTextWidth
= pOutDev
->GetTextWidth( *pText
, nStart
, nNext
);
140 if ( nTextWidth
> aSize
.Width() )
144 while ( nStart
+nNext
< pText
->getLength() );
147 nTextWidth
= pOutDev
->GetTextWidth( *pText
, nStart
, n
);
148 while( nTextWidth
> aSize
.Width() )
149 nTextWidth
= pOutDev
->GetTextWidth( *pText
, nStart
, --n
);
150 pOutDev
->DrawText( aPoint
, *pText
, nStart
, n
);
152 aPoint
.Y() += nTextHeight
;
153 nStart
= sal::static_int_cast
<sal_uInt16
>(nStart
+ nLen
);
155 while( nStart
< pText
->getLength() && (*pText
)[nStart
] == ' ' )
169 // If the default graphic does not have content, we draw a red rectangle
172 aBorderRect
.Left()++;
174 aBorderRect
.Right()--;
175 aBorderRect
.Bottom()--;
177 pOutDev
->SetLineColor( COL_LIGHTRED
);
178 pOutDev
->DrawLine( aBorderRect
.TopLeft(), aBorderRect
.BottomRight() );
179 pOutDev
->DrawLine( aBorderRect
.TopRight(), aBorderRect
.BottomLeft() );
185 } // end anonymous namespace
188 : mxImpGraphic(new ImpGraphic
)
192 Graphic::Graphic(const Graphic
& rGraphic
)
194 if( rGraphic
.IsAnimated() )
195 mxImpGraphic
.reset(new ImpGraphic(*rGraphic
.mxImpGraphic
));
197 mxImpGraphic
= rGraphic
.mxImpGraphic
;
200 Graphic::Graphic(Graphic
&& rGraphic
)
201 : mxImpGraphic(std::move(rGraphic
.mxImpGraphic
))
205 Graphic::Graphic(const Bitmap
& rBmp
)
206 : mxImpGraphic(new ImpGraphic(rBmp
))
210 Graphic::Graphic(const BitmapEx
& rBmpEx
)
211 : mxImpGraphic(new ImpGraphic(rBmpEx
))
215 Graphic::Graphic(const SvgDataPtr
& rSvgDataPtr
)
216 : mxImpGraphic(new ImpGraphic(rSvgDataPtr
))
220 Graphic::Graphic(const Animation
& rAnimation
)
221 : mxImpGraphic(new ImpGraphic(rAnimation
))
225 Graphic::Graphic(const GDIMetaFile
& rMtf
)
226 : mxImpGraphic(new ImpGraphic(rMtf
))
230 Graphic::Graphic( const css::uno::Reference
< css::graphic::XGraphic
>& rxGraphic
)
232 uno::Reference
< lang::XUnoTunnel
> xTunnel( rxGraphic
, uno::UNO_QUERY
);
233 const ::Graphic
* pGraphic
= ( xTunnel
.is() ?
234 reinterpret_cast< ::Graphic
* >( xTunnel
->getSomething( getUnoTunnelId() ) ) :
239 if (pGraphic
->IsAnimated())
240 mxImpGraphic
.reset(new ImpGraphic(*pGraphic
->mxImpGraphic
));
242 mxImpGraphic
= pGraphic
->mxImpGraphic
;
245 mxImpGraphic
.reset(new ImpGraphic
);
248 void Graphic::ImplTestRefCount()
250 if (!mxImpGraphic
.unique())
252 mxImpGraphic
.reset(new ImpGraphic(*mxImpGraphic
));
256 Graphic
& Graphic::operator=( const Graphic
& rGraphic
)
258 if( &rGraphic
!= this )
260 if( rGraphic
.IsAnimated() )
262 mxImpGraphic
.reset(new ImpGraphic(*rGraphic
.mxImpGraphic
));
266 mxImpGraphic
= rGraphic
.mxImpGraphic
;
273 Graphic
& Graphic::operator=(Graphic
&& rGraphic
)
275 mxImpGraphic
= std::move(rGraphic
.mxImpGraphic
);
279 bool Graphic::operator==( const Graphic
& rGraphic
) const
281 return (*mxImpGraphic
== *rGraphic
.mxImpGraphic
);
284 bool Graphic::operator!=( const Graphic
& rGraphic
) const
286 return (*mxImpGraphic
!= *rGraphic
.mxImpGraphic
);
289 bool Graphic::operator!() const
291 return (GraphicType::NONE
== mxImpGraphic
->ImplGetType());
294 void Graphic::Clear()
297 mxImpGraphic
->ImplClear();
300 GraphicType
Graphic::GetType() const
302 return mxImpGraphic
->ImplGetType();
305 void Graphic::SetDefaultType()
308 mxImpGraphic
->ImplSetDefaultType();
311 bool Graphic::IsSupportedGraphic() const
313 return mxImpGraphic
->ImplIsSupportedGraphic();
316 bool Graphic::IsTransparent() const
318 return mxImpGraphic
->ImplIsTransparent();
321 bool Graphic::IsAlpha() const
323 return mxImpGraphic
->ImplIsAlpha();
326 bool Graphic::IsAnimated() const
328 return mxImpGraphic
->ImplIsAnimated();
331 bool Graphic::IsEPS() const
333 return mxImpGraphic
->ImplIsEPS();
336 Bitmap
Graphic::GetBitmap(const GraphicConversionParameters
& rParameters
) const
338 return mxImpGraphic
->ImplGetBitmap(rParameters
);
341 BitmapEx
Graphic::GetBitmapEx(const GraphicConversionParameters
& rParameters
) const
343 return mxImpGraphic
->ImplGetBitmapEx(rParameters
);
346 Animation
Graphic::GetAnimation() const
348 return mxImpGraphic
->ImplGetAnimation();
351 const GDIMetaFile
& Graphic::GetGDIMetaFile() const
353 return mxImpGraphic
->ImplGetGDIMetaFile();
356 const BitmapEx
& Graphic::GetBitmapExRef() const
358 return mxImpGraphic
->ImplGetBitmapExRef();
361 uno::Reference
< graphic::XGraphic
> Graphic::GetXGraphic() const
363 uno::Reference
< graphic::XGraphic
> xRet
;
365 if( GetType() != GraphicType::NONE
)
367 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
368 uno::Reference
< graphic::XGraphicProvider
> xProv( graphic::GraphicProvider::create( xContext
) );
370 uno::Sequence
< beans::PropertyValue
> aLoadProps( 1 );
371 OUString aURL
= "private:memorygraphic/" + OUString::number( reinterpret_cast< sal_Int64
>( this ) );
373 aLoadProps
[ 0 ].Name
= "URL";
374 aLoadProps
[ 0 ].Value
<<= aURL
;
376 xRet
= xProv
->queryGraphic( aLoadProps
);
382 Size
Graphic::GetPrefSize() const
384 return mxImpGraphic
->ImplGetPrefSize();
387 void Graphic::SetPrefSize( const Size
& rPrefSize
)
390 mxImpGraphic
->ImplSetPrefSize( rPrefSize
);
393 MapMode
Graphic::GetPrefMapMode() const
395 return mxImpGraphic
->ImplGetPrefMapMode();
398 void Graphic::SetPrefMapMode( const MapMode
& rPrefMapMode
)
401 mxImpGraphic
->ImplSetPrefMapMode( rPrefMapMode
);
404 basegfx::B2DSize
Graphic::GetPPI() const
409 const MapMode
aGrfMap(GetPrefMapMode());
410 const Size
aGrfPixelSize(GetSizePixel());
411 const Size
aGrfPrefMapModeSize(GetPrefSize());
412 if (aGrfMap
.GetMapUnit() == MapUnit::MapInch
)
414 nGrfDPIx
= aGrfPixelSize
.Width() / ( (double)aGrfMap
.GetScaleX() * aGrfPrefMapModeSize
.Width() );
415 nGrfDPIy
= aGrfPixelSize
.Height() / ( (double)aGrfMap
.GetScaleY() * aGrfPrefMapModeSize
.Height() );
419 const Size aGrf1000thInchSize
= OutputDevice::LogicToLogic(aGrfPrefMapModeSize
, aGrfMap
, MapUnit::Map1000thInch
);
420 nGrfDPIx
= 1000.0 * aGrfPixelSize
.Width() / aGrf1000thInchSize
.Width();
421 nGrfDPIy
= 1000.0 * aGrfPixelSize
.Height() / aGrf1000thInchSize
.Height();
424 return basegfx::B2DSize(nGrfDPIx
, nGrfDPIy
);
427 Size
Graphic::GetSizePixel( const OutputDevice
* pRefDevice
) const
431 if( GraphicType::Bitmap
== mxImpGraphic
->ImplGetType() )
432 aRet
= mxImpGraphic
->ImplGetBitmapEx(GraphicConversionParameters()).GetSizePixel();
434 aRet
= ( pRefDevice
? pRefDevice
: Application::GetDefaultDevice() )->LogicToPixel( GetPrefSize(), GetPrefMapMode() );
439 sal_uLong
Graphic::GetSizeBytes() const
441 return mxImpGraphic
->ImplGetSizeBytes();
444 void Graphic::Draw( OutputDevice
* pOutDev
, const Point
& rDestPt
) const
446 mxImpGraphic
->ImplDraw( pOutDev
, rDestPt
);
449 void Graphic::Draw( OutputDevice
* pOutDev
,
450 const Point
& rDestPt
, const Size
& rDestSz
) const
452 if( GraphicType::Default
== mxImpGraphic
->ImplGetType() )
453 ImplDrawDefault( pOutDev
, nullptr, nullptr, nullptr, nullptr, rDestPt
, rDestSz
);
455 mxImpGraphic
->ImplDraw( pOutDev
, rDestPt
, rDestSz
);
458 void Graphic::DrawEx( OutputDevice
* pOutDev
, const OUString
& rText
,
459 vcl::Font
& rFont
, const BitmapEx
& rBitmap
,
460 const Point
& rDestPt
, const Size
& rDestSz
)
462 ImplDrawDefault( pOutDev
, &rText
, &rFont
, nullptr, &rBitmap
, rDestPt
, rDestSz
);
465 void Graphic::StartAnimation( OutputDevice
* pOutDev
, const Point
& rDestPt
,
466 const Size
& rDestSz
, long nExtraData
,
467 OutputDevice
* pFirstFrameOutDev
)
470 mxImpGraphic
->ImplStartAnimation( pOutDev
, rDestPt
, rDestSz
, nExtraData
, pFirstFrameOutDev
);
473 void Graphic::StopAnimation( OutputDevice
* pOutDev
, long nExtraData
)
476 mxImpGraphic
->ImplStopAnimation( pOutDev
, nExtraData
);
479 void Graphic::SetAnimationNotifyHdl( const Link
<Animation
*,void>& rLink
)
481 mxImpGraphic
->ImplSetAnimationNotifyHdl( rLink
);
484 Link
<Animation
*,void> Graphic::GetAnimationNotifyHdl() const
486 return mxImpGraphic
->ImplGetAnimationNotifyHdl();
489 sal_uLong
Graphic::GetAnimationLoopCount() const
491 return mxImpGraphic
->ImplGetAnimationLoopCount();
494 std::shared_ptr
<GraphicReader
>& Graphic::GetContext()
496 return mxImpGraphic
->ImplGetContext();
499 void Graphic::SetContext( const std::shared_ptr
<GraphicReader
> &pReader
)
501 mxImpGraphic
->ImplSetContext( pReader
);
504 void Graphic::SetDummyContext( bool value
)
506 mxImpGraphic
->ImplSetDummyContext( value
);
509 bool Graphic::IsDummyContext()
511 return mxImpGraphic
->ImplIsDummyContext();
514 bool Graphic::SwapOut()
517 return mxImpGraphic
->ImplSwapOut();
520 void Graphic::SwapOutAsLink()
523 mxImpGraphic
->ImplSwapOutAsLink();
526 bool Graphic::SwapOut( SvStream
* pOStream
)
529 return mxImpGraphic
->ImplSwapOut( pOStream
);
532 bool Graphic::SwapIn()
535 return mxImpGraphic
->ImplSwapIn();
538 bool Graphic::SwapIn( SvStream
* pStrm
)
541 return mxImpGraphic
->ImplSwapIn( pStrm
);
544 bool Graphic::IsSwapOut() const
546 return mxImpGraphic
->ImplIsSwapOut();
549 void Graphic::SetLink( const GfxLink
& rGfxLink
)
552 mxImpGraphic
->ImplSetLink( rGfxLink
);
555 GfxLink
Graphic::GetLink() const
557 return mxImpGraphic
->ImplGetLink();
560 bool Graphic::IsLink() const
562 return mxImpGraphic
->ImplIsLink();
565 BitmapChecksum
Graphic::GetChecksum() const
567 return mxImpGraphic
->ImplGetChecksum();
570 bool Graphic::ExportNative( SvStream
& rOStream
) const
572 return mxImpGraphic
->ImplExportNative( rOStream
);
575 void ReadGraphic(SvStream
& rIStream
, Graphic
& rGraphic
)
577 rGraphic
.ImplTestRefCount();
578 ReadImpGraphic(rIStream
, *rGraphic
.mxImpGraphic
);
581 void WriteGraphic( SvStream
& rOStream
, const Graphic
& rGraphic
)
583 WriteImpGraphic(rOStream
, *rGraphic
.mxImpGraphic
);
586 const SvgDataPtr
& Graphic::getSvgData() const
588 return mxImpGraphic
->getSvgData();
591 void Graphic::setPdfData(const uno::Sequence
<sal_Int8
>& rPdfData
)
594 mxImpGraphic
->maPdfData
= rPdfData
;
597 const uno::Sequence
<sal_Int8
>& Graphic::getPdfData() const
599 return mxImpGraphic
->maPdfData
;
604 struct Id
: public rtl::Static
<cppu::OImplementationId
, Id
> {};
608 css::uno::Sequence
<sal_Int8
> Graphic::getUnoTunnelId() {
609 return Id::get().getImplementationId();
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */