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 "PresenterPaneBorderPainter.hxx" 32 #include "PresenterCanvasHelper.hxx" 33 #include "PresenterConfigurationAccess.hxx" 34 #include "PresenterGeometryHelper.hxx" 35 #include "PresenterTheme.hxx" 36 #include <com/sun/star/awt/FontDescriptor.hpp> 37 #include <com/sun/star/awt/Point.hpp> 38 #include <com/sun/star/awt/Rectangle.hpp> 39 #include <com/sun/star/awt/SimpleFontMetric.hpp> 40 #include <com/sun/star/awt/XFont.hpp> 41 #include <com/sun/star/drawing/XPresenterHelper.hpp> 42 #include <com/sun/star/graphic/XGraphic.hpp> 43 #include <com/sun/star/graphic/XGraphicRenderer.hpp> 44 #include <com/sun/star/rendering/CompositeOperation.hpp> 45 #include <com/sun/star/rendering/FillRule.hpp> 46 #include <com/sun/star/rendering/TextDirection.hpp> 47 #include <com/sun/star/rendering/XIntegerBitmap.hpp> 48 #include <com/sun/star/rendering/XSpriteCanvas.hpp> 49 #include <map> 50 #include <vector> 51 #include <boost/shared_ptr.hpp> 52 53 using namespace ::com::sun::star; 54 using namespace ::com::sun::star::uno; 55 using ::rtl::OUString; 56 57 #define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) 58 59 namespace sdext { namespace presenter { 60 61 namespace { 62 class BorderSize 63 { 64 public: 65 BorderSize (void); 66 BorderSize (const BorderSize& rBorderSize); 67 BorderSize& operator= (const BorderSize& rBoderSize); 68 sal_Int32 mnLeft; 69 sal_Int32 mnTop; 70 sal_Int32 mnRight; 71 sal_Int32 mnBottom; 72 }; 73 74 class RendererPaneStyle 75 { 76 public: 77 RendererPaneStyle ( 78 const ::boost::shared_ptr<PresenterTheme>& rpTheme, 79 const OUString& rsStyleName); 80 81 awt::Rectangle AddBorder ( 82 const awt::Rectangle& rBox, 83 drawing::framework::BorderType eBorderType) const; 84 awt::Rectangle RemoveBorder ( 85 const awt::Rectangle& rBox, 86 drawing::framework::BorderType eBorderType) const; 87 const Reference<rendering::XCanvasFont> GetFont ( 88 const Reference<rendering::XCanvas>& rxCanvas) const; 89 90 SharedBitmapDescriptor mpTopLeft; 91 SharedBitmapDescriptor mpTop; 92 SharedBitmapDescriptor mpTopRight; 93 SharedBitmapDescriptor mpLeft; 94 SharedBitmapDescriptor mpRight; 95 SharedBitmapDescriptor mpBottomLeft; 96 SharedBitmapDescriptor mpBottom; 97 SharedBitmapDescriptor mpBottomRight; 98 SharedBitmapDescriptor mpBottomCallout; 99 SharedBitmapDescriptor mpBackground; 100 SharedBitmapDescriptor mpEmpty; 101 PresenterTheme::SharedFontDescriptor mpFont; 102 sal_Int32 mnFontXOffset; 103 sal_Int32 mnFontYOffset; 104 enum Anchor { AnchorLeft, AnchorRight, AnchorCenter } meFontAnchor; 105 BorderSize maInnerBorderSize; 106 BorderSize maOuterBorderSize; 107 BorderSize maTotalBorderSize; 108 enum Side { Left, Top, Right, Bottom }; 109 private: 110 void UpdateBorderSizes (void); 111 SharedBitmapDescriptor GetBitmap( 112 const ::boost::shared_ptr<PresenterTheme>& rpTheme, 113 const OUString& rsStyleName, 114 const OUString& rsBitmapName); 115 }; 116 } 117 118 119 120 class PresenterPaneBorderPainter::Renderer 121 { 122 public: 123 Renderer ( 124 const Reference<XComponentContext>& rxContext, 125 const ::boost::shared_ptr<PresenterTheme>& rpTheme); 126 ~Renderer (void); 127 128 void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas); 129 void PaintBorder ( 130 const OUString& rsTitle, 131 const awt::Rectangle& rBBox, 132 const awt::Rectangle& rUpdateBox, 133 const OUString& rsPaneURL); 134 void PaintTitle ( 135 const OUString& rsTitle, 136 const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, 137 const awt::Rectangle& rUpdateBox, 138 const awt::Rectangle& rOuterBox, 139 const awt::Rectangle& rInnerBox, 140 const bool bPaintBackground); 141 void SetupClipping ( 142 const awt::Rectangle& rUpdateBox, 143 const awt::Rectangle& rOuterBox, 144 const OUString& rsPaneStyleName); 145 ::boost::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL); 146 void SetCalloutAnchor ( 147 const awt::Point& rCalloutAnchor); 148 149 private: 150 ::boost::shared_ptr<PresenterTheme> mpTheme; 151 typedef ::std::map<OUString, ::boost::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer; 152 RendererPaneStyleContainer maRendererPaneStyles; 153 Reference<rendering::XCanvas> mxCanvas; 154 Reference<drawing::XPresenterHelper> mxPresenterHelper; 155 css::rendering::ViewState maViewState; 156 Reference<rendering::XPolyPolygon2D> mxViewStateClip; 157 bool mbHasCallout; 158 awt::Point maCalloutAnchor; 159 160 void PaintBitmap( 161 const awt::Rectangle& rBox, 162 const awt::Rectangle& rUpdateBox, 163 const sal_Int32 nXPosition, 164 const sal_Int32 nYPosition, 165 const sal_Int32 nStartOffset, 166 const sal_Int32 nEndOffset, 167 const bool bExpand, 168 const SharedBitmapDescriptor& rpBitmap, 169 const SharedBitmapDescriptor& rpBackgroundBitmap); 170 }; 171 172 173 174 175 // ===== PresenterPaneBorderPainter =========================================== 176 177 PresenterPaneBorderPainter::PresenterPaneBorderPainter ( 178 const Reference<XComponentContext>& rxContext) 179 : PresenterPaneBorderPainterInterfaceBase(m_aMutex), 180 mxContext(rxContext), 181 mpTheme(), 182 mpRenderer() 183 { 184 } 185 186 187 188 189 PresenterPaneBorderPainter::~PresenterPaneBorderPainter (void) 190 { 191 } 192 193 194 195 196 //----- XPaneBorderPainter ---------------------------------------------------- 197 198 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder ( 199 const rtl::OUString& rsPaneBorderStyleName, 200 const css::awt::Rectangle& rRectangle, 201 drawing::framework::BorderType eBorderType) 202 throw(css::uno::RuntimeException) 203 { 204 ThrowIfDisposed(); 205 206 ProvideTheme(); 207 208 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType); 209 } 210 211 212 213 214 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder ( 215 const rtl::OUString& rsPaneBorderStyleName, 216 const css::awt::Rectangle& rRectangle, 217 drawing::framework::BorderType eBorderType) 218 throw(css::uno::RuntimeException) 219 { 220 ThrowIfDisposed(); 221 222 ProvideTheme(); 223 224 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType); 225 } 226 227 228 229 230 void SAL_CALL PresenterPaneBorderPainter::paintBorder ( 231 const rtl::OUString& rsPaneBorderStyleName, 232 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 233 const css::awt::Rectangle& rOuterBorderRectangle, 234 const css::awt::Rectangle& rRepaintArea, 235 const rtl::OUString& rsTitle) 236 throw(css::uno::RuntimeException) 237 { 238 ThrowIfDisposed(); 239 240 // Early reject paints completely outside the repaint area. 241 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width 242 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height 243 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X 244 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) 245 { 246 return; 247 } 248 ProvideTheme(rxCanvas); 249 250 if (mpRenderer.get() != NULL) 251 { 252 mpRenderer->SetCanvas(rxCanvas); 253 mpRenderer->SetupClipping( 254 rRepaintArea, 255 rOuterBorderRectangle, 256 rsPaneBorderStyleName); 257 mpRenderer->PaintBorder( 258 rsTitle, 259 rOuterBorderRectangle, 260 rRepaintArea, 261 rsPaneBorderStyleName); 262 } 263 } 264 265 266 267 268 void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout ( 269 const rtl::OUString& rsPaneBorderStyleName, 270 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, 271 const css::awt::Rectangle& rOuterBorderRectangle, 272 const css::awt::Rectangle& rRepaintArea, 273 const rtl::OUString& rsTitle, 274 const css::awt::Point& rCalloutAnchor) 275 throw(css::uno::RuntimeException) 276 { 277 ThrowIfDisposed(); 278 279 // Early reject paints completely outside the repaint area. 280 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width 281 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height 282 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X 283 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) 284 { 285 return; 286 } 287 ProvideTheme(rxCanvas); 288 289 if (mpRenderer.get() != NULL) 290 { 291 mpRenderer->SetCanvas(rxCanvas); 292 mpRenderer->SetupClipping( 293 rRepaintArea, 294 rOuterBorderRectangle, 295 rsPaneBorderStyleName); 296 mpRenderer->SetCalloutAnchor(rCalloutAnchor); 297 mpRenderer->PaintBorder( 298 rsTitle, 299 rOuterBorderRectangle, 300 rRepaintArea, 301 rsPaneBorderStyleName); 302 } 303 } 304 305 306 307 308 awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset ( 309 const rtl::OUString& rsPaneBorderStyleName) 310 throw(css::uno::RuntimeException) 311 { 312 ThrowIfDisposed(); 313 ProvideTheme(); 314 if (mpRenderer.get() != NULL) 315 { 316 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle( 317 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName)); 318 if (pRendererPaneStyle.get() != NULL 319 && pRendererPaneStyle->mpBottomCallout.get() != NULL) 320 { 321 return awt::Point ( 322 0, 323 pRendererPaneStyle->mpBottomCallout->mnHeight 324 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot); 325 } 326 } 327 328 return awt::Point(0,0); 329 } 330 331 332 333 334 //----------------------------------------------------------------------------- 335 336 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas) 337 { 338 bool bModified (false); 339 340 if ( ! mxContext.is()) 341 return false; 342 343 if (mpTheme.get() != NULL) 344 { 345 // Check if the theme already has a canvas. 346 if ( ! mpTheme->HasCanvas()) 347 { 348 mpTheme->ProvideCanvas(rxCanvas); 349 bModified = true; 350 } 351 } 352 else 353 { 354 mpTheme.reset(new PresenterTheme(mxContext, OUString(), rxCanvas)); 355 bModified = true; 356 } 357 358 if (mpTheme.get() != NULL && bModified) 359 { 360 if (mpRenderer.get() == NULL) 361 mpRenderer.reset(new Renderer(mxContext, mpTheme)); 362 else 363 mpRenderer->SetCanvas(rxCanvas); 364 } 365 366 return bModified; 367 } 368 369 370 371 372 bool PresenterPaneBorderPainter::ProvideTheme (void) 373 { 374 if (mpTheme.get() == NULL) 375 { 376 // Create a theme without bitmaps (no canvas => no bitmaps). 377 return ProvideTheme(NULL); 378 } 379 else 380 { 381 // When there already is a theme then without a canvas we can not 382 // add anything new. 383 return false; 384 } 385 } 386 387 388 389 390 bool PresenterPaneBorderPainter::HasTheme (void) const 391 { 392 return mpTheme.get()!=NULL && mpRenderer.get()!=NULL; 393 } 394 395 396 397 398 void PresenterPaneBorderPainter::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme) 399 { 400 mpTheme = rpTheme; 401 if (mpRenderer.get() == NULL) 402 mpRenderer.reset(new Renderer(mxContext, mpTheme)); 403 } 404 405 406 407 408 awt::Rectangle PresenterPaneBorderPainter::AddBorder ( 409 const ::rtl::OUString& rsPaneURL, 410 const awt::Rectangle& rInnerBox, 411 const css::drawing::framework::BorderType eBorderType) const 412 { 413 if (mpRenderer.get() != NULL) 414 { 415 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); 416 if (pRendererPaneStyle.get() != NULL) 417 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType); 418 } 419 return rInnerBox; 420 } 421 422 423 424 425 awt::Rectangle PresenterPaneBorderPainter::RemoveBorder ( 426 const ::rtl::OUString& rsPaneURL, 427 const css::awt::Rectangle& rOuterBox, 428 const css::drawing::framework::BorderType eBorderType) const 429 { 430 if (mpRenderer.get() != NULL) 431 { 432 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); 433 if (pRendererPaneStyle.get() != NULL) 434 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType); 435 } 436 return rOuterBox; 437 } 438 439 440 441 442 void PresenterPaneBorderPainter::ThrowIfDisposed (void) const 443 throw (::com::sun::star::lang::DisposedException) 444 { 445 if (rBHelper.bDisposed || rBHelper.bInDispose) 446 { 447 throw lang::DisposedException ( 448 OUString(RTL_CONSTASCII_USTRINGPARAM( 449 "PresenterPaneBorderPainter object has already been disposed")), 450 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 451 } 452 } 453 454 455 456 457 //===== PresenterPaneBorderPainter::Renderer ===================================== 458 459 460 PresenterPaneBorderPainter::Renderer::Renderer ( 461 const Reference<XComponentContext>& rxContext, 462 const ::boost::shared_ptr<PresenterTheme>& rpTheme) 463 : mpTheme(rpTheme), 464 maRendererPaneStyles(), 465 mxCanvas(), 466 mxPresenterHelper(), 467 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), 468 mxViewStateClip(), 469 mbHasCallout(false), 470 maCalloutAnchor() 471 { 472 (void)rxContext; 473 474 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); 475 if (xFactory.is()) 476 { 477 mxPresenterHelper = Reference<drawing::XPresenterHelper>( 478 xFactory->createInstanceWithContext( 479 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"), 480 rxContext), 481 UNO_QUERY_THROW); 482 } 483 } 484 485 486 487 488 PresenterPaneBorderPainter::Renderer::~Renderer (void) 489 { 490 } 491 492 493 494 495 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas) 496 { 497 if (mxCanvas != rxCanvas) 498 { 499 mxCanvas = rxCanvas; 500 } 501 } 502 503 504 505 506 void PresenterPaneBorderPainter::Renderer::PaintBorder ( 507 const OUString& rsTitle, 508 const awt::Rectangle& rBBox, 509 const awt::Rectangle& rUpdateBox, 510 const OUString& rsPaneURL) 511 { 512 if ( ! mxCanvas.is()) 513 return; 514 515 // Create the outer and inner border of the, ahm, border. 516 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL)); 517 if (pStyle.get() == NULL) 518 return; 519 520 awt::Rectangle aOuterBox (rBBox); 521 awt::Rectangle aCenterBox ( 522 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER)); 523 awt::Rectangle aInnerBox ( 524 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); 525 526 // Prepare references for all used bitmaps. 527 SharedBitmapDescriptor pTop (pStyle->mpTop); 528 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft); 529 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight); 530 SharedBitmapDescriptor pLeft (pStyle->mpLeft); 531 SharedBitmapDescriptor pRight (pStyle->mpRight); 532 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft); 533 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight); 534 SharedBitmapDescriptor pBottom (pStyle->mpBottom); 535 SharedBitmapDescriptor pBackground (pStyle->mpBackground); 536 537 // Paint the sides. 538 PaintBitmap(aCenterBox, rUpdateBox, 0,-1, 539 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop, pBackground); 540 PaintBitmap(aCenterBox, rUpdateBox, -1,0, 541 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft, pBackground); 542 PaintBitmap(aCenterBox, rUpdateBox, +1,0, 543 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight, pBackground); 544 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is()) 545 { 546 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth); 547 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot 548 - (aCenterBox.X - aOuterBox.X)); 549 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X) 550 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X; 551 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width) 552 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width; 553 // Paint bottom callout. 554 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout, pBackground); 555 // Paint regular bottom bitmap left and right. 556 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, 557 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom, pBackground); 558 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, 559 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom, pBackground); 560 } 561 else 562 { 563 // Stretch the bottom bitmap over the full width. 564 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, 565 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom, pBackground); 566 } 567 568 // Paint the corners. 569 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft, pBackground); 570 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight, pBackground); 571 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft, pBackground); 572 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight, pBackground); 573 574 // Paint the title. 575 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox, false); 576 577 // In a double buffering environment request to make the changes visible. 578 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); 579 if (xSpriteCanvas.is()) 580 xSpriteCanvas->updateScreen(sal_False); 581 } 582 583 584 585 586 void PresenterPaneBorderPainter::Renderer::PaintTitle ( 587 const OUString& rsTitle, 588 const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, 589 const awt::Rectangle& rUpdateBox, 590 const awt::Rectangle& rOuterBox, 591 const awt::Rectangle& rInnerBox, 592 bool bPaintBackground) 593 { 594 if ( ! mxCanvas.is()) 595 return; 596 597 if (rsTitle.getLength() == 0) 598 return; 599 600 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas)); 601 if ( ! xFont.is()) 602 return; 603 604 rendering::StringContext aContext ( 605 rsTitle, 606 0, 607 rsTitle.getLength()); 608 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout( 609 aContext, 610 rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 611 0)); 612 if ( ! xLayout.is()) 613 return; 614 615 geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); 616 const double nTextHeight = aBox.Y2 - aBox.Y1; 617 const double nTextWidth = aBox.X2 - aBox.X1; 618 double nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; 619 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1; 620 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1; 621 if (nY >= rInnerBox.Y) 622 nY = rInnerBox.Y - 1; 623 switch (rpStyle->meFontAnchor) 624 { 625 default: 626 case RendererPaneStyle::AnchorLeft: 627 nX = rInnerBox.X; 628 break; 629 case RendererPaneStyle::AnchorRight: 630 nX = rInnerBox.X + rInnerBox.Width - nTextWidth; 631 break; 632 case RendererPaneStyle::AnchorCenter: 633 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; 634 break; 635 } 636 nX += rpStyle->mnFontXOffset; 637 nY += rpStyle->mnFontYOffset; 638 639 if (rUpdateBox.X >= nX+nTextWidth 640 || rUpdateBox.Y >= nY+nTextHeight 641 || rUpdateBox.X+rUpdateBox.Width <= nX 642 || rUpdateBox.Y+rUpdateBox.Height <= nY) 643 { 644 return; 645 } 646 647 rendering::RenderState aRenderState( 648 geometry::AffineMatrix2D(1,0,nX, 0,1,nY), 649 NULL, 650 Sequence<double>(4), 651 rendering::CompositeOperation::SOURCE); 652 653 if (bPaintBackground) 654 { 655 PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff)); 656 Sequence<Sequence<geometry::RealPoint2D> > aPolygons(1); 657 aPolygons[0] = Sequence<geometry::RealPoint2D>(4); 658 aPolygons[0][0] = geometry::RealPoint2D(0, -nTextHeight); 659 aPolygons[0][1] = geometry::RealPoint2D(0, 0); 660 aPolygons[0][2] = geometry::RealPoint2D(nTextWidth, 0); 661 aPolygons[0][3] = geometry::RealPoint2D(nTextWidth, -nTextHeight); 662 Reference<rendering::XPolyPolygon2D> xPolygon ( 663 mxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPolygons), UNO_QUERY); 664 if (xPolygon.is()) 665 xPolygon->setClosed(0, sal_True); 666 mxCanvas->fillPolyPolygon( 667 xPolygon, 668 maViewState, 669 aRenderState); 670 } 671 else 672 { 673 PresenterCanvasHelper::SetDeviceColor( 674 aRenderState, 675 rpStyle->mpFont->mnColor); 676 677 mxCanvas->drawText( 678 aContext, 679 xFont, 680 maViewState, 681 aRenderState, 682 rendering::TextDirection::WEAK_LEFT_TO_RIGHT); 683 } 684 } 685 686 687 688 ::boost::shared_ptr<RendererPaneStyle> 689 PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL) 690 { 691 OSL_ASSERT(mpTheme.get()!=NULL); 692 693 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL)); 694 if (iStyle == maRendererPaneStyles.end()) 695 { 696 OUString sPaneStyleName (OUString::createFromAscii("DefaultRendererPaneStyle")); 697 698 // Get pane layout name for resource URL. 699 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL)); 700 if (sStyleName.getLength() > 0) 701 sPaneStyleName = sStyleName; 702 703 // Create a new pane style object and initialize it with bitmaps. 704 ::boost::shared_ptr<RendererPaneStyle> pStyle ( 705 new RendererPaneStyle(mpTheme,sPaneStyleName)); 706 iStyle = maRendererPaneStyles.insert( 707 RendererPaneStyleContainer::value_type(rsResourceURL, pStyle)).first; 708 } 709 if (iStyle != maRendererPaneStyles.end()) 710 return iStyle->second; 711 else 712 return ::boost::shared_ptr<RendererPaneStyle>(); 713 } 714 715 716 717 718 void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor ( 719 const awt::Point& rCalloutAnchor) 720 { 721 mbHasCallout = true; 722 maCalloutAnchor = rCalloutAnchor; 723 } 724 725 726 727 728 void PresenterPaneBorderPainter::Renderer::PaintBitmap( 729 const awt::Rectangle& rBox, 730 const awt::Rectangle& rUpdateBox, 731 const sal_Int32 nXPosition, 732 const sal_Int32 nYPosition, 733 const sal_Int32 nStartOffset, 734 const sal_Int32 nEndOffset, 735 const bool bExpand, 736 const SharedBitmapDescriptor& rpBitmap, 737 const SharedBitmapDescriptor& rpBackgroundBitmap) 738 { 739 (void)rpBackgroundBitmap; 740 741 bool bUseCanvas (mxCanvas.is()); 742 if ( ! bUseCanvas) 743 return; 744 745 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0) 746 return; 747 748 Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY); 749 if ( ! xBitmap.is()) 750 return; 751 752 // Calculate position, and for side bitmaps, the size. 753 sal_Int32 nX = 0; 754 sal_Int32 nY = 0; 755 sal_Int32 nW = rpBitmap->mnWidth; 756 sal_Int32 nH = rpBitmap->mnHeight; 757 if (nXPosition < 0) 758 { 759 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset; 760 } 761 else if (nXPosition > 0) 762 { 763 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset; 764 } 765 else 766 { 767 nX = rBox.X + nStartOffset; 768 if (bExpand) 769 nW = rBox.Width - nStartOffset + nEndOffset; 770 } 771 772 if (nYPosition < 0) 773 { 774 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset; 775 } 776 else if (nYPosition > 0) 777 { 778 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset; 779 } 780 else 781 { 782 nY = rBox.Y + nStartOffset; 783 if (bExpand) 784 nH = rBox.Height - nStartOffset + nEndOffset; 785 } 786 787 // Do not paint when bitmap area does not intersect with update box. 788 if (nX >= rUpdateBox.X + rUpdateBox.Width 789 || nX+nW <= rUpdateBox.X 790 || nY >= rUpdateBox.Y + rUpdateBox.Height 791 || nY+nH <= rUpdateBox.Y) 792 { 793 return; 794 } 795 796 /* 797 Reference<rendering::XBitmap> xMaskedBitmap ( 798 PresenterBitmapHelper::FillMaskedWithColor ( 799 mxCanvas, 800 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), 801 rBitmap.mxMaskBitmap, 802 0x00ff0000, 803 rBackgroundBitmap.maReplacementColor)); 804 if (xMaskedBitmap.is()) 805 xBitmap = xMaskedBitmap; 806 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is()) 807 { 808 const static sal_Int32 nOutsideMaskColor (0x00ff0000); 809 Reference<rendering::XIntegerBitmap> xMask ( 810 mxPresenterHelper->createMask( 811 mxCanvas, 812 rBitmap.mxMaskBitmap, 813 nOutsideMaskColor, 814 false)); 815 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor( 816 mxCanvas, 817 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), 818 xMask, 819 rBackgroundBitmap.maReplacementColor); 820 } 821 */ 822 rendering::RenderState aRenderState ( 823 geometry::AffineMatrix2D( 824 double(nW)/rpBitmap->mnWidth, 0, nX, 825 0, double(nH)/rpBitmap->mnHeight, nY), 826 NULL, 827 Sequence<double>(4), 828 rendering::CompositeOperation::OVER); 829 830 if (xBitmap.is()) 831 mxCanvas->drawBitmap( 832 xBitmap, 833 maViewState, 834 aRenderState); 835 } 836 837 838 839 840 void PresenterPaneBorderPainter::Renderer::SetupClipping ( 841 const awt::Rectangle& rUpdateBox, 842 const awt::Rectangle& rOuterBox, 843 const OUString& rsPaneStyleName) 844 { 845 mxViewStateClip = NULL; 846 maViewState.Clip = NULL; 847 848 if ( ! mxCanvas.is()) 849 return; 850 851 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName)); 852 if (pStyle.get() == NULL) 853 { 854 mxViewStateClip = PresenterGeometryHelper::CreatePolygon( 855 rUpdateBox, 856 mxCanvas->getDevice()); 857 } 858 else 859 { 860 awt::Rectangle aInnerBox ( 861 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); 862 ::std::vector<awt::Rectangle> aRectangles; 863 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox)); 864 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox)); 865 mxViewStateClip = PresenterGeometryHelper::CreatePolygon( 866 aRectangles, 867 mxCanvas->getDevice()); 868 if (mxViewStateClip.is()) 869 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD); 870 } 871 maViewState.Clip = mxViewStateClip; 872 } 873 874 875 876 namespace { 877 878 //===== BorderSize ============================================================ 879 880 BorderSize::BorderSize (void) 881 : mnLeft(0), 882 mnTop(0), 883 mnRight(0), 884 mnBottom(0) 885 { 886 } 887 888 889 890 891 BorderSize::BorderSize (const BorderSize& rBorderSize) 892 : mnLeft(rBorderSize.mnLeft), 893 mnTop(rBorderSize.mnTop), 894 mnRight(rBorderSize.mnRight), 895 mnBottom(rBorderSize.mnBottom) 896 { 897 } 898 899 900 901 902 BorderSize& BorderSize::operator= (const BorderSize& rBorderSize) 903 { 904 if (&rBorderSize != this) 905 { 906 mnLeft = rBorderSize.mnLeft; 907 mnTop = rBorderSize.mnTop; 908 mnRight = rBorderSize.mnRight; 909 mnBottom = rBorderSize.mnBottom; 910 } 911 return *this; 912 } 913 914 915 916 917 //===== RendererPaneStyle ============================================================ 918 919 RendererPaneStyle::RendererPaneStyle ( 920 const ::boost::shared_ptr<PresenterTheme>& rpTheme, 921 const OUString& rsStyleName) 922 : mpTopLeft(), 923 mpTop(), 924 mpTopRight(), 925 mpLeft(), 926 mpRight(), 927 mpBottomLeft(), 928 mpBottom(), 929 mpBottomRight(), 930 mpBottomCallout(), 931 mpBackground(), 932 mpEmpty(new PresenterBitmapDescriptor()), 933 mpFont(), 934 mnFontXOffset(0), 935 mnFontYOffset(0), 936 meFontAnchor(AnchorCenter), 937 maInnerBorderSize(), 938 maOuterBorderSize(), 939 maTotalBorderSize() 940 { 941 if (rpTheme.get() != NULL) 942 { 943 mpTopLeft = GetBitmap(rpTheme, rsStyleName, A2S("TopLeft")); 944 mpTop = GetBitmap(rpTheme, rsStyleName, A2S("Top")); 945 mpTopRight = GetBitmap(rpTheme, rsStyleName, A2S("TopRight")); 946 mpLeft = GetBitmap(rpTheme, rsStyleName, A2S("Left")); 947 mpRight = GetBitmap(rpTheme, rsStyleName, A2S("Right")); 948 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, A2S("BottomLeft")); 949 mpBottom = GetBitmap(rpTheme, rsStyleName, A2S("Bottom")); 950 mpBottomRight = GetBitmap(rpTheme, rsStyleName, A2S("BottomRight")); 951 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, A2S("BottomCallout")); 952 mpBackground = GetBitmap(rpTheme, OUString(), A2S("Background")); 953 954 // Get font description. 955 mpFont = rpTheme->GetFont(rsStyleName); 956 957 OUString sAnchor (OUString::createFromAscii("Left")); 958 if (mpFont.get() != NULL) 959 { 960 sAnchor = mpFont->msAnchor; 961 mnFontXOffset = mpFont->mnXOffset; 962 mnFontYOffset = mpFont->mnYOffset; 963 } 964 965 if (sAnchor == OUString::createFromAscii("Left")) 966 meFontAnchor = AnchorLeft; 967 else if (sAnchor == OUString::createFromAscii("Right")) 968 meFontAnchor = AnchorRight; 969 else if (sAnchor == OUString::createFromAscii("Center")) 970 meFontAnchor = AnchorCenter; 971 else 972 meFontAnchor = AnchorCenter; 973 974 // Get border sizes. 975 try 976 { 977 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false)); 978 OSL_ASSERT(aInnerBorder.size()==4); 979 maInnerBorderSize.mnLeft = aInnerBorder[0]; 980 maInnerBorderSize.mnTop = aInnerBorder[1]; 981 maInnerBorderSize.mnRight = aInnerBorder[2]; 982 maInnerBorderSize.mnBottom = aInnerBorder[3]; 983 984 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true)); 985 OSL_ASSERT(aOuterBorder.size()==4); 986 maOuterBorderSize.mnLeft = aOuterBorder[0]; 987 maOuterBorderSize.mnTop = aOuterBorder[1]; 988 maOuterBorderSize.mnRight = aOuterBorder[2]; 989 maOuterBorderSize.mnBottom = aOuterBorder[3]; 990 } 991 catch(beans::UnknownPropertyException&) 992 { 993 OSL_ASSERT(false); 994 } 995 996 UpdateBorderSizes(); 997 } 998 } 999 1000 1001 1002 1003 1004 awt::Rectangle RendererPaneStyle::AddBorder ( 1005 const awt::Rectangle& rBox, 1006 const drawing::framework::BorderType eBorderType) const 1007 { 1008 const BorderSize* pBorderSize = NULL; 1009 switch (eBorderType) 1010 { 1011 case drawing::framework::BorderType_INNER_BORDER: 1012 pBorderSize = &maInnerBorderSize; 1013 break; 1014 case drawing::framework::BorderType_OUTER_BORDER: 1015 pBorderSize = &maOuterBorderSize; 1016 break; 1017 case drawing::framework::BorderType_TOTAL_BORDER: 1018 pBorderSize = &maTotalBorderSize; 1019 break; 1020 default: 1021 return rBox; 1022 } 1023 return awt::Rectangle ( 1024 rBox.X - pBorderSize->mnLeft, 1025 rBox.Y - pBorderSize->mnTop, 1026 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight, 1027 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom); 1028 } 1029 1030 1031 1032 1033 awt::Rectangle RendererPaneStyle::RemoveBorder ( 1034 const awt::Rectangle& rBox, 1035 const css::drawing::framework::BorderType eBorderType) const 1036 { 1037 const BorderSize* pBorderSize = NULL; 1038 switch (eBorderType) 1039 { 1040 case drawing::framework::BorderType_INNER_BORDER: 1041 pBorderSize = &maInnerBorderSize; 1042 break; 1043 case drawing::framework::BorderType_OUTER_BORDER: 1044 pBorderSize = &maOuterBorderSize; 1045 break; 1046 case drawing::framework::BorderType_TOTAL_BORDER: 1047 pBorderSize = &maTotalBorderSize; 1048 break; 1049 default: 1050 return rBox; 1051 } 1052 return awt::Rectangle ( 1053 rBox.X + pBorderSize->mnLeft, 1054 rBox.Y + pBorderSize->mnTop, 1055 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight, 1056 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom); 1057 } 1058 1059 1060 1061 1062 const Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont ( 1063 const Reference<rendering::XCanvas>& rxCanvas) const 1064 { 1065 if (mpFont.get() != NULL) 1066 mpFont->PrepareFont(rxCanvas); 1067 return mpFont->mxFont; 1068 } 1069 1070 1071 1072 1073 void RendererPaneStyle::UpdateBorderSizes (void) 1074 { 1075 maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft; 1076 maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop; 1077 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight; 1078 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom; 1079 } 1080 1081 1082 1083 1084 SharedBitmapDescriptor RendererPaneStyle::GetBitmap( 1085 const ::boost::shared_ptr<PresenterTheme>& rpTheme, 1086 const OUString& rsStyleName, 1087 const OUString& rsBitmapName) 1088 { 1089 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName)); 1090 if (pDescriptor.get() != NULL) 1091 return pDescriptor; 1092 else 1093 return mpEmpty; 1094 } 1095 1096 1097 1098 } // end of anonymous namespace 1099 1100 1101 } } // end of namespace ::sd::presenter 1102