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_sdext.hxx"
26 
27 #include "PresenterUIPainter.hxx"
28 
29 #include "PresenterCanvasHelper.hxx"
30 #include "PresenterGeometryHelper.hxx"
31 #include <com/sun/star/rendering/CompositeOperation.hpp>
32 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
33 
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36 
37 namespace sdext { namespace presenter {
38 
39 
PaintHorizontalBitmapComposite(const css::uno::Reference<css::rendering::XCanvas> & rxCanvas,const css::awt::Rectangle & rRepaintBox,const css::awt::Rectangle & rBoundingBox,const css::uno::Reference<css::rendering::XBitmap> & rxLeftBitmap,const css::uno::Reference<css::rendering::XBitmap> & rxRepeatableCenterBitmap,const css::uno::Reference<css::rendering::XBitmap> & rxRightBitmap)40 void PresenterUIPainter::PaintHorizontalBitmapComposite (
41     const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
42     const css::awt::Rectangle& rRepaintBox,
43     const css::awt::Rectangle& rBoundingBox,
44     const css::uno::Reference<css::rendering::XBitmap>& rxLeftBitmap,
45     const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap,
46     const css::uno::Reference<css::rendering::XBitmap>& rxRightBitmap)
47 {
48     if (PresenterGeometryHelper::AreRectanglesDisjoint(rRepaintBox, rBoundingBox))
49     {
50         // The bounding box lies completely outside the repaint area.
51         // Nothing has to be repainted.
52         return;
53     }
54 
55     // Get bitmap sizes.
56     geometry::IntegerSize2D aLeftBitmapSize;
57     if (rxLeftBitmap.is())
58         aLeftBitmapSize = rxLeftBitmap->getSize();
59     geometry::IntegerSize2D aCenterBitmapSize;
60     if (rxRepeatableCenterBitmap.is())
61         aCenterBitmapSize = rxRepeatableCenterBitmap->getSize();
62     geometry::IntegerSize2D aRightBitmapSize;
63     if (rxRightBitmap.is())
64         aRightBitmapSize = rxRightBitmap->getSize();
65 
66     // Prepare painting.
67     rendering::ViewState aViewState (
68         geometry::AffineMatrix2D(1,0,0, 0,1,0),
69         NULL);
70 
71     rendering::RenderState aRenderState (
72         geometry::AffineMatrix2D(1,0,0, 0,1,0),
73         NULL,
74         Sequence<double>(4),
75         rendering::CompositeOperation::SOURCE);
76 
77     // Paint the left bitmap once.
78     if (rxLeftBitmap.is())
79     {
80         const awt::Rectangle aLeftBoundingBox (
81             rBoundingBox.X,
82             rBoundingBox.Y,
83             ::std::min(aLeftBitmapSize.Width, rBoundingBox.Width),
84             rBoundingBox.Height);
85         aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
86             PresenterGeometryHelper::CreatePolygon(
87                 PresenterGeometryHelper::Intersection(rRepaintBox, aLeftBoundingBox),
88                 rxCanvas->getDevice()));
89         aRenderState.AffineTransform.m02 = aLeftBoundingBox.X;
90         aRenderState.AffineTransform.m12
91             = aLeftBoundingBox.Y + (aLeftBoundingBox.Height - aLeftBitmapSize.Height) / 2;
92         rxCanvas->drawBitmap(rxLeftBitmap, aViewState, aRenderState);
93     }
94 
95     // Paint the right bitmap once.
96     if (rxRightBitmap.is())
97     {
98         const awt::Rectangle aRightBoundingBox (
99             rBoundingBox.X + rBoundingBox.Width - aRightBitmapSize.Width,
100             rBoundingBox.Y,
101             ::std::min(aRightBitmapSize.Width, rBoundingBox.Width),
102             rBoundingBox.Height);
103         aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
104             PresenterGeometryHelper::CreatePolygon(
105                 PresenterGeometryHelper::Intersection(rRepaintBox, aRightBoundingBox),
106                 rxCanvas->getDevice()));
107         aRenderState.AffineTransform.m02
108             = aRightBoundingBox.X + aRightBoundingBox.Width - aRightBitmapSize.Width;
109         aRenderState.AffineTransform.m12
110             = aRightBoundingBox.Y + (aRightBoundingBox.Height - aRightBitmapSize.Height) / 2;
111         rxCanvas->drawBitmap(rxRightBitmap, aViewState, aRenderState);
112     }
113 
114     // Paint the center bitmap to fill the remaining space.
115     if (rxRepeatableCenterBitmap.is())
116     {
117         const awt::Rectangle aCenterBoundingBox (
118             rBoundingBox.X + aLeftBitmapSize.Width,
119             rBoundingBox.Y,
120             rBoundingBox.Width - aLeftBitmapSize.Width - aRightBitmapSize.Width,
121             rBoundingBox.Height);
122         if (aCenterBoundingBox.Width > 0)
123         {
124             aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
125                 PresenterGeometryHelper::CreatePolygon(
126                     PresenterGeometryHelper::Intersection(rRepaintBox, aCenterBoundingBox),
127                     rxCanvas->getDevice()));
128             sal_Int32 nX (aCenterBoundingBox.X);
129             const sal_Int32 nRight (aCenterBoundingBox.X + aCenterBoundingBox.Width - 1);
130             aRenderState.AffineTransform.m12
131                 = aCenterBoundingBox.Y + (aCenterBoundingBox.Height-aCenterBitmapSize.Height) / 2;
132             while(nX <= nRight)
133             {
134                 aRenderState.AffineTransform.m02 = nX;
135                 rxCanvas->drawBitmap(rxRepeatableCenterBitmap, aViewState, aRenderState);
136                 nX += aCenterBitmapSize.Width;
137             }
138         }
139     }
140 }
141 
142 
143 
144 
PaintVerticalBitmapComposite(const css::uno::Reference<css::rendering::XCanvas> & rxCanvas,const css::awt::Rectangle & rRepaintBox,const css::awt::Rectangle & rBoundingBox,const css::uno::Reference<css::rendering::XBitmap> & rxTopBitmap,const css::uno::Reference<css::rendering::XBitmap> & rxRepeatableCenterBitmap,const css::uno::Reference<css::rendering::XBitmap> & rxBottomBitmap)145 void PresenterUIPainter::PaintVerticalBitmapComposite (
146     const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
147     const css::awt::Rectangle& rRepaintBox,
148     const css::awt::Rectangle& rBoundingBox,
149     const css::uno::Reference<css::rendering::XBitmap>& rxTopBitmap,
150     const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap,
151     const css::uno::Reference<css::rendering::XBitmap>& rxBottomBitmap)
152 {
153     if (PresenterGeometryHelper::AreRectanglesDisjoint(rRepaintBox, rBoundingBox))
154     {
155         // The bounding box lies completely outside the repaint area.
156         // Nothing has to be repainted.
157         return;
158     }
159 
160     // Get bitmap sizes.
161     geometry::IntegerSize2D aTopBitmapSize;
162     if (rxTopBitmap.is())
163         aTopBitmapSize = rxTopBitmap->getSize();
164     geometry::IntegerSize2D aCenterBitmapSize;
165     if (rxRepeatableCenterBitmap.is())
166         aCenterBitmapSize = rxRepeatableCenterBitmap->getSize();
167     geometry::IntegerSize2D aBottomBitmapSize;
168     if (rxBottomBitmap.is())
169         aBottomBitmapSize = rxBottomBitmap->getSize();
170 
171     // Prepare painting.
172     rendering::ViewState aViewState (
173         geometry::AffineMatrix2D(1,0,0, 0,1,0),
174         NULL);
175 
176     rendering::RenderState aRenderState (
177         geometry::AffineMatrix2D(1,0,0, 0,1,0),
178         NULL,
179         Sequence<double>(4),
180         rendering::CompositeOperation::SOURCE);
181 
182     // Paint the top bitmap once.
183     if (rxTopBitmap.is())
184     {
185         const awt::Rectangle aTopBoundingBox (
186             rBoundingBox.X,
187             rBoundingBox.Y,
188             rBoundingBox.Width,
189             ::std::min(aTopBitmapSize.Height, rBoundingBox.Height));
190         aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
191             PresenterGeometryHelper::CreatePolygon(
192                 PresenterGeometryHelper::Intersection(rRepaintBox, aTopBoundingBox),
193                 rxCanvas->getDevice()));
194         aRenderState.AffineTransform.m02
195             = aTopBoundingBox.X + (aTopBoundingBox.Width - aTopBitmapSize.Width) / 2;
196         aRenderState.AffineTransform.m12 = aTopBoundingBox.Y;
197         rxCanvas->drawBitmap(rxTopBitmap, aViewState, aRenderState);
198     }
199 
200     // Paint the bottom bitmap once.
201     if (rxBottomBitmap.is())
202     {
203         const sal_Int32 nBBoxHeight (::std::min(aBottomBitmapSize.Height, rBoundingBox.Height));
204         const awt::Rectangle aBottomBoundingBox (
205             rBoundingBox.X,
206             rBoundingBox.Y  + rBoundingBox.Height - nBBoxHeight,
207             rBoundingBox.Width,
208             nBBoxHeight);
209         aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
210             PresenterGeometryHelper::CreatePolygon(
211                 PresenterGeometryHelper::Intersection(rRepaintBox, aBottomBoundingBox),
212                 rxCanvas->getDevice()));
213         aRenderState.AffineTransform.m02
214             = aBottomBoundingBox.X + (aBottomBoundingBox.Width - aBottomBitmapSize.Width) / 2;
215         aRenderState.AffineTransform.m12
216             = aBottomBoundingBox.Y + aBottomBoundingBox.Height - aBottomBitmapSize.Height;
217         rxCanvas->drawBitmap(rxBottomBitmap, aViewState, aRenderState);
218     }
219 
220     // Paint the center bitmap to fill the remaining space.
221     if (rxRepeatableCenterBitmap.is())
222     {
223         const awt::Rectangle aCenterBoundingBox (
224             rBoundingBox.X,
225             rBoundingBox.Y + aTopBitmapSize.Height,
226             rBoundingBox.Width,
227             rBoundingBox.Height - aTopBitmapSize.Height - aBottomBitmapSize.Height);
228         if (aCenterBoundingBox.Height > 0)
229         {
230             aViewState.Clip = Reference<rendering::XPolyPolygon2D>(
231                 PresenterGeometryHelper::CreatePolygon(
232                     PresenterGeometryHelper::Intersection(rRepaintBox, aCenterBoundingBox),
233                     rxCanvas->getDevice()));
234             sal_Int32 nY (aCenterBoundingBox.Y);
235             const sal_Int32 nBottom (aCenterBoundingBox.Y + aCenterBoundingBox.Height - 1);
236             aRenderState.AffineTransform.m02
237                 = aCenterBoundingBox.X + (aCenterBoundingBox.Width-aCenterBitmapSize.Width) / 2;
238             while(nY <= nBottom)
239             {
240                 aRenderState.AffineTransform.m12 = nY;
241                 rxCanvas->drawBitmap(rxRepeatableCenterBitmap, aViewState, aRenderState);
242                 nY += aCenterBitmapSize.Height;
243             }
244         }
245     }
246 }
247 
248 
249 
250 
251 
252 } } // end of namespace sdext::presenter
253