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