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_sdext.hxx" 30 31 #include "PresenterCanvasHelper.hxx" 32 33 #include "PresenterController.hxx" 34 #include "PresenterGeometryHelper.hxx" 35 #include <com/sun/star/rendering/CompositeOperation.hpp> 36 #include <com/sun/star/rendering/TextDirection.hpp> 37 #include <com/sun/star/rendering/TexturingMode.hpp> 38 39 using namespace ::com::sun::star; 40 using namespace ::com::sun::star::uno; 41 42 namespace sdext { namespace presenter { 43 44 PresenterCanvasHelper::PresenterCanvasHelper (void) 45 : maDefaultViewState( 46 geometry::AffineMatrix2D(1,0,0, 0,1,0), 47 NULL), 48 maDefaultRenderState( 49 geometry::AffineMatrix2D(1,0,0, 0,1,0), 50 NULL, 51 Sequence<double>(4), 52 rendering::CompositeOperation::SOURCE) 53 { 54 } 55 56 57 58 59 PresenterCanvasHelper::~PresenterCanvasHelper (void) 60 { 61 } 62 63 64 65 66 void PresenterCanvasHelper::Paint ( 67 const SharedBitmapDescriptor& rpBitmap, 68 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 69 const css::awt::Rectangle& rRepaintBox, 70 const css::awt::Rectangle& rOuterBoundingBox, 71 const css::awt::Rectangle& rContentBoundingBox) const 72 { 73 PaintRectangle(rpBitmap,rxCanvas,rRepaintBox,rOuterBoundingBox,rContentBoundingBox, 74 maDefaultViewState, maDefaultRenderState); 75 } 76 77 78 79 80 void PresenterCanvasHelper::PaintRectangle ( 81 const SharedBitmapDescriptor& rpBitmap, 82 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 83 const css::awt::Rectangle& rRepaintBox, 84 const css::awt::Rectangle& rOuterBoundingBox, 85 const css::awt::Rectangle& rContentBoundingBox, 86 const css::rendering::ViewState& rDefaultViewState, 87 const css::rendering::RenderState& rDefaultRenderState) 88 { 89 if (rpBitmap.get() == NULL) 90 return; 91 92 if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) 93 return; 94 95 // Create a clip polypolygon that has the content box as hole. 96 ::std::vector<awt::Rectangle> aRectangles; 97 aRectangles.reserve(2); 98 aRectangles.push_back( 99 PresenterGeometryHelper::Intersection(rRepaintBox, rOuterBoundingBox)); 100 if (rContentBoundingBox.Width > 0 && rContentBoundingBox.Height > 0) 101 aRectangles.push_back( 102 PresenterGeometryHelper::Intersection(rRepaintBox, rContentBoundingBox)); 103 Reference<rendering::XPolyPolygon2D> xPolyPolygon ( 104 PresenterGeometryHelper::CreatePolygon( 105 aRectangles, 106 rxCanvas->getDevice())); 107 if ( ! xPolyPolygon.is()) 108 return; 109 xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD); 110 111 if (rpBitmap->GetNormalBitmap().is()) 112 { 113 if (rpBitmap->meHorizontalTexturingMode == PresenterBitmapDescriptor::Repeat 114 || rpBitmap->meVerticalTexturingMode == PresenterBitmapDescriptor::Repeat) 115 { 116 PaintTiledBitmap( 117 Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), 118 rxCanvas, 119 rRepaintBox, 120 xPolyPolygon, 121 rContentBoundingBox, 122 rDefaultViewState, 123 rDefaultRenderState); 124 } 125 else 126 { 127 PaintBitmap( 128 Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), 129 awt::Point(rOuterBoundingBox.X, rOuterBoundingBox.Y), 130 rxCanvas, 131 rRepaintBox, 132 xPolyPolygon, 133 rDefaultViewState, 134 rDefaultRenderState); 135 } 136 } 137 else 138 { 139 PaintColor( 140 rpBitmap->maReplacementColor, 141 rxCanvas, 142 rRepaintBox, 143 xPolyPolygon, 144 rDefaultViewState, 145 rDefaultRenderState); 146 } 147 } 148 149 150 151 152 void PresenterCanvasHelper::PaintTiledBitmap ( 153 const css::uno::Reference<css::rendering::XBitmap>& rxTexture, 154 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 155 const css::awt::Rectangle& rRepaintBox, 156 const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, 157 const css::awt::Rectangle& rHole, 158 const css::rendering::ViewState& rDefaultViewState, 159 const css::rendering::RenderState& rDefaultRenderState) 160 { 161 if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) 162 return; 163 164 if ( ! rxTexture.is()) 165 return; 166 167 if ( ! rxPolygon.is()) 168 return; 169 170 rendering::ViewState aViewState (rDefaultViewState); 171 aViewState.Clip = rxPolygon; 172 173 // Create a local render state at which the location of the bitmap is 174 // set. 175 rendering::RenderState aRenderState (rDefaultRenderState); 176 177 178 // Tile the bitmap over the repaint box. 179 const geometry::IntegerSize2D aBitmapSize (rxTexture->getSize()); 180 const sal_Int32 nLeft = (rRepaintBox.X / aBitmapSize.Width) * aBitmapSize.Width; 181 const sal_Int32 nTop = (rRepaintBox.Y / aBitmapSize.Height) * aBitmapSize.Height; 182 const sal_Int32 nRight = ((rRepaintBox.X + rRepaintBox.Width - 1 + aBitmapSize.Width - 1) 183 / aBitmapSize.Width) * aBitmapSize.Width; 184 const sal_Int32 nBottom = ((rRepaintBox.Y + rRepaintBox.Height - 1 + aBitmapSize.Height - 1) 185 / aBitmapSize.Height) * aBitmapSize.Height; 186 187 for (sal_Int32 nY=nTop; nY<=nBottom; nY+=aBitmapSize.Height) 188 for (sal_Int32 nX=nLeft; nX<=nRight; nX+=aBitmapSize.Width) 189 { 190 if (PresenterGeometryHelper::IsInside( 191 awt::Rectangle(nX,nY,aBitmapSize.Width,aBitmapSize.Height), 192 rHole)) 193 { 194 continue; 195 } 196 aRenderState.AffineTransform.m02 = nX; 197 aRenderState.AffineTransform.m12 = nY; 198 rxCanvas->drawBitmap( 199 rxTexture, 200 aViewState, 201 aRenderState); 202 } 203 } 204 205 206 207 208 void PresenterCanvasHelper::PaintBitmap ( 209 const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, 210 const awt::Point& rLocation, 211 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 212 const css::awt::Rectangle& rRepaintBox, 213 const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, 214 const css::rendering::ViewState& rDefaultViewState, 215 const css::rendering::RenderState& rDefaultRenderState) 216 { 217 if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) 218 return; 219 220 if ( ! rxBitmap.is()) 221 return; 222 223 if ( ! rxPolygon.is()) 224 return; 225 226 // Set the repaint box as clip rectangle at the view state. 227 rendering::ViewState aViewState (rDefaultViewState); 228 aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); 229 230 231 // Setup the rendering state so that the bitmap is painted top left in 232 // the polygon bounding box. 233 rendering::RenderState aRenderState (rDefaultRenderState); 234 aRenderState.AffineTransform = geometry::AffineMatrix2D(1,0, rLocation.X, 0,1,rLocation.Y); 235 aRenderState.Clip = rxPolygon; 236 237 rxCanvas->drawBitmap( 238 rxBitmap, 239 aViewState, 240 aRenderState); 241 } 242 243 244 245 246 void PresenterCanvasHelper::PaintColor ( 247 const css::util::Color nColor, 248 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 249 const css::awt::Rectangle& rRepaintBox, 250 const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, 251 const css::rendering::ViewState& rDefaultViewState, 252 const css::rendering::RenderState& rDefaultRenderState) 253 { 254 if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) 255 return; 256 257 if ( ! rxPolygon.is()) 258 return; 259 260 // Set the repaint box as clip rectangle at the view state. 261 rendering::ViewState aViewState (rDefaultViewState); 262 aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); 263 264 265 // Setup the rendering state to use the given color. 266 rendering::RenderState aRenderState (rDefaultRenderState); 267 SetDeviceColor(aRenderState, nColor); 268 269 rxCanvas->fillPolyPolygon( 270 rxPolygon, 271 aViewState, 272 aRenderState); 273 } 274 275 276 277 278 void PresenterCanvasHelper::SetDeviceColor( 279 rendering::RenderState& rRenderState, 280 const util::Color aColor) 281 { 282 // Other component counts then 4 (RGBA) are not accepted (anymore). 283 284 OSL_ASSERT(rRenderState.DeviceColor.getLength() == 4); 285 if (rRenderState.DeviceColor.getLength() == 4) 286 { 287 rRenderState.DeviceColor[0] = ((aColor >> 16) & 0x0ff) / 255.0; 288 rRenderState.DeviceColor[1] = ((aColor >> 8) & 0x0ff) / 255.0; 289 rRenderState.DeviceColor[2] = ((aColor >> 0) & 0x0ff) / 255.0; 290 rRenderState.DeviceColor[3] = 1.0 - ((aColor >> 24) & 0x0ff) / 255.0; 291 } 292 } 293 294 295 296 297 css::geometry::RealRectangle2D PresenterCanvasHelper::GetTextBoundingBox ( 298 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 299 const ::rtl::OUString& rsText, 300 const sal_Int8 nTextDirection) 301 { 302 if (rxFont.is() && rsText.getLength() > 0) 303 { 304 rendering::StringContext aContext (rsText, 0, rsText.getLength()); 305 Reference<rendering::XTextLayout> xLayout ( 306 rxFont->createTextLayout(aContext, nTextDirection, 0)); 307 return xLayout->queryTextBounds(); 308 } 309 else 310 { 311 return geometry::RealRectangle2D(0,0,0,0); 312 } 313 } 314 315 316 317 318 css::geometry::RealSize2D PresenterCanvasHelper::GetTextSize ( 319 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 320 const ::rtl::OUString& rsText, 321 const sal_Int8 nTextDirection) 322 { 323 const geometry::RealRectangle2D aTextBBox (GetTextBoundingBox(rxFont, rsText, nTextDirection)); 324 return css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); 325 } 326 327 328 } } // end of namespace sdext::presenter 329