1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
30 
31 #include <boost/bind.hpp>
32 #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
33 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
34 #include <basegfx/polygon/b2dpolypolygontools.hxx>
35 #include "surfaceproxy.hxx"
36 
37 namespace canvas
38 {
39 	//////////////////////////////////////////////////////////////////////////////////
40 	// SurfaceProxy::SurfaceProxy
41 	//////////////////////////////////////////////////////////////////////////////////
42 
43 	SurfaceProxy::SurfaceProxy( const canvas::IColorBufferSharedPtr& pBuffer,
44 								const PageManagerSharedPtr&          pPageManager ) :
45 		mpPageManager( pPageManager ),
46         maSurfaceList(),
47         mpBuffer( pBuffer )
48     {
49 		const ::basegfx::B2ISize aImageSize(mpBuffer->getWidth(),mpBuffer->getHeight());
50 		const ::basegfx::B2ISize aPageSize(mpPageManager->getPageSize());
51 		const sal_Int32 aPageSizeX(aPageSize.getX());
52 		const sal_Int32 aPageSizeY(aPageSize.getY());
53 		const sal_Int32 aImageSizeX(aImageSize.getX());
54 		const sal_Int32 aImageSizeY(aImageSize.getY());
55 
56 		// see if the size of the colorbuffer is larger than the size
57 		// of a single page. if this is the case we divide the
58 		// colorbuffer into as many surfaces as we need to get the
59 		// whole area distributed.  otherwise (the colorbuffer is
60 		// smaller than the size of a single page) we search for free
61 		// pages or create a new one.
62 		// the incoming image is too large to fit into a single
63 		// page.  strategy: we split the image into rectangular
64 		// areas that are as large as the maximum page size
65 		// dictates and follow the strategy for fitting images.
66 		size_t dwNumSurfaces(0);
67 		for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
68 			for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
69 				++dwNumSurfaces;
70 		maSurfaceList.reserve(dwNumSurfaces);
71 
72 		for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
73 		{
74 			for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
75 			{
76 				// the current surface is located at the position [x,y]
77 				// and has the size [min(restx,pagesizex),min(resty,pagesizey)
78 				::basegfx::B2IPoint aOffset(x,y);
79 				::basegfx::B2ISize aSize( ::std::min( aImageSize.getX()-x,
80                                                       aPageSize.getX() ),
81                                           ::std::min( aImageSize.getY()-y,
82                                                       aPageSize.getY() ) );
83 
84 				maSurfaceList.push_back(
85 					SurfaceSharedPtr(
86 						new Surface(
87 							mpPageManager,
88 							mpBuffer,
89 							aOffset,
90 							aSize)));
91 			}
92 		}
93     }
94 
95 	//////////////////////////////////////////////////////////////////////////////////
96 	// SurfaceProxy::setColorBufferDirty
97 	//////////////////////////////////////////////////////////////////////////////////
98 
99 	void SurfaceProxy::setColorBufferDirty()
100 	{
101 		::std::for_each( maSurfaceList.begin(),
102                          maSurfaceList.end(),
103 						 ::boost::mem_fn(&Surface::setColorBufferDirty));
104 	}
105 
106 	//////////////////////////////////////////////////////////////////////////////////
107 	// SurfaceProxy::draw
108 	//////////////////////////////////////////////////////////////////////////////////
109 
110 	bool SurfaceProxy::draw( double                         fAlpha,
111                              const ::basegfx::B2DPoint&     rPos,
112                              const ::basegfx::B2DHomMatrix& rTransform )
113 	{
114 		::std::for_each( maSurfaceList.begin(),
115                          maSurfaceList.end(),
116 						 ::boost::bind( &Surface::draw,
117                                         _1,
118                                         fAlpha,
119                                         ::boost::cref(rPos),
120                                         ::boost::cref(rTransform)));
121 
122 		return true;
123 	}
124 
125 	//////////////////////////////////////////////////////////////////////////////////
126 	// SurfaceProxy::draw
127 	//////////////////////////////////////////////////////////////////////////////////
128 
129 	bool SurfaceProxy::draw( double                         fAlpha,
130                              const ::basegfx::B2DPoint&     rPos,
131                              const ::basegfx::B2DRange&		rArea,
132                              const ::basegfx::B2DHomMatrix& rTransform )
133 	{
134 		::std::for_each( maSurfaceList.begin(),
135                          maSurfaceList.end(),
136 						 ::boost::bind(&Surface::drawRectangularArea,
137                                        _1,
138                                        fAlpha,
139                                        ::boost::cref(rPos),
140                                        ::boost::cref(rArea),
141                                        ::boost::cref(rTransform)));
142 
143 		return true;
144 	}
145 
146 	//////////////////////////////////////////////////////////////////////////////////
147 	// SurfaceProxy::draw
148 	//////////////////////////////////////////////////////////////////////////////////
149 
150 	bool SurfaceProxy::draw( double                           fAlpha,
151                              const ::basegfx::B2DPoint&       rPos,
152                              const ::basegfx::B2DPolyPolygon& rClipPoly,
153                              const ::basegfx::B2DHomMatrix&   rTransform )
154 	{
155 		const ::basegfx::B2DPolygon& rTriangulatedPolygon(
156             ::basegfx::triangulator::triangulate(rClipPoly));
157 
158 #if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
159         // dump polygons
160         OSL_TRACE( "Original clip polygon: %s\n"
161                    "Triangulated polygon: %s\n",
162                    rtl::OUStringToOString(
163                        basegfx::tools::exportToSvgD( rClipPoly ),
164                        RTL_TEXTENCODING_ASCII_US).getStr(),
165                    rtl::OUStringToOString(
166                        basegfx::tools::exportToSvgD(
167                            basegfx::B2DPolyPolygon(rTriangulatedPolygon) ),
168                        RTL_TEXTENCODING_ASCII_US).getStr() );
169 #endif
170 
171 		::std::for_each( maSurfaceList.begin(),
172                          maSurfaceList.end(),
173 						 ::boost::bind(&Surface::drawWithClip,
174                                        _1,
175                                        fAlpha,
176                                        ::boost::cref(rPos),
177                                        ::boost::cref(rTriangulatedPolygon),
178                                        ::boost::cref(rTransform)));
179 
180 		return true;
181 	}
182 }
183