xref: /trunk/main/canvas/source/tools/page.cxx (revision 25ea7f45)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_canvas.hxx"
26 
27 #include <boost/bind.hpp>
28 #include "page.hxx"
29 
30 namespace canvas
31 {
Page(const IRenderModuleSharedPtr & rRenderModule)32 	Page::Page( const IRenderModuleSharedPtr &rRenderModule ) :
33 		mpRenderModule(rRenderModule),
34 		mpSurface(rRenderModule->createSurface(::basegfx::B2ISize()))
35 	{
36 	}
37 
validate()38 	void Page::validate()
39 	{
40 		if(!(isValid()))
41 		{
42 			::std::for_each( mpFragments.begin(),
43 							 mpFragments.end(),
44 							 ::boost::mem_fn(&PageFragment::refresh));
45 		}
46 	}
47 
isValid() const48 	bool Page::isValid() const
49 	{
50 		return mpSurface && mpSurface->isValid();
51 	}
52 
allocateSpace(const::basegfx::B2ISize & rSize)53 	FragmentSharedPtr Page::allocateSpace( const ::basegfx::B2ISize& rSize )
54 	{
55 		SurfaceRect rect(rSize);
56 		if(insert(rect))
57 		{
58 			FragmentSharedPtr pFragment(new PageFragment(rect,this));
59 			mpFragments.push_back(pFragment);
60 			return pFragment;
61 		}
62 
63 		return FragmentSharedPtr();
64 	}
65 
nakedFragment(const FragmentSharedPtr & pFragment)66 	bool Page::nakedFragment( const FragmentSharedPtr& pFragment )
67 	{
68 		SurfaceRect rect(pFragment->getSize());
69 		if(insert(rect))
70 		{
71 			pFragment->setPage(this);
72 			mpFragments.push_back(pFragment);
73 			return true;
74 		}
75 
76 		return false;
77 	}
78 
free(const FragmentSharedPtr & pFragment)79 	void Page::free( const FragmentSharedPtr& pFragment )
80 	{
81 		// the fragment passes as argument is no longer
82 		// dedicated to this page. either it is about to
83 		// be relocated to some other page or it will
84 		// currently be deleted. in either case, simply
85 		// remove the reference from our internal storage.
86 		FragmentContainer_t::iterator it(
87 			std::remove(
88 				mpFragments.begin(),mpFragments.end(),pFragment));
89 		mpFragments.erase(it,mpFragments.end());
90 	}
91 
insert(SurfaceRect & r)92 	bool Page::insert( SurfaceRect& r )
93 	{
94 		const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
95 		FragmentContainer_t::const_iterator       it(mpFragments.begin());
96 		while(it != aEnd)
97 		{
98 			const SurfaceRect &rect = (*it)->getRect();
99             const sal_Int32 x = rect.maPos.getX();
100             const sal_Int32 y = rect.maPos.getY();
101             // to avoid interpolation artifacts from other textures,
102             // one pixel gap between them
103             const sal_Int32 w = rect.maSize.getX()+1;
104             const sal_Int32 h = rect.maSize.getY()+1;
105 
106 			// probe location to the right
107 			r.maPos.setX(x+w);
108             r.maPos.setY(y);
109             if(isValidLocation(r))
110 				return true;
111 
112 			// probe location at bottom
113             r.maPos.setX(x);
114             r.maPos.setY(y+h);
115             if(isValidLocation(r))
116 				return true;
117 
118 			++it;
119 		}
120 
121 		r.maPos.setX(0);
122 		r.maPos.setY(0);
123 
124 		return isValidLocation(r);
125 	}
126 
isValidLocation(const SurfaceRect & r) const127 	bool Page::isValidLocation( const SurfaceRect& r ) const
128 	{
129 		// the rectangle passed as argument has a valid
130 		// location if and only if there's no intersection
131 		// with existing areas.
132 		SurfaceRect aBoundary(mpRenderModule->getPageSize()-basegfx::B2IVector(1,1));
133 		if( !r.inside(aBoundary) )
134 			return false;
135 
136 		const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
137 		FragmentContainer_t::const_iterator       it(mpFragments.begin());
138 		while(it != aEnd)
139 		{
140             if(r.intersection((*it)->getRect()))
141                 return false;
142 
143 			++it;
144 		}
145 
146 		return true;
147 	}
148 }
149