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