| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_canvas.hxx" |
| |
| #include <boost/bind.hpp> |
| #include "page.hxx" |
| |
| namespace canvas |
| { |
| Page::Page( const IRenderModuleSharedPtr &rRenderModule ) : |
| mpRenderModule(rRenderModule), |
| mpSurface(rRenderModule->createSurface(::basegfx::B2ISize())) |
| { |
| } |
| |
| void Page::validate() |
| { |
| if(!(isValid())) |
| { |
| ::std::for_each( mpFragments.begin(), |
| mpFragments.end(), |
| ::boost::mem_fn(&PageFragment::refresh)); |
| } |
| } |
| |
| bool Page::isValid() const |
| { |
| return mpSurface && mpSurface->isValid(); |
| } |
| |
| FragmentSharedPtr Page::allocateSpace( const ::basegfx::B2ISize& rSize ) |
| { |
| SurfaceRect rect(rSize); |
| if(insert(rect)) |
| { |
| FragmentSharedPtr pFragment(new PageFragment(rect,this)); |
| mpFragments.push_back(pFragment); |
| return pFragment; |
| } |
| |
| return FragmentSharedPtr(); |
| } |
| |
| bool Page::nakedFragment( const FragmentSharedPtr& pFragment ) |
| { |
| SurfaceRect rect(pFragment->getSize()); |
| if(insert(rect)) |
| { |
| pFragment->setPage(this); |
| mpFragments.push_back(pFragment); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void Page::free( const FragmentSharedPtr& pFragment ) |
| { |
| // the fragment passes as argument is no longer |
| // dedicated to this page. either it is about to |
| // be relocated to some other page or it will |
| // currently be deleted. in either case, simply |
| // remove the reference from our internal storage. |
| FragmentContainer_t::iterator it( |
| std::remove( |
| mpFragments.begin(),mpFragments.end(),pFragment)); |
| mpFragments.erase(it,mpFragments.end()); |
| } |
| |
| bool Page::insert( SurfaceRect& r ) |
| { |
| const FragmentContainer_t::const_iterator aEnd(mpFragments.end()); |
| FragmentContainer_t::const_iterator it(mpFragments.begin()); |
| while(it != aEnd) |
| { |
| const SurfaceRect &rect = (*it)->getRect(); |
| const sal_Int32 x = rect.maPos.getX(); |
| const sal_Int32 y = rect.maPos.getY(); |
| // to avoid interpolation artifacts from other textures, |
| // one pixel gap between them |
| const sal_Int32 w = rect.maSize.getX()+1; |
| const sal_Int32 h = rect.maSize.getY()+1; |
| |
| // probe location to the right |
| r.maPos.setX(x+w); |
| r.maPos.setY(y); |
| if(isValidLocation(r)) |
| return true; |
| |
| // probe location at bottom |
| r.maPos.setX(x); |
| r.maPos.setY(y+h); |
| if(isValidLocation(r)) |
| return true; |
| |
| ++it; |
| } |
| |
| r.maPos.setX(0); |
| r.maPos.setY(0); |
| |
| return isValidLocation(r); |
| } |
| |
| bool Page::isValidLocation( const SurfaceRect& r ) const |
| { |
| // the rectangle passed as argument has a valid |
| // location if and only if there's no intersection |
| // with existing areas. |
| SurfaceRect aBoundary(mpRenderModule->getPageSize()-basegfx::B2IVector(1,1)); |
| if( !r.inside(aBoundary) ) |
| return false; |
| |
| const FragmentContainer_t::const_iterator aEnd(mpFragments.end()); |
| FragmentContainer_t::const_iterator it(mpFragments.begin()); |
| while(it != aEnd) |
| { |
| if(r.intersection((*it)->getRect())) |
| return false; |
| |
| ++it; |
| } |
| |
| return true; |
| } |
| } |