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 .
22 #include <canvas/debug.hxx>
24 #include <basegfx/range/b2drange.hxx>
25 #include <basegfx/range/b1drange.hxx>
26 #include <basegfx/range/b2dpolyrange.hxx>
27 #include <basegfx/matrix/b2dhommatrix.hxx>
28 #include <basegfx/polygon/b2dpolypolygon.hxx>
29 #include <basegfx/polygon/b2dpolypolygontools.hxx>
30 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
34 #include <boost/bind.hpp>
37 using namespace ::com::sun::star
;
43 Layer::Layer( const basegfx::B2DRange
& rMaxLayerBounds
,
48 maMaxBounds( rMaxLayerBounds
),
50 mbBackgroundLayer(true),
55 Layer::Layer( const basegfx::B2DRange
& rMaxLayerBounds
) :
59 maMaxBounds( rMaxLayerBounds
),
61 mbBackgroundLayer(false),
66 ViewLayerSharedPtr
Layer::addView( const ViewSharedPtr
& rNewView
)
68 OSL_ASSERT( rNewView
);
70 ViewEntryVector::iterator aIter
;
71 const ViewEntryVector::iterator
aEnd( maViewEntries
.end() );
72 if( (aIter
=std::find_if( maViewEntries
.begin(),
75 std::equal_to
< ViewSharedPtr
>(),
76 boost::bind( &ViewEntry::getView
, _1
),
77 boost::cref( rNewView
)))) != aEnd
)
79 // already added - just return existing layer
80 return aIter
->mpViewLayer
;
84 // not yet added - create new view layer
85 ViewLayerSharedPtr pNewLayer
;
86 if( mbBackgroundLayer
)
89 pNewLayer
= rNewView
->createViewLayer(maBounds
);
92 maViewEntries
.push_back(
96 return maViewEntries
.back().mpViewLayer
;
99 ViewLayerSharedPtr
Layer::removeView( const ViewSharedPtr
& rView
)
103 ViewEntryVector::iterator aIter
;
104 const ViewEntryVector::iterator
aEnd( maViewEntries
.end() );
105 if( (aIter
=std::find_if( maViewEntries
.begin(),
108 std::equal_to
< ViewSharedPtr
>(),
109 boost::bind( &ViewEntry::getView
, _1
),
110 boost::cref( rView
)))) == aEnd
)
112 // View was not added/is already removed
113 return ViewLayerSharedPtr();
116 OSL_ENSURE( std::count_if( maViewEntries
.begin(),
119 std::equal_to
< ViewSharedPtr
>(),
120 boost::bind( &ViewEntry::getView
, _1
),
121 boost::cref( rView
))) == 1,
122 "Layer::removeView(): view added multiple times" );
124 ViewLayerSharedPtr
pRet( aIter
->mpViewLayer
);
125 maViewEntries
.erase(aIter
);
130 void Layer::setShapeViews( ShapeSharedPtr
const& rShape
) const
132 rShape
->clearAllViewLayers();
134 std::for_each( maViewEntries
.begin(),
136 boost::bind(&Shape::addViewLayer
,
138 boost::bind(&ViewEntry::getViewLayer
,
143 void Layer::setPriority( const ::basegfx::B1DRange
& rPrioRange
)
145 if( !mbBackgroundLayer
)
147 std::for_each( maViewEntries
.begin(),
149 boost::bind( &ViewLayer::setPriority
,
150 boost::bind( &ViewEntry::getViewLayer
,
152 boost::cref(rPrioRange
)));
156 void Layer::addUpdateRange( ::basegfx::B2DRange
const& rUpdateRange
)
158 // TODO(Q1): move this to B2DMultiRange
159 if( !rUpdateRange
.isEmpty() )
160 maUpdateAreas
.appendElement( rUpdateRange
,
161 basegfx::ORIENTATION_POSITIVE
);
164 void Layer::updateBounds( ShapeSharedPtr
const& rShape
)
166 if( !mbBackgroundLayer
)
171 maNewBounds
.expand( rShape
->getUpdateArea() );
174 mbBoundsDirty
= true;
177 bool Layer::commitBounds()
179 mbBoundsDirty
= false;
181 if( mbBackgroundLayer
)
184 if( maNewBounds
== maBounds
)
187 maBounds
= maNewBounds
;
188 if( std::count_if( maViewEntries
.begin(),
190 boost::bind( &ViewLayer::resize
,
191 boost::bind( &ViewEntry::getViewLayer
,
193 boost::cref(maBounds
)) ) == 0 )
198 // layer content invalid, update areas have wrong
199 // coordinates/not sensible anymore.
205 void Layer::clearUpdateRanges()
207 maUpdateAreas
.clear();
210 void Layer::clearContent()
212 // clear content on all view layers
213 std::for_each( maViewEntries
.begin(),
216 &ViewLayer::clearAll
,
218 &ViewEntry::getViewLayer
,
221 // layer content cleared, update areas are not sensible
226 class LayerEndUpdate
: private boost::noncopyable
229 LayerEndUpdate( LayerSharedPtr
const& rLayer
) :
233 ~LayerEndUpdate() { if(mpLayer
) mpLayer
->endUpdate(); }
236 LayerSharedPtr mpLayer
;
239 Layer::EndUpdater
Layer::beginUpdate()
241 if( maUpdateAreas
.count() )
243 // perform proper layer update. That means, setup proper
244 // clipping, and render each shape that intersects with
245 // the calculated update area
246 ::basegfx::B2DPolyPolygon
aClip( maUpdateAreas
.solveCrossovers() );
247 aClip
= ::basegfx::tools::stripNeutralPolygons(aClip
);
248 aClip
= ::basegfx::tools::stripDispensablePolygons(aClip
, false);
250 // actually, if there happen to be shapes with zero
251 // update area in the maUpdateAreas vector, the
252 // resulting clip polygon will be empty.
255 // set clip to all view layers
256 std::for_each( maViewEntries
.begin(),
261 &ViewEntry::getViewLayer
,
263 boost::cref(aClip
)));
265 // clear update area on all view layers
266 std::for_each( maViewEntries
.begin(),
271 &ViewEntry::getViewLayer
,
278 return EndUpdater(new LayerEndUpdate(shared_from_this()));
281 void Layer::endUpdate()
287 basegfx::B2DPolyPolygon aEmptyClip
;
288 std::for_each( maViewEntries
.begin(),
293 &ViewEntry::getViewLayer
,
295 boost::cref(aEmptyClip
)));
301 bool Layer::isInsideUpdateArea( ShapeSharedPtr
const& rShape
) const
303 return maUpdateAreas
.overlaps( rShape
->getUpdateArea() );
306 LayerSharedPtr
Layer::createBackgroundLayer( const basegfx::B2DRange
& rMaxLayerBounds
)
308 return LayerSharedPtr(new Layer( rMaxLayerBounds
,
312 LayerSharedPtr
Layer::createLayer( const basegfx::B2DRange
& rMaxLayerBounds
)
314 return LayerSharedPtr( new Layer( rMaxLayerBounds
) );
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */