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