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 <sal/config.h>
21 #include <sal/log.hxx>
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <basegfx/numeric/ftools.hxx>
25 #include <basegfx/point/b2dpoint.hxx>
26 #include <basegfx/range/b2drectangle.hxx>
27 #include <basegfx/utils/canvastools.hxx>
28 #include <rtl/math.hxx>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <vcl/alpha.hxx>
31 #include <vcl/bitmapex.hxx>
32 #include <vcl/canvastools.hxx>
33 #include <vcl/outdev.hxx>
35 #include <canvas/canvastools.hxx>
37 #include "spritehelper.hxx"
39 using namespace ::com::sun::star
;
44 SpriteHelper::SpriteHelper() :
45 mbShowSpriteBounds(false)
49 void SpriteHelper::init( const geometry::RealSize2D
& rSpriteSize
,
50 const ::canvas::SpriteSurface::Reference
& rOwningSpriteCanvas
,
51 const BackBufferSharedPtr
& rBackBuffer
,
52 const BackBufferSharedPtr
& rBackBufferMask
,
53 bool bShowSpriteBounds
)
55 ENSURE_OR_THROW( rOwningSpriteCanvas
&& rBackBuffer
&& rBackBufferMask
,
56 "SpriteHelper::init(): Invalid sprite canvas or back buffer" );
58 mpBackBuffer
= rBackBuffer
;
59 mpBackBufferMask
= rBackBufferMask
;
60 mbShowSpriteBounds
= bShowSpriteBounds
;
62 init( rSpriteSize
, rOwningSpriteCanvas
);
65 void SpriteHelper::disposing()
68 mpBackBufferMask
.reset();
71 CanvasCustomSpriteHelper::disposing();
74 void SpriteHelper::redraw( OutputDevice
& rTargetSurface
,
75 const ::basegfx::B2DPoint
& rPos
,
76 bool& io_bSurfacesDirty
,
77 bool /*bBufferedUpdate*/ ) const
82 return; // we're disposed
85 // log output pos in device pixel
86 SAL_INFO("canvas.vcl", "SpriteHelper::redraw(): output pos is (" <<
87 rPos
.getX() << "," << rPos
.getY() << ")");
89 const double fAlpha( getAlpha() );
91 if( !isActive() || ::basegfx::fTools::equalZero( fAlpha
) )
94 const ::basegfx::B2DVector
& rOrigOutputSize( getSizePixel() );
96 // might get changed below (e.g. adapted for
97 // transformations). IMPORTANT: both position and size are
98 // rounded to integer values. From now on, only those
99 // rounded values are used, to keep clip and content in
101 ::Size
aOutputSize( vcl::unotools::sizeFromB2DSize( rOrigOutputSize
) );
102 ::Point
aOutPos( vcl::unotools::pointFromB2DPoint( rPos
) );
105 // TODO(F3): Support for alpha-VDev
107 // Do we have to update our bitmaps (necessary if virdev
108 // was painted to, or transformation changed)?
109 const bool bNeedBitmapUpdate( io_bSurfacesDirty
||
110 hasTransformChanged() ||
111 maContent
->IsEmpty() );
113 // updating content of sprite cache - surface is no
114 // longer dirty in relation to our cache
115 io_bSurfacesDirty
= false;
118 if( bNeedBitmapUpdate
)
120 const Point aEmptyPoint
;
121 BitmapEx
aBmp( mpBackBuffer
->getOutDev().GetBitmapEx( aEmptyPoint
,
124 if( isContentFullyOpaque() )
126 // optimized case: content canvas is fully
127 // opaque. Note: since we retrieved aBmp directly
128 // from an OutDev, it's already a 'display bitmap'
134 // sprite content might contain alpha, create
136 BitmapEx
aMask( mpBackBufferMask
->getOutDev().GetBitmapEx( aEmptyPoint
,
138 AlphaMask
aAlpha( aMask
.GetBitmap() );
141 // Note: since we retrieved aBmp and aMask
142 // directly from an OutDev, it's already a
143 // 'display bitmap' on windows.
144 maContent
= BitmapEx( aBmp
.GetBitmap(), aAlpha
);
148 ::basegfx::B2DHomMatrix
aTransform( getTransformation() );
150 rTargetSurface
.Push( vcl::PushFlags::CLIPREGION
);
152 // apply clip (if any)
155 ::basegfx::B2DPolyPolygon
aClipPoly(
156 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
159 if( aClipPoly
.count() )
161 // Move the clip to the final sprite output position.
162 ::basegfx::B2DHomMatrix
aClipTransform( aTransform
);
163 aClipTransform
.translate( aOutPos
.X(), aOutPos
.Y() );
164 aClipPoly
.transform( aClipTransform
);
166 if( mbShowSpriteBounds
)
168 // Paint green sprite clip area
169 rTargetSurface
.SetLineColor( COL_LIGHTGREEN
);
170 rTargetSurface
.SetFillColor();
172 rTargetSurface
.DrawPolyPolygon(::tools::PolyPolygon(aClipPoly
)); // #i76339#
175 vcl::Region
aClipRegion( aClipPoly
);
176 rTargetSurface
.SetClipRegion( aClipRegion
);
180 ::basegfx::B2DHomMatrix aSizeTransform
, aMoveTransform
;
181 aSizeTransform
.scale( aOutputSize
.Width(), aOutputSize
.Height() );
182 aMoveTransform
.translate( aOutPos
.X(), aOutPos
.Y() );
183 aTransform
= aMoveTransform
* aTransform
* aSizeTransform
;
185 rTargetSurface
.DrawTransformedBitmapEx( aTransform
, *maContent
, fAlpha
);
187 rTargetSurface
.Pop();
189 if( !mbShowSpriteBounds
)
192 ::tools::PolyPolygon
aMarkerPoly(
193 ::canvas::tools::getBoundMarksPolyPolygon(
194 ::basegfx::B2DRectangle(aOutPos
.X(),
196 aOutPos
.X() + aOutputSize
.Width()-1,
197 aOutPos
.Y() + aOutputSize
.Height()-1) ) );
199 // Paint little red sprite area markers
200 rTargetSurface
.SetLineColor( COL_RED
);
201 rTargetSurface
.SetFillColor();
203 for( int i
=0; i
<aMarkerPoly
.Count(); ++i
)
205 rTargetSurface
.DrawPolyLine( aMarkerPoly
.GetObject(static_cast<sal_uInt16
>(i
)) );
210 aVCLFont
.SetFontHeight( std::min(::tools::Long(20),aOutputSize
.Height()) );
211 aVCLFont
.SetColor( COL_RED
);
213 rTargetSurface
.SetTextAlign(ALIGN_TOP
);
214 rTargetSurface
.SetTextColor( COL_RED
);
215 rTargetSurface
.SetFont( aVCLFont
);
217 OUString
text( ::rtl::math::doubleToUString( getPriority(),
218 rtl_math_StringFormat_F
,
219 2,'.',nullptr,' ') );
221 rTargetSurface
.DrawText( aOutPos
+Point(2,2), text
);
222 SAL_INFO( "canvas.vcl",
223 "sprite " << this << " has prio " << getPriority());
226 ::basegfx::B2DPolyPolygon
SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference
< rendering::XPolyPolygon2D
>& xPoly
) const
228 return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly
);
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */