xref: /AOO41X/main/canvas/source/tools/pagemanager.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 "pagemanager.hxx"
29 
30 namespace canvas
31 {
32 
33     //////////////////////////////////////////////////////////////////////////////////
34     // PageManager
35     //////////////////////////////////////////////////////////////////////////////////
36 
37     //////////////////////////////////////////////////////////////////////////////////
38     // PageManager::allocateSpace
39     //////////////////////////////////////////////////////////////////////////////////
40 
allocateSpace(const::basegfx::B2ISize & rSize)41     FragmentSharedPtr PageManager::allocateSpace( const ::basegfx::B2ISize& rSize )
42     {
43         // we are asked to find a location for the requested size.
44         // first we try to satisfy the request from the
45         // remaining space in the existing pages.
46         const PageContainer_t::iterator aEnd(maPages.end());
47         PageContainer_t::iterator       it(maPages.begin());
48         while(it != aEnd)
49         {
50             FragmentSharedPtr pFragment((*it)->allocateSpace(rSize));
51             if(pFragment)
52             {
53                 // the page created a new fragment, since we maybe want
54                 // to consolidate sparse pages we keep a reference to
55                 // the fragment.
56                 maFragments.push_back(pFragment);
57                 return pFragment;
58             }
59 
60             ++it;
61         }
62 
63         // otherwise try to create a new page and allocate space there...
64         PageSharedPtr pPage(new Page(mpRenderModule));
65         if(pPage->isValid())
66         {
67             maPages.push_back(pPage);
68             FragmentSharedPtr pFragment(pPage->allocateSpace(rSize));
69             if (pFragment)
70                 maFragments.push_back(pFragment);
71             return pFragment;
72         }
73 
74         // the rendermodule failed to create a new page [maybe out
75         // of videomemory], and all other pages could not take
76         // the new request. we decide to create a 'naked' fragment
77         // which will receive its location later.
78         FragmentSharedPtr pFragment(new PageFragment(rSize));
79         maFragments.push_back(pFragment);
80         return pFragment;
81     }
82 
83     //////////////////////////////////////////////////////////////////////////////////
84     // PageManager::free
85     //////////////////////////////////////////////////////////////////////////////////
86 
free(const FragmentSharedPtr & pFragment)87     void PageManager::free( const FragmentSharedPtr& pFragment )
88     {
89         // erase the reference to the given fragment from our
90         // internal container.
91         FragmentContainer_t::iterator it(
92             std::remove(
93                 maFragments.begin(),maFragments.end(),pFragment));
94         maFragments.erase(it,maFragments.end());
95 
96         // let the fragment itself know about it...
97         // we need to pass 'this' as argument since the fragment
98         // needs to pass this to the page and can't create
99         // shared_ptr from itself...
100         pFragment->free(pFragment);
101     }
102 
103     //////////////////////////////////////////////////////////////////////////////////
104     // PageManager::nakedFragment
105     //////////////////////////////////////////////////////////////////////////////////
106 
nakedFragment(const FragmentSharedPtr & pFragment)107     void PageManager::nakedFragment( const FragmentSharedPtr& pFragment )
108     {
109         if(maPages.empty())
110             return;
111 
112         // okay, one last chance is left, we try all available
113         // pages again. maybe some other fragment was deleted
114         // and we can exploit the space.
115         while(!(relocate(pFragment)))
116         {
117             // no way, we need to free up some space...
118             // TODO(F1): this is a heuristic, could
119             // be designed as a policy.
120             const FragmentContainer_t::const_iterator aEnd(maFragments.end());
121             FragmentContainer_t::const_iterator       candidate(maFragments.begin());
122             while(candidate != aEnd)
123             {
124                 if(*candidate && !((*candidate)->isNaked()))
125                     break;
126                 ++candidate;
127             }
128 
129             if (candidate != aEnd)
130             {
131                 const ::basegfx::B2ISize& rSize((*candidate)->getSize());
132                 sal_uInt32                nMaxArea(rSize.getX()*rSize.getY());
133 
134                 FragmentContainer_t::const_iterator it(candidate);
135                 while(it != aEnd)
136                 {
137                     if (*it && !((*it)->isNaked()))
138                     {
139                         const ::basegfx::B2ISize& rCandidateSize((*it)->getSize());
140                         const sal_uInt32 nArea(rCandidateSize.getX()*rCandidateSize.getY());
141                         if(nArea > nMaxArea)
142                         {
143                             candidate=it;
144                             nMaxArea=nArea;
145                         }
146                     }
147 
148                     ++it;
149                 }
150 
151                 // this does not erase the candidate,
152                 // but makes it 'naked'...
153                 (*candidate)->free(*candidate);
154             }
155             else
156                 break;
157         }
158     }
159 
160     //////////////////////////////////////////////////////////////////////////////////
161     // PageManager::relocate
162     //////////////////////////////////////////////////////////////////////////////////
163 
relocate(const FragmentSharedPtr & pFragment)164     bool PageManager::relocate( const FragmentSharedPtr& pFragment )
165     {
166         // the fragment passed as argument is assumed to
167         // be naked, that is it is not located on any page.
168         // we try all available pages again, maybe some
169         // other fragment was deleted and we can exploit the space.
170         const PageContainer_t::iterator aEnd(maPages.end());
171         PageContainer_t::iterator       it(maPages.begin());
172         while(it != aEnd)
173         {
174             // if the page at hand takes the fragment, we immediatelly
175             // call select() to pull the information from the associated
176             // image to the hardware surface.
177             if((*it)->nakedFragment(pFragment))
178             {
179                 // dirty, since newly allocated.
180                 pFragment->select(true);
181                 return true;
182             }
183 
184             ++it;
185         }
186 
187         return false;
188     }
189 
190     //////////////////////////////////////////////////////////////////////////////////
191     // PageManager::validatePages
192     //////////////////////////////////////////////////////////////////////////////////
193 
validatePages()194     void PageManager::validatePages()
195     {
196         ::std::for_each( maPages.begin(),
197                          maPages.end(),
198                          ::boost::mem_fn(&Page::validate));
199     }
200 
201     //////////////////////////////////////////////////////////////////////////////////
202     // PageManager::getPageSize
203     //////////////////////////////////////////////////////////////////////////////////
204 
getPageSize() const205     ::basegfx::B2ISize PageManager::getPageSize() const
206     {
207         return mpRenderModule->getPageSize();
208     }
209 
210     //////////////////////////////////////////////////////////////////////////////////
211     // PageManager::getRenderModule
212     //////////////////////////////////////////////////////////////////////////////////
213 
getRenderModule() const214     canvas::IRenderModuleSharedPtr PageManager::getRenderModule() const
215     {
216         return mpRenderModule;
217     }
218 }
219