xref: /aoo41x/main/canvas/source/tools/page.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
30 
31 #include <boost/bind.hpp>
32 #include "page.hxx"
33 
34 namespace canvas
35 {
36 	Page::Page( const IRenderModuleSharedPtr &rRenderModule ) :
37 		mpRenderModule(rRenderModule),
38 		mpSurface(rRenderModule->createSurface(::basegfx::B2ISize()))
39 	{
40 	}
41 
42 	void Page::validate()
43 	{
44 		if(!(isValid()))
45 		{
46 			::std::for_each( mpFragments.begin(),
47 							 mpFragments.end(),
48 							 ::boost::mem_fn(&PageFragment::refresh));
49 		}
50 	}
51 
52 	bool Page::isValid() const
53 	{
54 		return mpSurface && mpSurface->isValid();
55 	}
56 
57 	FragmentSharedPtr Page::allocateSpace( const ::basegfx::B2ISize& rSize )
58 	{
59 		SurfaceRect rect(rSize);
60 		if(insert(rect))
61 		{
62 			FragmentSharedPtr pFragment(new PageFragment(rect,this));
63 			mpFragments.push_back(pFragment);
64 			return pFragment;
65 		}
66 
67 		return FragmentSharedPtr();
68 	}
69 
70 	bool Page::nakedFragment( const FragmentSharedPtr& pFragment )
71 	{
72 		SurfaceRect rect(pFragment->getSize());
73 		if(insert(rect))
74 		{
75 			pFragment->setPage(this);
76 			mpFragments.push_back(pFragment);
77 			return true;
78 		}
79 
80 		return false;
81 	}
82 
83 	void Page::free( const FragmentSharedPtr& pFragment )
84 	{
85 		// the fragment passes as argument is no longer
86 		// dedicated to this page. either it is about to
87 		// be relocated to some other page or it will
88 		// currently be deleted. in either case, simply
89 		// remove the reference from our internal storage.
90 		FragmentContainer_t::iterator it(
91 			std::remove(
92 				mpFragments.begin(),mpFragments.end(),pFragment));
93 		mpFragments.erase(it,mpFragments.end());
94 	}
95 
96 	bool Page::insert( SurfaceRect& r )
97 	{
98 		const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
99 		FragmentContainer_t::const_iterator       it(mpFragments.begin());
100 		while(it != aEnd)
101 		{
102 			const SurfaceRect &rect = (*it)->getRect();
103             const sal_Int32 x = rect.maPos.getX();
104             const sal_Int32 y = rect.maPos.getY();
105             // to avoid interpolation artifacts from other textures,
106             // one pixel gap between them
107             const sal_Int32 w = rect.maSize.getX()+1;
108             const sal_Int32 h = rect.maSize.getY()+1;
109 
110 			// probe location to the right
111 			r.maPos.setX(x+w);
112             r.maPos.setY(y);
113             if(isValidLocation(r))
114 				return true;
115 
116 			// probe location at bottom
117             r.maPos.setX(x);
118             r.maPos.setY(y+h);
119             if(isValidLocation(r))
120 				return true;
121 
122 			++it;
123 		}
124 
125 		r.maPos.setX(0);
126 		r.maPos.setY(0);
127 
128 		return isValidLocation(r);
129 	}
130 
131 	bool Page::isValidLocation( const SurfaceRect& r ) const
132 	{
133 		// the rectangle passed as argument has a valid
134 		// location if and only if there's no intersection
135 		// with existing areas.
136 		SurfaceRect aBoundary(mpRenderModule->getPageSize()-basegfx::B2IVector(1,1));
137 		if( !r.inside(aBoundary) )
138 			return false;
139 
140 		const FragmentContainer_t::const_iterator aEnd(mpFragments.end());
141 		FragmentContainer_t::const_iterator       it(mpFragments.begin());
142 		while(it != aEnd)
143 		{
144             if(r.intersection((*it)->getRect()))
145                 return false;
146 
147 			++it;
148 		}
149 
150 		return true;
151 	}
152 }
153