summaryrefslogtreecommitdiff
path: root/canvas/source/tools/page.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/tools/page.cxx')
-rw-r--r--canvas/source/tools/page.cxx152
1 files changed, 152 insertions, 0 deletions
diff --git a/canvas/source/tools/page.cxx b/canvas/source/tools/page.cxx
new file mode 100644
index 000000000000..5035c0e81916
--- /dev/null
+++ b/canvas/source/tools/page.cxx
@@ -0,0 +1,152 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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;
+ }
+}