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 "PresenterClock.hxx" 28 #include "PresenterComponent.hxx" 29 #include "PresenterConfigurationAccess.hxx" 30 #include "PresenterGeometryHelper.hxx" 31 #include <com/sun/star/awt/InvalidateStyle.hpp> 32 #include <com/sun/star/awt/MouseButton.hpp> 33 #include <com/sun/star/awt/Point.hpp> 34 #include <com/sun/star/awt/XWindowPeer.hpp> 35 #include <com/sun/star/container/XNameAccess.hpp> 36 #include <com/sun/star/deployment/XPackageInformationProvider.hpp> 37 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 38 #include <com/sun/star/drawing/framework/XConfigurationController.hpp> 39 #include <com/sun/star/rendering/CompositeOperation.hpp> 40 #include <com/sun/star/rendering/PathCapType.hpp> 41 #include <com/sun/star/rendering/TextDirection.hpp> 42 #include <com/sun/star/rendering/XCanvasFont.hpp> 43 #include <com/sun/star/rendering/XSpriteCanvas.hpp> 44 #include <com/sun/star/util/Color.hpp> 45 #include <osl/mutex.hxx> 46 #include <osl/time.h> 47 #include <rtl/ref.hxx> 48 #include <vos/timer.hxx> 49 #include <boost/bind.hpp> 50 #include <cmath> 51 52 using namespace ::com::sun::star; 53 using namespace ::com::sun::star::uno; 54 using namespace ::com::sun::star::drawing::framework; 55 using ::rtl::OUString; 56 57 namespace sdext { namespace presenter { 58 59 60 /** Wrapper around a library timer. 61 */ 62 class PresenterClock::Timer : public vos::OTimer 63 { 64 public: 65 explicit Timer (const ::rtl::Reference<PresenterClock>& rpClock); 66 virtual ~Timer (void); 67 68 void Stop (void); 69 70 protected: 71 virtual void SAL_CALL onShot (void); 72 73 private: 74 ::rtl::Reference<PresenterClock> mpClock; 75 }; 76 77 78 79 80 namespace { 81 bool GetDateTime (oslDateTime& rDateTime); 82 83 class BitmapDescriptor 84 { 85 public: 86 Reference<rendering::XBitmap> mxBitmap; 87 awt::Point maOffset; 88 Reference<rendering::XBitmap> mxScaledBitmap; 89 geometry::RealPoint2D maScaledOffset; 90 }; 91 } 92 93 94 95 96 class PresenterClock::Painter 97 { 98 public: 99 virtual void Paint ( 100 const Reference<rendering::XCanvas>& rxCanvas, 101 const rendering::ViewState& rViewState, 102 const rendering::RenderState& rRenderState, 103 const util::Color& rBackgroundColor, 104 const sal_Int32 nHour, 105 const sal_Int32 nMinute, 106 const sal_Int32 nSecond, 107 const bool bShowSeconds) = 0; 108 virtual void Resize (const awt::Size& rSize) = 0; 109 }; 110 111 112 113 114 namespace { 115 class AnalogDefaultPainter : public PresenterClock::Painter 116 { 117 public: 118 AnalogDefaultPainter (void); 119 virtual ~AnalogDefaultPainter (void) {} 120 virtual void Paint ( 121 const Reference<rendering::XCanvas>& rxCanvas, 122 const rendering::ViewState& rViewState, 123 const rendering::RenderState& rRenderState, 124 const util::Color& rBackgroundColor, 125 const sal_Int32 nHour, 126 const sal_Int32 nMinute, 127 const sal_Int32 nSecond, 128 const bool bShowSeconds); 129 virtual void Resize (const awt::Size& rSize); 130 private: 131 geometry::RealPoint2D maCenter; 132 double mnOuterRadius; 133 awt::Size maSize; 134 Reference<rendering::XBitmap> mxBitmap; 135 136 /** Relative length (with respect to radius) from center to the tip of 137 the hand. 138 */ 139 static const double mnRelativeHourHandLength; 140 /** Relative length (with respect to radius) from center to the 141 oposing end of the tip of the hand. 142 */ 143 static const double mnRelativeHourHandLength2; 144 static const double mnRelativeHourHandWidth; 145 static const double mnRelativeMinuteHandLength; 146 static const double mnRelativeMinuteHandLength2; 147 static const double mnRelativeMinuteHandWidth; 148 static const double mnRelativeSecondHandLength; 149 static const double mnRelativeSecondHandLength2; 150 static const double mnRelativeSecondHandWidth; 151 152 void PaintAngledLine ( 153 const double nAngle, 154 const double nInnerRadius, 155 const double nOuterRadius, 156 const double nStrokeWidth, 157 const Reference<rendering::XCanvas>& rxCanvas, 158 const rendering::ViewState& rViewState, 159 const rendering::RenderState& rRenderState); 160 }; 161 162 163 class AnalogBitmapPainter : public PresenterClock::Painter 164 { 165 public: 166 AnalogBitmapPainter( 167 const Reference<XComponentContext>& rxContext, 168 const OUString& rsThemeName); 169 virtual ~AnalogBitmapPainter (void) {} 170 virtual void Paint ( 171 const Reference<rendering::XCanvas>& rxCanvas, 172 const rendering::ViewState& rViewState, 173 const rendering::RenderState& rRenderState, 174 const util::Color& rBackgroundColor, 175 const sal_Int32 nHour, 176 const sal_Int32 nMinute, 177 const sal_Int32 nSecond, 178 const bool bShowSeconds); 179 virtual void Resize (const awt::Size& rSize); 180 private: 181 css::uno::Reference<css::uno::XComponentContext> mxComponentContext; 182 const OUString msThemeName; 183 bool mbThemeLoaded; 184 bool mbThemeLoadingFailed; 185 geometry::RealPoint2D maCenter; 186 double mnOuterRadius; 187 BitmapDescriptor maFace; 188 BitmapDescriptor maMinuteHand; 189 BitmapDescriptor maHourHand; 190 191 void PrepareBitmaps (const Reference<rendering::XCanvas>& rxCanvas); 192 Reference<container::XNameAccess> GetTheme ( 193 PresenterConfigurationAccess& rConfiguration); 194 bool ThemeNameComparator ( 195 const ::rtl::OUString& rsKey, 196 const Reference<container::XNameAccess>& rxCandidate, 197 const ::rtl::OUString& rsCurrentThemeName); 198 void LoadBitmaps ( 199 PresenterConfigurationAccess& rConfiguration, 200 const Reference<container::XNameAccess>& rxNameAccess, 201 const Reference<rendering::XCanvas>& rxCanvas); 202 void LoadBitmap ( 203 const OUString& rsKey, 204 const ::std::vector<Any>& rValues, 205 const OUString& rsBitmapPath, 206 const Reference<container::XNameAccess>& rxBitmapLoader); 207 void ScaleBitmaps (void); 208 }; 209 210 211 class DigitalDefaultPainter : public PresenterClock::Painter 212 { 213 public: 214 DigitalDefaultPainter ( 215 const ::rtl::Reference<PresenterController>& rpPresenterController, 216 const Reference<XResourceId>& rxViewId); 217 virtual ~DigitalDefaultPainter (void); 218 219 virtual void Paint ( 220 const Reference<rendering::XCanvas>& rxCanvas, 221 const rendering::ViewState& rViewState, 222 const rendering::RenderState& rRenderState, 223 const util::Color& rBackgroundColor, 224 const sal_Int32 nHour, 225 const sal_Int32 nMinute, 226 const sal_Int32 nSecond, 227 const bool bShowSeconds); 228 virtual void Resize (const awt::Size& rSize); 229 230 private: 231 ::rtl::Reference<PresenterController> mpPresenterController; 232 bool mbIs24HourFormat; 233 bool mbIsAdaptFontSize; 234 Reference<rendering::XCanvasFont> mxFont; 235 awt::Size maWindowSize; 236 OUString msViewURL; 237 238 void CreateFont ( 239 const Reference<rendering::XCanvas>& rxCanvas, 240 const bool bIsShowSeconds); 241 }; 242 243 244 } // end of anonymous namespace 245 246 247 248 249 //===== PresenterClock ================================================================= 250 251 ::rtl::Reference<PresenterClock> PresenterClock::Create ( 252 const Reference<XComponentContext>& rxContext, 253 const Reference<XResourceId>& rxViewId, 254 const Reference<frame::XController>& rxController, 255 const ::rtl::Reference<PresenterController>& rpPresenterController) 256 { 257 ::rtl::Reference<PresenterClock> pClock (new PresenterClock( 258 rxContext, 259 rxViewId, 260 rxController, 261 rpPresenterController)); 262 pClock->LateInit(); 263 return pClock; 264 } 265 266 267 268 269 PresenterClock::PresenterClock ( 270 const Reference<XComponentContext>& rxContext, 271 const Reference<XResourceId>& rxViewId, 272 const Reference<frame::XController>& rxController, 273 const ::rtl::Reference<PresenterController>& rpPresenterController) 274 : PresenterClockInterfaceBase(m_aMutex), 275 mxComponentContext(rxContext), 276 mxViewId(rxViewId), 277 mxWindow(), 278 mxCanvas(), 279 mxPane(), 280 mpPresenterController(rpPresenterController), 281 mbIsResizePending(true), 282 maViewState(), 283 maRenderState(), 284 mpTimer(), 285 mpClockPainter(), 286 mpClockPainter2(), 287 mnMode(1), 288 mnHour(-1), 289 mnMinute(-1), 290 mnSecond(-1), 291 mbIsShowSeconds(true) 292 { 293 SetMode(mnMode); 294 295 maViewState.AffineTransform = geometry::AffineMatrix2D(1,0,0, 0,1,0); 296 maRenderState.AffineTransform = geometry::AffineMatrix2D(1,0,0, 0,1,0); 297 maRenderState.DeviceColor = Sequence<double>(4); 298 PresenterCanvasHelper::SetDeviceColor(maRenderState, util::Color(0x00000000)); 299 300 try 301 { 302 303 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); 304 Reference<XConfigurationController> xCC (xCM->getConfigurationController(), UNO_QUERY_THROW); 305 mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); 306 307 mxWindow = mxPane->getWindow(); 308 if (mxWindow.is()) 309 { 310 mxWindow->addPaintListener(this); 311 mxWindow->addWindowListener(this); 312 mxWindow->addMouseListener(this); 313 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); 314 if (xPeer.is()) 315 xPeer->setBackground(util::Color(0xff000000)); 316 mxWindow->setVisible(sal_True); 317 } 318 319 Resize(); 320 } 321 catch (RuntimeException&) 322 { 323 disposing(); 324 throw; 325 } 326 } 327 328 329 330 331 PresenterClock::~PresenterClock (void) 332 { 333 } 334 335 336 337 338 void PresenterClock::LateInit (void) 339 { 340 mpTimer = new Timer(this); 341 } 342 343 344 345 346 void SAL_CALL PresenterClock::disposing (void) 347 { 348 // osl::MutexGuard aGuard (m_aMutex); 349 if (mpTimer != NULL) 350 { 351 mpTimer->Stop(); 352 } 353 if (mxWindow.is()) 354 { 355 mxWindow->removePaintListener(this); 356 mxWindow->removeWindowListener(this); 357 mxWindow->removeMouseListener(this); 358 mxWindow = NULL; 359 } 360 mxCanvas = NULL; 361 mxViewId = NULL; 362 } 363 364 365 366 367 void PresenterClock::UpdateTime (void) 368 { 369 // Get current time and check whether it is different from last time. 370 oslDateTime aDateTime; 371 if ( ! GetDateTime(aDateTime)) 372 return; 373 if (aDateTime.Hours != mnHour 374 || aDateTime.Minutes != mnMinute 375 || aDateTime.Seconds != mnSecond) 376 { 377 mnHour = aDateTime.Hours % 24; 378 mnMinute = aDateTime.Minutes % 60; 379 mnSecond = aDateTime.Seconds % 60; 380 381 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); 382 if (xPeer.is()) 383 xPeer->invalidate(awt::InvalidateStyle::NOERASE | 384 awt::InvalidateStyle::UPDATE); 385 } 386 } 387 388 389 390 391 //----- lang::XEventListener ------------------------------------------------- 392 393 void SAL_CALL PresenterClock::disposing (const lang::EventObject& rEventObject) 394 throw (RuntimeException) 395 { 396 // ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); 397 // osl::MutexGuard aGuard (m_aMutex); 398 399 if (rEventObject.Source == mxWindow) 400 { 401 mxWindow = NULL; 402 if (mpTimer != NULL) 403 mpTimer->Stop(); 404 } 405 } 406 407 408 409 410 //----- XPaintListener -------------------------------------------------------- 411 412 void SAL_CALL PresenterClock::windowPaint (const awt::PaintEvent& rEvent) 413 throw (RuntimeException) 414 { 415 (void)rEvent; 416 ThrowIfDisposed(); 417 ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); 418 Paint(rEvent.UpdateRect); 419 } 420 421 422 423 424 //----- XWindowListener ------------------------------------------------------- 425 426 void SAL_CALL PresenterClock::windowResized (const awt::WindowEvent& rEvent) 427 throw (RuntimeException) 428 { 429 (void)rEvent; 430 mbIsResizePending = true; 431 } 432 433 434 435 436 void SAL_CALL PresenterClock::windowMoved (const awt::WindowEvent& rEvent) 437 throw (RuntimeException) 438 { 439 (void)rEvent; 440 mbIsResizePending = true; 441 } 442 443 444 445 446 void SAL_CALL PresenterClock::windowShown (const lang::EventObject& rEvent) 447 throw (RuntimeException) 448 { 449 (void)rEvent; 450 mbIsResizePending = true; 451 } 452 453 454 455 456 void SAL_CALL PresenterClock::windowHidden (const lang::EventObject& rEvent) 457 throw (RuntimeException) 458 { 459 (void)rEvent; 460 } 461 462 463 464 465 //----- XMouseListener -------------------------------------------------------- 466 467 void SAL_CALL PresenterClock::mousePressed (const css::awt::MouseEvent& rEvent) 468 throw (css::uno::RuntimeException) 469 { 470 (void)rEvent; 471 if (rEvent.Buttons == awt::MouseButton::LEFT) 472 { 473 SetMode(mnMode+1); 474 } 475 } 476 477 478 479 480 void SAL_CALL PresenterClock::mouseReleased (const css::awt::MouseEvent& rEvent) 481 throw (css::uno::RuntimeException) 482 { 483 (void)rEvent; 484 } 485 486 487 488 489 void SAL_CALL PresenterClock::mouseEntered (const css::awt::MouseEvent& rEvent) 490 throw (css::uno::RuntimeException) 491 { 492 (void)rEvent; 493 } 494 495 496 497 498 void SAL_CALL PresenterClock::mouseExited (const css::awt::MouseEvent& rEvent) 499 throw (css::uno::RuntimeException) 500 { 501 (void)rEvent; 502 } 503 504 505 506 507 //----- XResourceId ----------------------------------------------------------- 508 509 Reference<XResourceId> SAL_CALL PresenterClock::getResourceId (void) 510 throw (RuntimeException) 511 { 512 return mxViewId; 513 } 514 515 516 517 518 sal_Bool SAL_CALL PresenterClock::isAnchorOnly (void) 519 throw (RuntimeException) 520 { 521 return false; 522 } 523 524 525 526 527 //----------------------------------------------------------------------------- 528 529 void PresenterClock::Resize (void) 530 { 531 if (mxPane.is()) 532 mxCanvas = Reference<rendering::XCanvas>(mxPane->getCanvas(), UNO_QUERY); 533 if (mxWindow.is() && mxCanvas.is()) 534 { 535 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 536 const awt::Size aWindowSize(aWindowBox.Width,aWindowBox.Height); 537 if (mpClockPainter.get() != NULL) 538 mpClockPainter->Resize(aWindowSize); 539 if (mpClockPainter2.get() != NULL) 540 mpClockPainter2->Resize(aWindowSize); 541 mbIsResizePending = false; 542 } 543 } 544 545 546 547 548 void PresenterClock::Paint (const awt::Rectangle& rUpdateBox) 549 { 550 if ( ! mxCanvas.is() && mxPane.is()) 551 mxCanvas = Reference<rendering::XCanvas>(mxPane->getCanvas(), UNO_QUERY); 552 if ( ! mxWindow.is() 553 || ! mxCanvas.is() 554 || ! mxCanvas->getDevice().is()) 555 { 556 return; 557 } 558 559 try 560 { 561 if (mbIsResizePending) 562 Resize(); 563 564 Reference<rendering::XPolyPolygon2D> xUpdatePolygon ( 565 PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); 566 567 Clear(xUpdatePolygon); 568 569 if (mpClockPainter.get() != NULL) 570 mpClockPainter->Paint(mxCanvas, 571 maViewState, 572 maRenderState, 573 mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL()), 574 mnHour, 575 mnMinute, 576 mnSecond, 577 mbIsShowSeconds); 578 579 if (mpClockPainter2.get() != NULL) 580 mpClockPainter2->Paint( 581 mxCanvas, 582 maViewState, 583 maRenderState, 584 mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL()), 585 mnHour, 586 mnMinute, 587 mnSecond, 588 mbIsShowSeconds); 589 } 590 catch (RuntimeException& e) 591 { 592 (void)e; 593 } 594 595 // Make the back buffer visible. 596 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); 597 if (xSpriteCanvas.is()) 598 xSpriteCanvas->updateScreen(sal_False); 599 } 600 601 602 603 604 void PresenterClock::Clear (const Reference<rendering::XPolyPolygon2D>& rxUpdatePolygon) 605 { 606 rendering::RenderState aRenderState = maRenderState; 607 const sal_Int32 nColor ( 608 mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL())); 609 aRenderState.DeviceColor[0] = ((nColor&0x00ff0000) >> 16) / 255.0; 610 aRenderState.DeviceColor[1] = ((nColor&0x0000ff00) >> 8) / 255.0; 611 aRenderState.DeviceColor[2] = ((nColor&0x000000ff) >> 0) / 255.0; 612 613 if (rxUpdatePolygon.is()) 614 mxCanvas->fillPolyPolygon( 615 rxUpdatePolygon, 616 maViewState, 617 aRenderState); 618 } 619 620 621 622 623 void PresenterClock::SetMode (const sal_Int32 nMode) 624 { 625 mnMode = nMode % 3; 626 627 switch (mnMode) 628 { 629 case 0: 630 mpClockPainter.reset( 631 new AnalogBitmapPainter( 632 mxComponentContext, 633 OUString::createFromAscii("ClockTheme"))); 634 mpClockPainter2.reset(); 635 break; 636 637 case 1: 638 mpClockPainter.reset(); 639 mpClockPainter2.reset(new AnalogDefaultPainter()); 640 break; 641 642 case 2: 643 mpClockPainter.reset(); 644 mpClockPainter2.reset(new DigitalDefaultPainter(mpPresenterController, mxViewId)); 645 break; 646 647 case 3: 648 mpClockPainter.reset( 649 new AnalogBitmapPainter( 650 mxComponentContext, 651 OUString::createFromAscii("ClockTheme"))); 652 mpClockPainter2.reset(new AnalogDefaultPainter()); 653 break; 654 } 655 Resize(); 656 } 657 658 659 660 661 void PresenterClock::ThrowIfDisposed (void) 662 throw (::com::sun::star::lang::DisposedException) 663 { 664 if (rBHelper.bDisposed || rBHelper.bInDispose) 665 { 666 throw lang::DisposedException ( 667 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 668 "PresenterClock object has already been disposed")), 669 static_cast<uno::XWeak*>(this)); 670 } 671 } 672 673 674 675 676 //===== Timer ================================================================= 677 678 PresenterClock::Timer::Timer (const ::rtl::Reference<PresenterClock>& rpClock) 679 : OTimer(vos::TTimeValue(10), vos::TTimeValue(100/*ms*/)), 680 mpClock(rpClock) 681 { 682 acquire(); 683 start(); 684 } 685 686 687 688 689 PresenterClock::Timer::~Timer (void) 690 { 691 if (mpClock.is()) 692 Stop(); 693 } 694 695 696 697 698 void PresenterClock::Timer::Stop (void) 699 { 700 mpClock = NULL; 701 stop(); 702 release(); 703 } 704 705 706 707 708 void SAL_CALL PresenterClock::Timer::onShot (void) 709 { 710 if (mpClock.get() != NULL) 711 mpClock->UpdateTime(); 712 } 713 714 715 716 namespace { 717 718 //============================================================================= 719 720 bool GetDateTime (oslDateTime& rDateTime) 721 { 722 TimeValue aSystemTime; 723 TimeValue aLocalTime; 724 if (osl_getSystemTime(&aSystemTime)) 725 if (osl_getLocalTimeFromSystemTime(&aSystemTime, &aLocalTime)) 726 if (osl_getDateTimeFromTimeValue(&aLocalTime, &rDateTime)) 727 return true; 728 return false; 729 } 730 731 732 733 734 //===== AnalogDefaultPainter ================================================== 735 736 const double AnalogDefaultPainter::mnRelativeHourHandLength = 0.65; 737 const double AnalogDefaultPainter::mnRelativeHourHandLength2 (-0.1); 738 const double AnalogDefaultPainter::mnRelativeHourHandWidth (0.055); 739 const double AnalogDefaultPainter::mnRelativeMinuteHandLength (-0.2); 740 const double AnalogDefaultPainter::mnRelativeMinuteHandLength2 (0.85); 741 const double AnalogDefaultPainter::mnRelativeMinuteHandWidth (0.025); 742 const double AnalogDefaultPainter::mnRelativeSecondHandLength (-0.25); 743 const double AnalogDefaultPainter::mnRelativeSecondHandLength2 (0.95); 744 const double AnalogDefaultPainter::mnRelativeSecondHandWidth (0.015); 745 746 AnalogDefaultPainter::AnalogDefaultPainter (void) 747 : maCenter(0,0), 748 mnOuterRadius(0), 749 maSize(0,0), 750 mxBitmap() 751 { 752 } 753 754 755 756 757 void AnalogDefaultPainter::Paint ( 758 const Reference<rendering::XCanvas>& rxCanvas, 759 const rendering::ViewState& rViewState, 760 const rendering::RenderState& rRenderState, 761 const util::Color& rBackgroundColor, 762 const sal_Int32 nHour, 763 const sal_Int32 nMinute, 764 const sal_Int32 nSecond, 765 const bool bShowSeconds) 766 { 767 double nInnerRadius (0); 768 double nStrokeWidth (0.1); 769 const double nClockSize (2*mnOuterRadius); 770 771 // Some antialiasing is created by painting into a bitmap twice the 772 // screen size and then scaling it down. 773 const sal_Int32 nSuperSampleFactor (2); 774 if ( ! mxBitmap.is()) 775 { 776 mxBitmap = (rxCanvas->getDevice()->createCompatibleBitmap( 777 geometry::IntegerSize2D( 778 maSize.Width*nSuperSampleFactor, 779 maSize.Height*nSuperSampleFactor))); 780 } 781 Reference<rendering::XCanvas> xBitmapCanvas (mxBitmap, UNO_QUERY); 782 rendering::RenderState aRenderState(rRenderState); 783 aRenderState.AffineTransform.m00 = nSuperSampleFactor; 784 aRenderState.AffineTransform.m11 = nSuperSampleFactor; 785 786 // Clear the background. 787 aRenderState.DeviceColor[0] = ((rBackgroundColor&0x00ff0000) >> 16) / 255.0; 788 aRenderState.DeviceColor[1] = ((rBackgroundColor&0x0000ff00) >> 8) / 255.0; 789 aRenderState.DeviceColor[2] = ((rBackgroundColor&0x000000ff) >> 0) / 255.0; 790 Reference<rendering::XPolyPolygon2D> xPolygon ( 791 PresenterGeometryHelper::CreatePolygon( 792 awt::Rectangle(0,0,maSize.Width,maSize.Height), 793 xBitmapCanvas->getDevice())); 794 if (xPolygon.is()) 795 xBitmapCanvas->fillPolyPolygon(xPolygon, rViewState, aRenderState); 796 797 // Clock face and clock hands are painted in black. 798 aRenderState.DeviceColor[0] = 0; 799 aRenderState.DeviceColor[1] = 0; 800 aRenderState.DeviceColor[2] = 0; 801 802 // Paint the clock face. 803 for (sal_Int32 nHourMark=0; nHourMark<12; ++nHourMark) 804 { 805 if (nHourMark%3 == 0) 806 { 807 nInnerRadius = 0.7 * mnOuterRadius; 808 nStrokeWidth = 0.05 * nClockSize; 809 } 810 else 811 { 812 nInnerRadius = 0.8 * mnOuterRadius; 813 nStrokeWidth = 0.03 * nClockSize; 814 } 815 816 const double nAngle (nHourMark * 2 * M_PI / 12); 817 PaintAngledLine(nAngle, nInnerRadius, mnOuterRadius, nStrokeWidth, 818 xBitmapCanvas, rViewState, aRenderState); 819 } 820 821 // Paint the hour hand. 822 const double nHoursAngle (((nHour%12)+nMinute/60.0) * 2 * M_PI / 12); 823 PaintAngledLine(nHoursAngle, 824 mnRelativeHourHandLength2*mnOuterRadius, 825 mnRelativeHourHandLength*mnOuterRadius, 826 mnRelativeHourHandWidth*nClockSize, 827 xBitmapCanvas, rViewState, aRenderState); 828 829 // Paint the minute hand. 830 const double nMinutesAngle ((nMinute+nSecond/60.0) * 2 * M_PI / 60); 831 PaintAngledLine(nMinutesAngle, 832 mnRelativeMinuteHandLength2*mnOuterRadius, 833 mnRelativeMinuteHandLength*mnOuterRadius, 834 mnRelativeMinuteHandWidth*nClockSize, 835 xBitmapCanvas, rViewState, aRenderState); 836 837 // Optionally paint the second hand. 838 if (bShowSeconds) 839 { 840 const double nSecondsAngle (nSecond * 2 * M_PI / 60); 841 PaintAngledLine(nSecondsAngle, 842 mnRelativeSecondHandLength2*mnOuterRadius, 843 mnRelativeSecondHandLength*mnOuterRadius, 844 mnRelativeSecondHandWidth*nClockSize, 845 xBitmapCanvas, rViewState, aRenderState); 846 } 847 848 aRenderState.AffineTransform.m00 = 1.0 / nSuperSampleFactor; 849 aRenderState.AffineTransform.m11 = 1.0 / nSuperSampleFactor; 850 rxCanvas->drawBitmap(mxBitmap,rViewState,aRenderState); 851 } 852 853 854 855 856 void AnalogDefaultPainter::PaintAngledLine ( 857 const double nAngle, 858 const double nInnerRadius, 859 const double nOuterRadius, 860 const double nStrokeWidth, 861 const Reference<rendering::XCanvas>& rxCanvas, 862 const rendering::ViewState& rViewState, 863 const rendering::RenderState& rRenderState) 864 { 865 if ( ! rxCanvas.is()) 866 return; 867 868 rendering::StrokeAttributes aStrokeAttributes; 869 aStrokeAttributes.StrokeWidth = nStrokeWidth; 870 aStrokeAttributes.StartCapType = rendering::PathCapType::SQUARE; 871 aStrokeAttributes.EndCapType = rendering::PathCapType::SQUARE; 872 aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT; 873 aStrokeAttributes.EndCapType = rendering::PathCapType::BUTT; 874 const double nCos (cos(nAngle - M_PI/2)); 875 const double nSin (sin(nAngle - M_PI/2)); 876 877 Sequence<Sequence<geometry::RealPoint2D> > aPoints(1); 878 aPoints[0] = Sequence<geometry::RealPoint2D>(2); 879 aPoints[0][0] = geometry::RealPoint2D( 880 maCenter.X + nInnerRadius*nCos + 0.5, 881 maCenter.Y + nInnerRadius*nSin + 0.5); 882 aPoints[0][1] = geometry::RealPoint2D( 883 maCenter.X + nOuterRadius*nCos + 0.5, 884 maCenter.Y + nOuterRadius*nSin + 0.5); 885 886 Reference<rendering::XPolyPolygon2D> xLine ( 887 rxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPoints), 888 UNO_QUERY); 889 if ( ! xLine.is()) 890 return; 891 rxCanvas->strokePolyPolygon( 892 xLine, 893 rViewState, 894 rRenderState, 895 aStrokeAttributes); 896 } 897 898 899 900 901 void AnalogDefaultPainter::Resize (const awt::Size& rWindowSize) 902 { 903 maSize = rWindowSize; 904 maCenter = geometry::RealPoint2D(rWindowSize.Width/2.0, rWindowSize.Height/2.0); 905 mnOuterRadius = ::std::min(rWindowSize.Width, rWindowSize.Height) / 2.0 - 2; 906 mxBitmap = NULL; 907 } 908 909 910 911 912 //===== AnalogBitmapPainter =================================================== 913 914 AnalogBitmapPainter::AnalogBitmapPainter ( 915 const Reference<XComponentContext>& rxContext, 916 const OUString& rsThemeName) 917 : mxComponentContext(rxContext), 918 msThemeName(rsThemeName), 919 mbThemeLoaded(false), 920 mbThemeLoadingFailed(false), 921 maCenter(), 922 mnOuterRadius(), 923 maFace(), 924 maMinuteHand(), 925 maHourHand() 926 { 927 } 928 929 930 931 932 void AnalogBitmapPainter::Paint ( 933 const Reference<rendering::XCanvas>& rxCanvas, 934 const rendering::ViewState& rViewState, 935 const rendering::RenderState& rRenderState, 936 const util::Color& rBackgroundColor, 937 const sal_Int32 nHour, 938 const sal_Int32 nMinute, 939 const sal_Int32 nSecond, 940 const bool bShowSeconds) 941 { 942 (void)rBackgroundColor; 943 (void)nSecond; 944 (void)bShowSeconds; 945 946 if ( ! rxCanvas.is()) 947 return; 948 949 rendering::RenderState aRenderState = rRenderState; 950 951 try 952 { 953 PrepareBitmaps(rxCanvas); 954 955 if (maFace.mxScaledBitmap.is()) 956 { 957 aRenderState.AffineTransform = geometry::AffineMatrix2D( 958 1,0, maCenter.X - maFace.maScaledOffset.X, 959 0,1, maCenter.Y - maFace.maScaledOffset.Y); 960 rxCanvas->drawBitmap(maFace.mxScaledBitmap, rViewState, aRenderState); 961 } 962 963 if (maMinuteHand.mxScaledBitmap.is()) 964 { 965 const double nMinuteAngle ((nMinute+nSecond/60.0) * 2.0 * M_PI / 60.0); 966 const double nCos (cos(nMinuteAngle - M_PI/2)); 967 const double nSin (sin(nMinuteAngle - M_PI/2)); 968 aRenderState.AffineTransform = geometry::AffineMatrix2D( 969 nCos, 970 -nSin, 971 -maMinuteHand.maScaledOffset.X*nCos 972 + maMinuteHand.maScaledOffset.Y*nSin+maCenter.X, 973 nSin, 974 nCos, 975 -maMinuteHand.maScaledOffset.X*nSin 976 - maMinuteHand.maScaledOffset.Y*nCos+maCenter.Y); 977 rxCanvas->drawBitmap(maMinuteHand.mxScaledBitmap, rViewState, aRenderState); 978 } 979 980 if (maHourHand.mxScaledBitmap.is()) 981 { 982 const double nHoursAngle ((nHour%12+nMinute/60.0) * 2.0 * M_PI / 12.0); 983 const double nCos (cos(nHoursAngle - M_PI/2)); 984 const double nSin (sin(nHoursAngle - M_PI/2)); 985 aRenderState.AffineTransform = geometry::AffineMatrix2D( 986 nCos, 987 -nSin, 988 -maHourHand.maScaledOffset.X*nCos+maHourHand.maScaledOffset.Y*nSin+maCenter.X, 989 nSin, 990 nCos, 991 -maHourHand.maScaledOffset.X*nSin-maHourHand.maScaledOffset.Y*nCos+maCenter.Y); 992 rxCanvas->drawBitmap(maHourHand.mxScaledBitmap, rViewState, aRenderState); 993 } 994 } 995 catch(beans::UnknownPropertyException&) 996 { 997 } 998 catch(RuntimeException&) 999 { 1000 } 1001 } 1002 1003 1004 1005 1006 void AnalogBitmapPainter::Resize (const awt::Size& rWindowSize) 1007 { 1008 maCenter = geometry::RealPoint2D(rWindowSize.Width/2.0, rWindowSize.Height/2.0); 1009 mnOuterRadius = ::std::min(rWindowSize.Width, rWindowSize.Height) / 2.0 - 2; 1010 maFace.mxScaledBitmap = NULL; 1011 maHourHand.mxScaledBitmap = NULL; 1012 maMinuteHand.mxScaledBitmap = NULL; 1013 } 1014 1015 1016 1017 1018 void AnalogBitmapPainter::PrepareBitmaps (const Reference<rendering::XCanvas>& rxCanvas) 1019 { 1020 if (mbThemeLoadingFailed) 1021 { 1022 // Theme loading has failed previously. Do not try a second time. 1023 return; 1024 } 1025 if ( ! rxCanvas.is()) 1026 { 1027 // No canvas => bitmaps can neither be loaded, transformed into the 1028 // right format, nor can they be painted. 1029 return; 1030 } 1031 1032 if ( ! mbThemeLoaded) 1033 { 1034 mbThemeLoaded = true; 1035 1036 // Get access to the clock bitmaps in the configuration. 1037 PresenterConfigurationAccess aConfiguration ( 1038 mxComponentContext, 1039 OUString::createFromAscii("org.openoffice.Office.extension.PresenterScreen"), 1040 PresenterConfigurationAccess::READ_ONLY); 1041 1042 Reference<container::XNameAccess> xTheme (GetTheme(aConfiguration)); 1043 if (xTheme.is()) 1044 LoadBitmaps(aConfiguration, xTheme, rxCanvas); 1045 else 1046 mbThemeLoadingFailed = true; 1047 } 1048 1049 ScaleBitmaps(); 1050 } 1051 1052 1053 1054 1055 Reference<container::XNameAccess> AnalogBitmapPainter::GetTheme ( 1056 PresenterConfigurationAccess& rConfiguration) 1057 { 1058 Reference<container::XNameAccess> xTheme; 1059 1060 // Get root of clock themes. 1061 Reference<container::XHierarchicalNameAccess> xClock ( 1062 rConfiguration.GetConfigurationNode( 1063 OUString::createFromAscii("PresenterScreenSettings/AnalogBitmapClock")), 1064 UNO_QUERY); 1065 1066 // Determine the name of the theme to use. 1067 OUString sCurrentThemeName (OUString::createFromAscii("DefaultTheme")); 1068 rConfiguration.GetConfigurationNode( 1069 xClock, 1070 OUString::createFromAscii("CurrentTheme")) >>= sCurrentThemeName; 1071 1072 // Load the clock theme. 1073 Reference<container::XNameAccess> xThemes ( 1074 rConfiguration.GetConfigurationNode( 1075 xClock, 1076 OUString::createFromAscii("Themes")), 1077 UNO_QUERY); 1078 if (xThemes.is()) 1079 { 1080 xTheme = Reference<container::XNameAccess>( 1081 PresenterConfigurationAccess::Find( 1082 xThemes, 1083 ::boost::bind(&AnalogBitmapPainter::ThemeNameComparator, 1084 this, _1, _2, sCurrentThemeName)), 1085 UNO_QUERY); 1086 } 1087 1088 return xTheme; 1089 } 1090 1091 1092 1093 1094 bool AnalogBitmapPainter::ThemeNameComparator ( 1095 const OUString& rsKey, 1096 const Reference<container::XNameAccess>& rxCandidate, 1097 const OUString& rsCurrentThemeName) 1098 { 1099 (void)rsKey; 1100 if (rxCandidate.is()) 1101 { 1102 OUString sThemeName; 1103 if (rxCandidate->getByName(OUString::createFromAscii("ThemeName")) >>= sThemeName) 1104 { 1105 return sThemeName == rsCurrentThemeName; 1106 } 1107 } 1108 return false; 1109 } 1110 1111 1112 1113 1114 1115 void AnalogBitmapPainter::LoadBitmaps ( 1116 PresenterConfigurationAccess& rConfiguration, 1117 const Reference<container::XNameAccess>& rxClockTheme, 1118 const Reference<rendering::XCanvas>& rxCanvas) 1119 { 1120 (void)rConfiguration; 1121 1122 // Get base path to bitmaps. 1123 Reference<deployment::XPackageInformationProvider> xInformationProvider ( 1124 mxComponentContext->getValueByName(OUString::createFromAscii( 1125 "/singletons/com.sun.star.deployment.PackageInformationProvider")), 1126 UNO_QUERY); 1127 OUString sLocation; 1128 if (xInformationProvider.is()) 1129 sLocation = xInformationProvider->getPackageLocation(gsExtensionIdentifier); 1130 sLocation += OUString::createFromAscii("/"); 1131 1132 // Create the bitmap loader. 1133 Reference<lang::XMultiComponentFactory> xFactory ( 1134 mxComponentContext->getServiceManager(), UNO_QUERY); 1135 if ( ! xFactory.is()) 1136 return; 1137 Sequence<Any> aArguments(1); 1138 aArguments[0] <<= rxCanvas; 1139 Reference<container::XNameAccess> xBitmapLoader( 1140 xFactory->createInstanceWithArgumentsAndContext( 1141 OUString::createFromAscii("com.sun.star.drawing.PresenterWorkaroundService"), 1142 aArguments, 1143 mxComponentContext), 1144 UNO_QUERY); 1145 if ( ! xBitmapLoader.is()) 1146 return; 1147 1148 1149 // Iterate over all entries in the bitmap list and load the bitmaps. 1150 Reference<container::XNameAccess> xBitmaps ( 1151 rxClockTheme->getByName(OUString::createFromAscii("Bitmaps")), 1152 UNO_QUERY); 1153 ::std::vector<rtl::OUString> aBitmapProperties (3); 1154 aBitmapProperties[0] = OUString::createFromAscii("FileName"); 1155 aBitmapProperties[1] = OUString::createFromAscii("XOffset"); 1156 aBitmapProperties[2] = OUString::createFromAscii("YOffset"); 1157 PresenterConfigurationAccess::ForAll( 1158 xBitmaps, 1159 aBitmapProperties, 1160 ::boost::bind(&AnalogBitmapPainter::LoadBitmap, 1161 this, 1162 _1, 1163 _2, 1164 sLocation, 1165 xBitmapLoader)); 1166 } 1167 1168 1169 1170 1171 void AnalogBitmapPainter::LoadBitmap ( 1172 const OUString& rsKey, 1173 const ::std::vector<Any>& rValues, 1174 const OUString& rsBitmapPath, 1175 const Reference<container::XNameAccess>& rxBitmapLoader) 1176 { 1177 if (rValues.size() == 3) 1178 { 1179 BitmapDescriptor* pDescriptor = NULL; 1180 if (rsKey == OUString::createFromAscii("Face")) 1181 pDescriptor = &maFace; 1182 else if (rsKey == OUString::createFromAscii("HourHand")) 1183 pDescriptor = &maHourHand; 1184 else if (rsKey == OUString::createFromAscii("MinuteHand")) 1185 pDescriptor = &maMinuteHand; 1186 1187 if (pDescriptor == NULL) 1188 return; 1189 1190 OUString sFileName; 1191 if ( ! (rValues[0] >>= sFileName)) 1192 return; 1193 1194 rValues[1] >>= pDescriptor->maOffset.X; 1195 rValues[2] >>= pDescriptor->maOffset.Y; 1196 1197 pDescriptor->mxBitmap = Reference<rendering::XBitmap>( 1198 rxBitmapLoader->getByName(rsBitmapPath+sFileName), UNO_QUERY); 1199 1200 if ( ! pDescriptor->mxBitmap.is()) 1201 mbThemeLoadingFailed = true; 1202 } 1203 } 1204 1205 1206 1207 1208 void AnalogBitmapPainter::ScaleBitmaps (void) 1209 { 1210 if (mbThemeLoadingFailed) 1211 return; 1212 if ( ! maFace.mxBitmap.is()) 1213 return; 1214 1215 const geometry::IntegerSize2D aFaceSize (maFace.mxBitmap->getSize()); 1216 const sal_Int32 nSize = std::max(aFaceSize.Width, aFaceSize.Height); 1217 const double nScale = mnOuterRadius*2 / nSize; 1218 1219 BitmapDescriptor* aDescriptors[3] = { &maFace, &maHourHand, &maMinuteHand }; 1220 for (int nIndex=0; nIndex<3; ++nIndex) 1221 { 1222 BitmapDescriptor& rDescriptor (*aDescriptors[nIndex]); 1223 if ( ! rDescriptor.mxScaledBitmap.is() && rDescriptor.mxBitmap.is()) 1224 { 1225 const geometry::IntegerSize2D aBitmapSize (rDescriptor.mxBitmap->getSize()); 1226 rDescriptor.mxScaledBitmap = rDescriptor.mxBitmap->getScaledBitmap( 1227 geometry::RealSize2D(aBitmapSize.Width*nScale, aBitmapSize.Height*nScale), 1228 sal_False); 1229 rDescriptor.maScaledOffset = geometry::RealPoint2D( 1230 rDescriptor.maOffset.X * nScale, 1231 rDescriptor.maOffset.Y * nScale); 1232 } 1233 } 1234 } 1235 1236 1237 1238 1239 //===== DigitalDefaultPainter ================================================= 1240 1241 DigitalDefaultPainter::DigitalDefaultPainter ( 1242 const ::rtl::Reference<PresenterController>& rpPresenterController, 1243 const Reference<XResourceId>& rxViewId) 1244 : mpPresenterController(rpPresenterController), 1245 mbIs24HourFormat(false), 1246 mbIsAdaptFontSize(true), 1247 mxFont(), 1248 maWindowSize(0,0), 1249 msViewURL(rxViewId.is() ? rxViewId->getResourceURL() : OUString()) 1250 { 1251 } 1252 1253 1254 1255 1256 DigitalDefaultPainter::~DigitalDefaultPainter (void) 1257 { 1258 } 1259 1260 1261 1262 1263 void DigitalDefaultPainter::Paint ( 1264 const Reference<rendering::XCanvas>& rxCanvas, 1265 const rendering::ViewState& rViewState, 1266 const rendering::RenderState& rRenderState, 1267 const util::Color& rBackgroundColor, 1268 const sal_Int32 nHour, 1269 const sal_Int32 nMinute, 1270 const sal_Int32 nSecond, 1271 const bool bIsShowSeconds) 1272 { 1273 (void)rBackgroundColor; 1274 (void)rRenderState; 1275 1276 if ( ! mxFont.is()) 1277 CreateFont(rxCanvas,bIsShowSeconds); 1278 if ( ! mxFont.is()) 1279 return; 1280 1281 OUString sText; 1282 1283 if (mbIs24HourFormat) 1284 sText = OUString::valueOf(nHour); 1285 else 1286 { 1287 sText = OUString::valueOf(nHour>12 ? nHour-12 : nHour); 1288 } 1289 sText += OUString::createFromAscii(":"); 1290 const OUString sMinutes (OUString::valueOf(nMinute)); 1291 switch (sMinutes.getLength()) 1292 { 1293 case 1 : 1294 sText += OUString::createFromAscii("0") + sMinutes; 1295 break; 1296 case 2: 1297 sText += sMinutes; 1298 break; 1299 1300 default: 1301 return; 1302 } 1303 if (bIsShowSeconds) 1304 { 1305 sText += OUString::createFromAscii(":"); 1306 const OUString sSeconds (OUString::valueOf(nSecond)); 1307 switch (sSeconds.getLength()) 1308 { 1309 case 1 : 1310 sText += OUString::createFromAscii("0") + sSeconds; 1311 break; 1312 case 2: 1313 sText += sSeconds; 1314 break; 1315 1316 default: 1317 return; 1318 } 1319 } 1320 1321 rendering::StringContext aContext ( 1322 sText, 1323 0, 1324 sText.getLength()); 1325 Reference<rendering::XTextLayout> xLayout (mxFont->createTextLayout( 1326 aContext, 1327 rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 1328 0)); 1329 if ( ! xLayout.is()) 1330 return; 1331 geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); 1332 1333 1334 rendering::RenderState aRenderState( 1335 geometry::AffineMatrix2D(1,0,0, 0,1,0), 1336 NULL, 1337 Sequence<double>(4), 1338 rendering::CompositeOperation::SOURCE); 1339 1340 util::Color aFontColor (mpPresenterController->GetViewFontColor(msViewURL)); 1341 PresenterCanvasHelper::SetDeviceColor(aRenderState, aFontColor); 1342 aRenderState.AffineTransform.m02 1343 = (maWindowSize.Width - (aBox.X2-aBox.X1+1)) / 2 - aBox.X1; 1344 aRenderState.AffineTransform.m12 1345 = (maWindowSize.Height - (aBox.Y2-aBox.Y1+1)) / 2 - aBox.Y1; 1346 rxCanvas->drawText( 1347 aContext, 1348 mxFont, 1349 rViewState, 1350 aRenderState, 1351 rendering::TextDirection::WEAK_LEFT_TO_RIGHT); 1352 } 1353 1354 1355 1356 1357 void DigitalDefaultPainter::Resize (const awt::Size& rSize) 1358 { 1359 if (maWindowSize.Width != rSize.Width || maWindowSize.Height != rSize.Height) 1360 { 1361 maWindowSize = rSize; 1362 if (mbIsAdaptFontSize) 1363 mxFont = NULL; 1364 } 1365 } 1366 1367 1368 1369 1370 void DigitalDefaultPainter::CreateFont ( 1371 const Reference<rendering::XCanvas>& rxCanvas, 1372 const bool bIsShowSeconds) 1373 { 1374 if (rxCanvas.is() 1375 && rxCanvas->getDevice().is() 1376 && maWindowSize.Width>0 1377 && maWindowSize.Height>0) 1378 { 1379 // Create a time template for determinging the right font size. 1380 // Assume that 0 is the widest digit or that all digits have the 1381 // same width. 1382 OUString sTimeTemplate; 1383 // For the case that not all digits have the same width, create 1384 // different templates for 12 and 24 hour mode. 1385 if (mbIs24HourFormat) 1386 sTimeTemplate = OUString::createFromAscii("20"); 1387 else 1388 sTimeTemplate = OUString::createFromAscii("10"); 1389 if (bIsShowSeconds) 1390 sTimeTemplate += OUString::createFromAscii(":00:00"); 1391 else 1392 sTimeTemplate += OUString::createFromAscii(":00"); 1393 1394 rendering::StringContext aContext ( 1395 sTimeTemplate, 1396 0, 1397 sTimeTemplate.getLength()); 1398 1399 // When the font size is adapted to the window size (as large as 1400 // possible without overlapping) then that is done in a four step 1401 // process: 1402 // 1. Create a font in a default size, e.g. 10pt. 1403 // 2. Determine a scale factor from enlarging the text bounding box 1404 // to maximal size inside the window. 1405 // 3. Create a new font by scaling the default size with the factor 1406 // calculated in step 2. 1407 // 4. Text may be rendered differently in different sizes. 1408 // Therefore repeat step 2 and 3 once. More iterations may lead to 1409 // even better results but probably not to visible differences. 1410 rendering::FontRequest aFontRequest (mpPresenterController->GetViewFontRequest(msViewURL)); 1411 // TODO: use font from view style from configuration 1412 aFontRequest.CellSize = 10; 1413 1414 for (sal_Int32 nLoop=0; nLoop<3; ++nLoop) 1415 { 1416 mxFont = rxCanvas->createFont( 1417 aFontRequest, 1418 Sequence<beans::PropertyValue>(), 1419 geometry::Matrix2D(1,0,0,1)); 1420 if (mxFont.is()) 1421 { 1422 Reference<rendering::XTextLayout> xLayout (mxFont->createTextLayout( 1423 aContext, 1424 rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 1425 0)); 1426 1427 if ( ! xLayout.is()) 1428 break; 1429 1430 geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); 1431 if (aBox.X2<=aBox.X1 || aBox.Y2<=aBox.Y1) 1432 break; 1433 const double nHorizontalFactor = maWindowSize.Width / (aBox.X2-aBox.X1+1); 1434 const double nVerticalFactor = maWindowSize.Height / (aBox.Y2-aBox.Y1+1); 1435 aFontRequest.CellSize *= ::std::min(nHorizontalFactor,nVerticalFactor); 1436 } 1437 } 1438 } 1439 } 1440 1441 1442 } // end of anonymous namespace 1443 1444 1445 } } // end of namespace ::sdext::presenter 1446