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 <basegfx/polygon/b2dpolygoncutandtouch.hxx>
29 #include <basegfx/polygon/b2dpolygontriangulator.hxx>
30 #include <basegfx/polygon/b2dpolypolygontools.hxx>
31 #include "surfaceproxy.hxx"
32 
33 namespace canvas
34 {
35 	//////////////////////////////////////////////////////////////////////////////////
36 	// SurfaceProxy::SurfaceProxy
37 	//////////////////////////////////////////////////////////////////////////////////
38 
39 	SurfaceProxy::SurfaceProxy( const canvas::IColorBufferSharedPtr& pBuffer,
40 								const PageManagerSharedPtr&          pPageManager ) :
41 		mpPageManager( pPageManager ),
42         maSurfaceList(),
43         mpBuffer( pBuffer )
44     {
45 		const ::basegfx::B2ISize aImageSize(mpBuffer->getWidth(),mpBuffer->getHeight());
46 		const ::basegfx::B2ISize aPageSize(mpPageManager->getPageSize());
47 		const sal_Int32 aPageSizeX(aPageSize.getX());
48 		const sal_Int32 aPageSizeY(aPageSize.getY());
49 		const sal_Int32 aImageSizeX(aImageSize.getX());
50 		const sal_Int32 aImageSizeY(aImageSize.getY());
51 
52 		// see if the size of the colorbuffer is larger than the size
53 		// of a single page. if this is the case we divide the
54 		// colorbuffer into as many surfaces as we need to get the
55 		// whole area distributed.  otherwise (the colorbuffer is
56 		// smaller than the size of a single page) we search for free
57 		// pages or create a new one.
58 		// the incoming image is too large to fit into a single
59 		// page.  strategy: we split the image into rectangular
60 		// areas that are as large as the maximum page size
61 		// dictates and follow the strategy for fitting images.
62 		size_t dwNumSurfaces(0);
63 		for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
64 			for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
65 				++dwNumSurfaces;
66 		maSurfaceList.reserve(dwNumSurfaces);
67 
68 		for(sal_Int32 y=0; y<aImageSizeY; y+=aPageSizeY)
69 		{
70 			for(sal_Int32 x=0; x<aImageSizeX; x+=aPageSizeX)
71 			{
72 				// the current surface is located at the position [x,y]
73 				// and has the size [min(restx,pagesizex),min(resty,pagesizey)
74 				::basegfx::B2IPoint aOffset(x,y);
75 				::basegfx::B2ISize aSize( ::std::min( aImageSize.getX()-x,
76                                                       aPageSize.getX() ),
77                                           ::std::min( aImageSize.getY()-y,
78                                                       aPageSize.getY() ) );
79 
80 				maSurfaceList.push_back(
81 					SurfaceSharedPtr(
82 						new Surface(
83 							mpPageManager,
84 							mpBuffer,
85 							aOffset,
86 							aSize)));
87 			}
88 		}
89     }
90 
91 	//////////////////////////////////////////////////////////////////////////////////
92 	// SurfaceProxy::setColorBufferDirty
93 	//////////////////////////////////////////////////////////////////////////////////
94 
95 	void SurfaceProxy::setColorBufferDirty()
96 	{
97 		::std::for_each( maSurfaceList.begin(),
98                          maSurfaceList.end(),
99 						 ::boost::mem_fn(&Surface::setColorBufferDirty));
100 	}
101 
102 	//////////////////////////////////////////////////////////////////////////////////
103 	// SurfaceProxy::draw
104 	//////////////////////////////////////////////////////////////////////////////////
105 
106 	bool SurfaceProxy::draw( double                         fAlpha,
107                              const ::basegfx::B2DPoint&     rPos,
108                              const ::basegfx::B2DHomMatrix& rTransform )
109 	{
110 		::std::for_each( maSurfaceList.begin(),
111                          maSurfaceList.end(),
112 						 ::boost::bind( &Surface::draw,
113                                         _1,
114                                         fAlpha,
115                                         ::boost::cref(rPos),
116                                         ::boost::cref(rTransform)));
117 
118 		return true;
119 	}
120 
121 	//////////////////////////////////////////////////////////////////////////////////
122 	// SurfaceProxy::draw
123 	//////////////////////////////////////////////////////////////////////////////////
124 
125 	bool SurfaceProxy::draw( double                         fAlpha,
126                              const ::basegfx::B2DPoint&     rPos,
127                              const ::basegfx::B2DRange&		rArea,
128                              const ::basegfx::B2DHomMatrix& rTransform )
129 	{
130 		::std::for_each( maSurfaceList.begin(),
131                          maSurfaceList.end(),
132 						 ::boost::bind(&Surface::drawRectangularArea,
133                                        _1,
134                                        fAlpha,
135                                        ::boost::cref(rPos),
136                                        ::boost::cref(rArea),
137                                        ::boost::cref(rTransform)));
138 
139 		return true;
140 	}
141 
142 	//////////////////////////////////////////////////////////////////////////////////
143 	// SurfaceProxy::draw
144 	//////////////////////////////////////////////////////////////////////////////////
145 
146 	bool SurfaceProxy::draw( double                           fAlpha,
147                              const ::basegfx::B2DPoint&       rPos,
148                              const ::basegfx::B2DPolyPolygon& rClipPoly,
149                              const ::basegfx::B2DHomMatrix&   rTransform )
150 	{
151 		const ::basegfx::B2DPolygon& rTriangulatedPolygon(
152             ::basegfx::triangulator::triangulate(rClipPoly));
153 
154 #if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
155         // dump polygons
156         OSL_TRACE( "Original clip polygon: %s\n"
157                    "Triangulated polygon: %s\n",
158                    rtl::OUStringToOString(
159                        basegfx::tools::exportToSvgD( rClipPoly ),
160                        RTL_TEXTENCODING_ASCII_US).getStr(),
161                    rtl::OUStringToOString(
162                        basegfx::tools::exportToSvgD(
163                            basegfx::B2DPolyPolygon(rTriangulatedPolygon) ),
164                        RTL_TEXTENCODING_ASCII_US).getStr() );
165 #endif
166 
167 		::std::for_each( maSurfaceList.begin(),
168                          maSurfaceList.end(),
169 						 ::boost::bind(&Surface::drawWithClip,
170                                        _1,
171                                        fAlpha,
172                                        ::boost::cref(rPos),
173                                        ::boost::cref(rTriangulatedPolygon),
174                                        ::boost::cref(rTransform)));
175 
176 		return true;
177 	}
178 }
179