xref: /trunk/main/canvas/source/tools/page.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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