LibreOffice Module canvas (master) 1
spritehelper.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 <sal/config.h>
21#include <sal/log.hxx>
22
28#include <rtl/math.hxx>
29#include <tools/diagnose_ex.h>
30#include <vcl/alpha.hxx>
31#include <vcl/bitmapex.hxx>
32#include <vcl/canvastools.hxx>
33#include <vcl/outdev.hxx>
34
36
37#include "spritehelper.hxx"
38
39using namespace ::com::sun::star;
40
41
42namespace vclcanvas
43{
45 mbShowSpriteBounds(false)
46 {
47 }
48
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 )
54 {
55 ENSURE_OR_THROW( rOwningSpriteCanvas && rBackBuffer && rBackBufferMask,
56 "SpriteHelper::init(): Invalid sprite canvas or back buffer" );
57
58 mpBackBuffer = rBackBuffer;
59 mpBackBufferMask = rBackBufferMask;
60 mbShowSpriteBounds = bShowSpriteBounds;
61
62 init( rSpriteSize, rOwningSpriteCanvas );
63 }
64
66 {
67 mpBackBuffer.reset();
68 mpBackBufferMask.reset();
69
70 // forward to parent
71 CanvasCustomSpriteHelper::disposing();
72 }
73
74 void SpriteHelper::redraw( OutputDevice& rTargetSurface,
75 const ::basegfx::B2DPoint& rPos,
76 bool& io_bSurfacesDirty,
77 bool /*bBufferedUpdate*/ ) const
78 {
79 if( !mpBackBuffer ||
81 {
82 return; // we're disposed
83 }
84
85 // log output pos in device pixel
86 SAL_INFO("canvas.vcl", "SpriteHelper::redraw(): output pos is (" <<
87 rPos.getX() << "," << rPos.getY() << ")");
88
89 const double fAlpha( getAlpha() );
90
91 if( !isActive() || ::basegfx::fTools::equalZero( fAlpha ) )
92 return;
93
94 const ::basegfx::B2DVector& rOrigOutputSize( getSizePixel() );
95
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
100 // sync.
101 ::Size aOutputSize( vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
102 ::Point aOutPos( vcl::unotools::pointFromB2DPoint( rPos ) );
103
104
105 // TODO(F3): Support for alpha-VDev
106
107 // Do we have to update our bitmaps (necessary if virdev
108 // was painted to, or transformation changed)?
109 const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
111 maContent->IsEmpty() );
112
113 // updating content of sprite cache - surface is no
114 // longer dirty in relation to our cache
115 io_bSurfacesDirty = false;
117
118 if( bNeedBitmapUpdate )
119 {
120 const Point aEmptyPoint;
121 BitmapEx aBmp( mpBackBuffer->getOutDev().GetBitmapEx( aEmptyPoint,
122 aOutputSize ) );
123
125 {
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'
129 // on windows.
130 maContent = aBmp;
131 }
132 else
133 {
134 // sprite content might contain alpha, create
135 // BmpEx, then.
136 BitmapEx aMask( mpBackBufferMask->getOutDev().GetBitmapEx( aEmptyPoint,
137 aOutputSize ) );
138
139 // Note: since we retrieved aBmp and aMask
140 // directly from an OutDev, it's already a
141 // 'display bitmap' on windows.
142 maContent = BitmapEx( aBmp.GetBitmap(), AlphaMask( aMask.GetBitmap()) );
143 }
144 }
145
147
148 rTargetSurface.Push( vcl::PushFlags::CLIPREGION );
149
150 // apply clip (if any)
151 if( getClip().is() )
152 {
154 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
155 getClip() ));
156
157 if( aClipPoly.count() )
158 {
159 // Move the clip to the final sprite output position.
160 ::basegfx::B2DHomMatrix aClipTransform( aTransform );
161 aClipTransform.translate( aOutPos.X(), aOutPos.Y() );
162 aClipPoly.transform( aClipTransform );
163
165 {
166 // Paint green sprite clip area
167 rTargetSurface.SetLineColor( Color( 0,255,0 ) );
168 rTargetSurface.SetFillColor();
169
170 rTargetSurface.DrawPolyPolygon(::tools::PolyPolygon(aClipPoly)); // #i76339#
171 }
172
173 vcl::Region aClipRegion( aClipPoly );
174 rTargetSurface.SetClipRegion( aClipRegion );
175 }
176 }
177
178 ::basegfx::B2DHomMatrix aSizeTransform, aMoveTransform;
179 aSizeTransform.scale( aOutputSize.Width(), aOutputSize.Height() );
180 aMoveTransform.translate( aOutPos.X(), aOutPos.Y() );
181 aTransform = aMoveTransform * aTransform * aSizeTransform;
182
183 rTargetSurface.DrawTransformedBitmapEx( aTransform, *maContent, fAlpha );
184
185 rTargetSurface.Pop();
186
187 if( !mbShowSpriteBounds )
188 return;
189
190 ::tools::PolyPolygon aMarkerPoly(
192 ::basegfx::B2DRectangle(aOutPos.X(),
193 aOutPos.Y(),
194 aOutPos.X() + aOutputSize.Width()-1,
195 aOutPos.Y() + aOutputSize.Height()-1) ) );
196
197 // Paint little red sprite area markers
198 rTargetSurface.SetLineColor( COL_RED );
199 rTargetSurface.SetFillColor();
200
201 for( int i=0; i<aMarkerPoly.Count(); ++i )
202 {
203 rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject(static_cast<sal_uInt16>(i)) );
204 }
205
206 // paint sprite prio
207 vcl::Font aVCLFont;
208 aVCLFont.SetFontHeight( std::min(::tools::Long(20),aOutputSize.Height()) );
209 aVCLFont.SetColor( COL_RED );
210
211 rTargetSurface.SetTextAlign(ALIGN_TOP);
212 rTargetSurface.SetTextColor( COL_RED );
213 rTargetSurface.SetFont( aVCLFont );
214
215 OUString text( ::rtl::math::doubleToUString( getPriority(),
216 rtl_math_StringFormat_F,
217 2,'.',nullptr,' ') );
218
219 rTargetSurface.DrawText( aOutPos+Point(2,2), text );
220 SAL_INFO( "canvas.vcl",
221 "sprite " << this << " has prio " << getPriority());
222 }
223
224 ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
225 {
226 return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly );
227 }
228
229}
230
231/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsEmpty() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
void DrawTransformedBitmapEx(const basegfx::B2DHomMatrix &rTransformation, const BitmapEx &rBitmapEx, double fAlpha=1.0)
void DrawPolyLine(const tools::Polygon &rPoly)
void SetFont(const vcl::Font &rNewFont)
void SetTextAlign(TextAlign eAlign)
void SetLineColor()
void SetTextColor(const Color &rColor)
void SetClipRegion()
void SetFillColor()
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
constexpr tools::Long Height() const
constexpr tools::Long Width() const
void translate(double fX, double fY)
void scale(double fX, double fY)
void transform(const basegfx::B2DHomMatrix &rMatrix)
sal_uInt32 count() const
bool isContentFullyOpaque() const
Returns true, if sprite content bitmap is fully opaque.
void transformUpdated() const
Notifies that caller is again in sync with current transformation.
const css::uno::Reference< css::rendering::XPolyPolygon2D > & getClip() const
Retrieve current clip.
bool isActive() const
Retrieve current activation state.
const ::basegfx::B2DHomMatrix & getTransformation() const
bool hasTransformChanged() const
Returns true, if transformation has changed since last transformUpdated() call.
double getAlpha() const
Retrieve current alpha value.
const ::basegfx::B2DVector & getSizePixel() const
sal_uInt16 Count() const
const tools::Polygon & GetObject(sal_uInt16 nPos) const
void SetColor(const Color &)
void SetFontHeight(tools::Long nHeight)
void init(const css::geometry::RealSize2D &rSpriteSize, const ::canvas::SpriteSurface::Reference &rOwningSpriteCanvas, const BackBufferSharedPtr &rBackBuffer, const BackBufferSharedPtr &rBackBufferMask, bool bShowSpriteBounds)
Late-init the sprite helper.
void redraw(OutputDevice &rOutDev, const ::basegfx::B2DPoint &rPos, bool &bSurfacesDirty, bool bBufferedUpdate) const
Repaint sprite content to associated sprite canvas.
mutable ::canvas::vcltools::VCLObject< BitmapEx > maContent
Cached bitmap for the current sprite content.
virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D(css::uno::Reference< css::rendering::XPolyPolygon2D > &xPoly) const override
Called to convert an API polygon to a basegfx polygon.
BackBufferSharedPtr mpBackBuffer
bool mbShowSpriteBounds
When true, line sprite corners in red.
BackBufferSharedPtr mpBackBufferMask
constexpr ::Color COL_RED(0x80, 0x00, 0x00)
#define ENSURE_OR_THROW(c, m)
ALIGN_TOP
#define SAL_INFO(area, stream)
def text(shape, orig_st)
::basegfx::B2DPolyPolygon getBoundMarksPolyPolygon(const ::basegfx::B2DRange &rRange)
Retrieve for small bound marks around each corner of the given rectangle.
int i
long Long
::Point pointFromB2DPoint(const basegfx::B2DPoint &rPoint)
::Size sizeFromB2DSize(const basegfx::B2DVector &rVec)
std::shared_ptr< BackBuffer > BackBufferSharedPtr
Definition: backbuffer.hxx:47