LibreOffice Module sd (master) 1
PresenterPaneBorderPainter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
23#include "PresenterTheme.hxx"
24#include <com/sun/star/awt/Point.hpp>
25#include <com/sun/star/awt/Rectangle.hpp>
26#include <com/sun/star/drawing/XPresenterHelper.hpp>
27#include <com/sun/star/rendering/CompositeOperation.hpp>
28#include <com/sun/star/rendering/FillRule.hpp>
29#include <com/sun/star/rendering/TextDirection.hpp>
30#include <com/sun/star/rendering/XSpriteCanvas.hpp>
31#include <map>
32#include <memory>
33#include <utility>
34#include <vector>
35
36using namespace ::com::sun::star;
37using namespace ::com::sun::star::uno;
38
39namespace sdext::presenter {
40
41namespace {
42 class BorderSize
43 {
44 public:
45 BorderSize();
46 sal_Int32 mnLeft;
47 sal_Int32 mnTop;
48 sal_Int32 mnRight;
49 sal_Int32 mnBottom;
50 };
51
52 class RendererPaneStyle
53 {
54 public:
55 RendererPaneStyle (
56 const std::shared_ptr<PresenterTheme>& rpTheme,
57 const OUString& rsStyleName);
58
59 awt::Rectangle AddBorder (
60 const awt::Rectangle& rBox,
61 drawing::framework::BorderType eBorderType) const;
62 awt::Rectangle RemoveBorder (
63 const awt::Rectangle& rBox,
64 drawing::framework::BorderType eBorderType) const;
65 Reference<rendering::XCanvasFont> GetFont (
66 const Reference<rendering::XCanvas>& rxCanvas) const;
67
79 sal_Int32 mnFontXOffset;
80 sal_Int32 mnFontYOffset;
81 enum class Anchor { Left, Right, Center };
86 private:
87 void UpdateBorderSizes();
88 SharedBitmapDescriptor GetBitmap(
89 const std::shared_ptr<PresenterTheme>& rpTheme,
90 const OUString& rsStyleName,
91 const OUString& rsBitmapName);
92 };
93}
94
96{
97public:
98 Renderer (
99 const Reference<XComponentContext>& rxContext,
100 std::shared_ptr<PresenterTheme> xTheme);
101
102 void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas);
103 void PaintBorder (
104 const OUString& rsTitle,
105 const awt::Rectangle& rBBox,
106 const awt::Rectangle& rUpdateBox,
107 const OUString& rsPaneURL);
108 void PaintTitle (
109 const OUString& rsTitle,
110 const std::shared_ptr<RendererPaneStyle>& rpStyle,
111 const awt::Rectangle& rUpdateBox,
112 const awt::Rectangle& rOuterBox,
113 const awt::Rectangle& rInnerBox);
114 void SetupClipping (
115 const awt::Rectangle& rUpdateBox,
116 const awt::Rectangle& rOuterBox,
117 const OUString& rsPaneStyleName);
118 std::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL);
119 void SetCalloutAnchor (
120 const awt::Point& rCalloutAnchor);
121
122private:
123 std::shared_ptr<PresenterTheme> mpTheme;
124 typedef ::std::map<OUString, std::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer;
126 Reference<rendering::XCanvas> mxCanvas;
127 Reference<drawing::XPresenterHelper> mxPresenterHelper;
128 css::rendering::ViewState maViewState;
129 Reference<rendering::XPolyPolygon2D> mxViewStateClip;
131 awt::Point maCalloutAnchor;
132
133 void PaintBitmap(
134 const awt::Rectangle& rBox,
135 const awt::Rectangle& rUpdateBox,
136 const sal_Int32 nXPosition,
137 const sal_Int32 nYPosition,
138 const sal_Int32 nStartOffset,
139 const sal_Int32 nEndOffset,
140 const bool bExpand,
141 const SharedBitmapDescriptor& rpBitmap);
142};
143
144// ===== PresenterPaneBorderPainter ===========================================
145
147 const Reference<XComponentContext>& rxContext)
149 mxContext(rxContext)
150{
151}
152
154{
155}
156
157//----- XPaneBorderPainter ----------------------------------------------------
158
160 const OUString& rsPaneBorderStyleName,
161 const css::awt::Rectangle& rRectangle,
162 drawing::framework::BorderType eBorderType)
163{
165
166 ProvideTheme();
167
168 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
169}
170
172 const OUString& rsPaneBorderStyleName,
173 const css::awt::Rectangle& rRectangle,
174 drawing::framework::BorderType eBorderType)
175{
177
178 ProvideTheme();
179
180 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
181}
182
184 const OUString& rsPaneBorderStyleName,
185 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
186 const css::awt::Rectangle& rOuterBorderRectangle,
187 const css::awt::Rectangle& rRepaintArea,
188 const OUString& rsTitle)
189{
191
192 // Early reject paints completely outside the repaint area.
193 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
194 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
195 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
196 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
197 {
198 return;
199 }
200 ProvideTheme(rxCanvas);
201
202 if (mpRenderer == nullptr)
203 return;
204
205 mpRenderer->SetCanvas(rxCanvas);
206 mpRenderer->SetupClipping(
207 rRepaintArea,
208 rOuterBorderRectangle,
209 rsPaneBorderStyleName);
210 mpRenderer->PaintBorder(
211 rsTitle,
212 rOuterBorderRectangle,
213 rRepaintArea,
214 rsPaneBorderStyleName);
215}
216
218 const OUString& rsPaneBorderStyleName,
219 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
220 const css::awt::Rectangle& rOuterBorderRectangle,
221 const css::awt::Rectangle& rRepaintArea,
222 const OUString& rsTitle,
223 const css::awt::Point& rCalloutAnchor)
224{
226
227 // Early reject paints completely outside the repaint area.
228 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
229 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
230 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
231 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
232 {
233 return;
234 }
235 ProvideTheme(rxCanvas);
236
237 if (mpRenderer == nullptr)
238 return;
239
240 mpRenderer->SetCanvas(rxCanvas);
241 mpRenderer->SetupClipping(
242 rRepaintArea,
243 rOuterBorderRectangle,
244 rsPaneBorderStyleName);
245 mpRenderer->SetCalloutAnchor(rCalloutAnchor);
246 mpRenderer->PaintBorder(
247 rsTitle,
248 rOuterBorderRectangle,
249 rRepaintArea,
250 rsPaneBorderStyleName);
251}
252
254 const OUString& rsPaneBorderStyleName)
255{
257 ProvideTheme();
258 if (mpRenderer != nullptr)
259 {
260 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
261 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
262 if (pRendererPaneStyle != nullptr && pRendererPaneStyle->mpBottomCallout)
263 {
264 return awt::Point (
265 0,
266 pRendererPaneStyle->mpBottomCallout->mnHeight
267 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
268 }
269 }
270
271 return awt::Point(0,0);
272}
273
274
275bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
276{
277 bool bModified (false);
278
279 if ( ! mxContext.is())
280 return false;
281
282 if (mpTheme != nullptr)
283 {
284 // Check if the theme already has a canvas.
285 if ( ! mpTheme->HasCanvas())
286 {
287 mpTheme->ProvideCanvas(rxCanvas);
288 bModified = true;
289 }
290 }
291 else
292 {
293 mpTheme = std::make_shared<PresenterTheme>(mxContext, rxCanvas);
294 bModified = true;
295 }
296
297 if (bModified)
298 {
299 if (mpRenderer == nullptr)
300 mpRenderer.reset(new Renderer(mxContext, mpTheme));
301 else
302 mpRenderer->SetCanvas(rxCanvas);
303 }
304
305 return bModified;
306}
307
309{
310 if (mpTheme == nullptr)
311 {
312 // Create a theme without bitmaps (no canvas => no bitmaps).
313 ProvideTheme(nullptr);
314 }
315 // When there already is a theme then without a canvas we can not
316 // add anything new.
317}
318
319void PresenterPaneBorderPainter::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
320{
321 mpTheme = rpTheme;
322 if (mpRenderer == nullptr)
324}
325
327 const OUString& rsPaneURL,
328 const awt::Rectangle& rInnerBox,
329 const css::drawing::framework::BorderType eBorderType) const
330{
331 if (mpRenderer != nullptr)
332 {
333 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
334 if (pRendererPaneStyle != nullptr)
335 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
336 }
337 return rInnerBox;
338}
339
341 const OUString& rsPaneURL,
342 const css::awt::Rectangle& rOuterBox,
343 const css::drawing::framework::BorderType eBorderType) const
344{
345 if (mpRenderer != nullptr)
346 {
347 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
348 if (pRendererPaneStyle != nullptr)
349 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
350 }
351 return rOuterBox;
352}
353
355{
356 if (rBHelper.bDisposed || rBHelper.bInDispose)
357 {
358 throw lang::DisposedException (
359 "PresenterPaneBorderPainter object has already been disposed",
360 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
361 }
362}
363
364//===== PresenterPaneBorderPainter::Renderer =====================================
365
367 const Reference<XComponentContext>& rxContext,
368 std::shared_ptr<PresenterTheme> xTheme)
369 : mpTheme(std::move(xTheme)),
370 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
371 mbHasCallout(false)
372{
373 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
374 if (xFactory.is())
375 {
377 xFactory->createInstanceWithContext(
378 "com.sun.star.comp.Draw.PresenterHelper",
379 rxContext),
380 UNO_QUERY_THROW);
381 }
382}
383
384void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
385{
386 if (mxCanvas != rxCanvas)
387 {
388 mxCanvas = rxCanvas;
389 }
390}
391
393 const OUString& rsTitle,
394 const awt::Rectangle& rBBox,
395 const awt::Rectangle& rUpdateBox,
396 const OUString& rsPaneURL)
397{
398 if ( ! mxCanvas.is())
399 return;
400
401 // Create the outer and inner border of the, ahm, border.
402 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
403 if (pStyle == nullptr)
404 return;
405
406 awt::Rectangle aOuterBox (rBBox);
407 awt::Rectangle aCenterBox (
408 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
409 awt::Rectangle aInnerBox (
410 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
411
412 // Prepare references for all used bitmaps.
413 SharedBitmapDescriptor pTop (pStyle->mpTop);
414 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
415 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
416 SharedBitmapDescriptor pLeft (pStyle->mpLeft);
417 SharedBitmapDescriptor pRight (pStyle->mpRight);
418 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
419 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
420 SharedBitmapDescriptor pBottom (pStyle->mpBottom);
421
422 // Paint the sides.
423 PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
424 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop);
425 PaintBitmap(aCenterBox, rUpdateBox, -1,0,
426 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft);
427 PaintBitmap(aCenterBox, rUpdateBox, +1,0,
428 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight);
429 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
430 {
431 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
432 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
433 - (aCenterBox.X - aOuterBox.X));
434 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
435 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
436 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
437 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
438 // Paint bottom callout.
439 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout);
440 // Paint regular bottom bitmap left and right.
441 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
442 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom);
443 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
444 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom);
445 }
446 else
447 {
448 // Stretch the bottom bitmap over the full width.
449 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
450 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom);
451 }
452
453 // Paint the corners.
454 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft);
455 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight);
456 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft);
457 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight);
458
459 // Paint the title.
460 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox);
461
462 // In a double buffering environment request to make the changes visible.
463 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
464 if (xSpriteCanvas.is())
465 xSpriteCanvas->updateScreen(false);
466}
467
469 const OUString& rsTitle,
470 const std::shared_ptr<RendererPaneStyle>& rpStyle,
471 const awt::Rectangle& rUpdateBox,
472 const awt::Rectangle& rOuterBox,
473 const awt::Rectangle& rInnerBox)
474{
475 if ( ! mxCanvas.is())
476 return;
477
478 if (rsTitle.isEmpty())
479 return;
480
481 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
482 if ( ! xFont.is())
483 return;
484
485 rendering::StringContext aContext (
486 rsTitle,
487 0,
488 rsTitle.getLength());
489 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
490 aContext,
491 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
492 0));
493 if ( ! xLayout.is())
494 return;
495
497 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
498 const double nTextHeight = aBox.Y2 - aBox.Y1;
499 const double nTextWidth = aBox.X1 + aBox.X2;
500 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
501 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
502 if (nY >= rInnerBox.Y)
503 nY = rInnerBox.Y - 1;
504 double nX;
505 switch (rpStyle->meFontAnchor)
506 {
507 case RendererPaneStyle::Anchor::Left:
508 nX = rInnerBox.X;
509 break;
510 case RendererPaneStyle::Anchor::Right:
511 nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
512 break;
513 default: // RendererPaneStyle::Anchor::Center
514 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
515 break;
516 }
517 nX += rpStyle->mnFontXOffset;
518 nY += rpStyle->mnFontYOffset;
519
520 if (rUpdateBox.X >= nX+nTextWidth
521 || rUpdateBox.Y >= nY+nTextHeight
522 || rUpdateBox.X+rUpdateBox.Width <= nX
523 || rUpdateBox.Y+rUpdateBox.Height <= nY)
524 {
525 return;
526 }
527
528 rendering::RenderState aRenderState(
529 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
530 nullptr,
531 Sequence<double>(4),
532 rendering::CompositeOperation::SOURCE);
533
535 aRenderState,
536 rpStyle->mpFont->mnColor);
537
538 mxCanvas->drawTextLayout (
539 xLayout,
540 maViewState,
541 aRenderState);
542}
543
544std::shared_ptr<RendererPaneStyle>
546{
547 OSL_ASSERT(mpTheme != nullptr);
548
549 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
550 if (iStyle == maRendererPaneStyles.end())
551 {
552 OUString sPaneStyleName ("DefaultRendererPaneStyle");
553
554 // Get pane layout name for resource URL.
555 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
556 if (!sStyleName.isEmpty())
557 sPaneStyleName = sStyleName;
558
559 // Create a new pane style object and initialize it with bitmaps.
560 auto pStyle = std::make_shared<RendererPaneStyle>(mpTheme,sPaneStyleName);
561 iStyle = maRendererPaneStyles.emplace(rsResourceURL, pStyle).first;
562 }
563 if (iStyle != maRendererPaneStyles.end())
564 return iStyle->second;
565 else
566 return std::shared_ptr<RendererPaneStyle>();
567}
568
570 const awt::Point& rCalloutAnchor)
571{
572 mbHasCallout = true;
573 maCalloutAnchor = rCalloutAnchor;
574}
575
577 const awt::Rectangle& rBox,
578 const awt::Rectangle& rUpdateBox,
579 const sal_Int32 nXPosition,
580 const sal_Int32 nYPosition,
581 const sal_Int32 nStartOffset,
582 const sal_Int32 nEndOffset,
583 const bool bExpand,
584 const SharedBitmapDescriptor& rpBitmap)
585{
586 bool bUseCanvas (mxCanvas.is());
587 if ( ! bUseCanvas)
588 return;
589
590 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
591 return;
592
593 Reference<rendering::XBitmap> xBitmap = rpBitmap->GetNormalBitmap();
594 if ( ! xBitmap.is())
595 return;
596
597 // Calculate position, and for side bitmaps, the size.
598 sal_Int32 nX = 0;
599 sal_Int32 nY = 0;
600 sal_Int32 nW = rpBitmap->mnWidth;
601 sal_Int32 nH = rpBitmap->mnHeight;
602 if (nXPosition < 0)
603 {
604 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
605 }
606 else if (nXPosition > 0)
607 {
608 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
609 }
610 else
611 {
612 nX = rBox.X + nStartOffset;
613 if (bExpand)
614 nW = rBox.Width - nStartOffset + nEndOffset;
615 }
616
617 if (nYPosition < 0)
618 {
619 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
620 }
621 else if (nYPosition > 0)
622 {
623 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
624 }
625 else
626 {
627 nY = rBox.Y + nStartOffset;
628 if (bExpand)
629 nH = rBox.Height - nStartOffset + nEndOffset;
630 }
631
632 // Do not paint when bitmap area does not intersect with update box.
633 if (nX >= rUpdateBox.X + rUpdateBox.Width
634 || nX+nW <= rUpdateBox.X
635 || nY >= rUpdateBox.Y + rUpdateBox.Height
636 || nY+nH <= rUpdateBox.Y)
637 {
638 return;
639 }
640
641 /*
642 Reference<rendering::XBitmap> xMaskedBitmap (
643 PresenterBitmapHelper::FillMaskedWithColor (
644 mxCanvas,
645 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
646 rBitmap.mxMaskBitmap,
647 0x00ff0000,
648 rBackgroundBitmap.maReplacementColor));
649 if (xMaskedBitmap.is())
650 xBitmap = xMaskedBitmap;
651 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
652 {
653 const static sal_Int32 nOutsideMaskColor (0x00ff0000);
654 Reference<rendering::XIntegerBitmap> xMask (
655 mxPresenterHelper->createMask(
656 mxCanvas,
657 rBitmap.mxMaskBitmap,
658 nOutsideMaskColor,
659 false));
660 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
661 mxCanvas,
662 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
663 xMask,
664 rBackgroundBitmap.maReplacementColor);
665 }
666 */
667 rendering::RenderState aRenderState (
668 geometry::AffineMatrix2D(
669 double(nW)/rpBitmap->mnWidth, 0, nX,
670 0, double(nH)/rpBitmap->mnHeight, nY),
671 nullptr,
672 Sequence<double>(4),
673 rendering::CompositeOperation::OVER);
674
675 if (xBitmap.is())
676 mxCanvas->drawBitmap(
677 xBitmap,
678 maViewState,
679 aRenderState);
680}
681
683 const awt::Rectangle& rUpdateBox,
684 const awt::Rectangle& rOuterBox,
685 const OUString& rsPaneStyleName)
686{
687 mxViewStateClip = nullptr;
688 maViewState.Clip = nullptr;
689
690 if ( ! mxCanvas.is())
691 return;
692
693 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
694 if (pStyle == nullptr)
695 {
697 rUpdateBox,
698 mxCanvas->getDevice());
699 }
700 else
701 {
702 awt::Rectangle aInnerBox (
703 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
704 ::std::vector<awt::Rectangle> aRectangles
705 {
706 PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox),
707 PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox)
708 };
710 aRectangles,
711 mxCanvas->getDevice());
712 if (mxViewStateClip.is())
713 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
714 }
715 maViewState.Clip = mxViewStateClip;
716}
717
718namespace {
719
720//===== BorderSize ============================================================
721
722BorderSize::BorderSize()
723 : mnLeft(0),
724 mnTop(0),
725 mnRight(0),
726 mnBottom(0)
727{
728}
729
730//===== RendererPaneStyle ============================================================
731
732RendererPaneStyle::RendererPaneStyle (
733 const std::shared_ptr<PresenterTheme>& rpTheme,
734 const OUString& rsStyleName)
736 mnFontXOffset(0),
737 mnFontYOffset(0),
739{
740 if (rpTheme == nullptr)
741 return;
742
743 mpTopLeft = GetBitmap(rpTheme, rsStyleName, "TopLeft");
744 mpTop = GetBitmap(rpTheme, rsStyleName, "Top");
745 mpTopRight = GetBitmap(rpTheme, rsStyleName, "TopRight");
746 mpLeft = GetBitmap(rpTheme, rsStyleName,"Left");
747 mpRight = GetBitmap(rpTheme, rsStyleName, "Right");
748 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, "BottomLeft");
749 mpBottom = GetBitmap(rpTheme, rsStyleName, "Bottom");
750 mpBottomRight = GetBitmap(rpTheme, rsStyleName, "BottomRight");
751 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, "BottomCallout");
752
753 // Get font description.
754 mpFont = rpTheme->GetFont(rsStyleName);
755
756 OUString sAnchor ("Left");
757 if (mpFont)
758 {
759 sAnchor = mpFont->msAnchor;
760 mnFontXOffset = mpFont->mnXOffset;
761 mnFontYOffset = mpFont->mnYOffset;
762 }
763
764 if ( sAnchor == "Left" )
765 meFontAnchor = Anchor::Left;
766 else if ( sAnchor == "Right" )
767 meFontAnchor = Anchor::Right;
768 else
769 meFontAnchor = Anchor::Center;
770
771 // Get border sizes.
772 try
773 {
774 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
775 OSL_ASSERT(aInnerBorder.size()==4);
776 maInnerBorderSize.mnLeft = aInnerBorder[0];
777 maInnerBorderSize.mnTop = aInnerBorder[1];
778 maInnerBorderSize.mnRight = aInnerBorder[2];
779 maInnerBorderSize.mnBottom = aInnerBorder[3];
780
781 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
782 OSL_ASSERT(aOuterBorder.size()==4);
783 maOuterBorderSize.mnLeft = aOuterBorder[0];
784 maOuterBorderSize.mnTop = aOuterBorder[1];
785 maOuterBorderSize.mnRight = aOuterBorder[2];
786 maOuterBorderSize.mnBottom = aOuterBorder[3];
787 }
788 catch(beans::UnknownPropertyException&)
789 {
790 OSL_ASSERT(false);
791 }
792
793 UpdateBorderSizes();
794}
795
796awt::Rectangle RendererPaneStyle::AddBorder (
797 const awt::Rectangle& rBox,
798 const drawing::framework::BorderType eBorderType) const
799{
800 const BorderSize* pBorderSize = nullptr;
801 switch (eBorderType)
802 {
803 case drawing::framework::BorderType_INNER_BORDER:
804 pBorderSize = &maInnerBorderSize;
805 break;
806 case drawing::framework::BorderType_OUTER_BORDER:
807 pBorderSize = &maOuterBorderSize;
808 break;
809 case drawing::framework::BorderType_TOTAL_BORDER:
810 pBorderSize = &maTotalBorderSize;
811 break;
812 default:
813 return rBox;
814 }
815 return awt::Rectangle (
816 rBox.X - pBorderSize->mnLeft,
817 rBox.Y - pBorderSize->mnTop,
818 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
819 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
820}
821
822awt::Rectangle RendererPaneStyle::RemoveBorder (
823 const awt::Rectangle& rBox,
824 const css::drawing::framework::BorderType eBorderType) const
825{
826 const BorderSize* pBorderSize = nullptr;
827 switch (eBorderType)
828 {
829 case drawing::framework::BorderType_INNER_BORDER:
830 pBorderSize = &maInnerBorderSize;
831 break;
832 case drawing::framework::BorderType_OUTER_BORDER:
833 pBorderSize = &maOuterBorderSize;
834 break;
835 case drawing::framework::BorderType_TOTAL_BORDER:
836 pBorderSize = &maTotalBorderSize;
837 break;
838 default:
839 return rBox;
840 }
841 return awt::Rectangle (
842 rBox.X + pBorderSize->mnLeft,
843 rBox.Y + pBorderSize->mnTop,
844 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
845 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
846}
847
848Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
849 const Reference<rendering::XCanvas>& rxCanvas) const
850{
851 if (mpFont)
852 {
853 mpFont->PrepareFont(rxCanvas);
854 return mpFont->mxFont;
855 }
856 return Reference<rendering::XCanvasFont>();
857}
858
859void RendererPaneStyle::UpdateBorderSizes()
860{
863 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
864 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
865}
866
867SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
868 const std::shared_ptr<PresenterTheme>& rpTheme,
869 const OUString& rsStyleName,
870 const OUString& rsBitmapName)
871{
872 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
873 if (pDescriptor)
874 return pDescriptor;
875 else
876 return mpEmpty;
877}
878
879} // end of anonymous namespace
880
881} // end of namespace ::sd::presenter
882
883/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 mnTop
SharedBitmapDescriptor mpBottomRight
SharedBitmapDescriptor mpBottomCallout
SharedBitmapDescriptor mpLeft
Anchor meFontAnchor
BorderSize maTotalBorderSize
SharedBitmapDescriptor mpRight
sal_Int32 mnRight
SharedBitmapDescriptor mpTop
sal_Int32 mnFontYOffset
PresenterTheme::SharedFontDescriptor mpFont
sal_Int32 mnFontXOffset
sal_Int32 mnBottom
BorderSize maInnerBorderSize
SharedBitmapDescriptor mpTopRight
sal_Int32 mnLeft
SharedBitmapDescriptor mpEmpty
SharedBitmapDescriptor mpTopLeft
BorderSize maOuterBorderSize
SharedBitmapDescriptor mpBottomLeft
SharedBitmapDescriptor mpBottom
Reference< rendering::XCanvas > mxCanvas
There is one bitmap for the normal state, one for a mouse over effect and one to show that a button h...
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
static css::awt::Rectangle Intersection(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
void SetCanvas(const Reference< rendering::XCanvas > &rxCanvas)
std::shared_ptr< RendererPaneStyle > GetRendererPaneStyle(const OUString &rsResourceURL)
void PaintBorder(const OUString &rsTitle, const awt::Rectangle &rBBox, const awt::Rectangle &rUpdateBox, const OUString &rsPaneURL)
void SetupClipping(const awt::Rectangle &rUpdateBox, const awt::Rectangle &rOuterBox, const OUString &rsPaneStyleName)
void PaintTitle(const OUString &rsTitle, const std::shared_ptr< RendererPaneStyle > &rpStyle, const awt::Rectangle &rUpdateBox, const awt::Rectangle &rOuterBox, const awt::Rectangle &rInnerBox)
::std::map< OUString, std::shared_ptr< RendererPaneStyle > > RendererPaneStyleContainer
void PaintBitmap(const awt::Rectangle &rBox, const awt::Rectangle &rUpdateBox, const sal_Int32 nXPosition, const sal_Int32 nYPosition, const sal_Int32 nStartOffset, const sal_Int32 nEndOffset, const bool bExpand, const SharedBitmapDescriptor &rpBitmap)
Renderer(const Reference< XComponentContext > &rxContext, std::shared_ptr< PresenterTheme > xTheme)
PresenterPaneBorderPainter(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual css::awt::Point SAL_CALL getCalloutOffset(const OUString &rsPaneBorderStyleName) override
css::awt::Rectangle AddBorder(const OUString &rsPaneURL, const css::awt::Rectangle &rInnerBox, const css::drawing::framework::BorderType eBorderType) const
Transform the bounding box of the window content to the outer bounding box of the border that is pain...
void SetTheme(const std::shared_ptr< PresenterTheme > &rpTheme)
css::awt::Rectangle RemoveBorder(const OUString &rsPaneURL, const css::awt::Rectangle &rOuterBox, const css::drawing::framework::BorderType eBorderType) const
Transform the outer bounding box of a window to the bounding box of the inner content area.
virtual void SAL_CALL paintBorder(const OUString &rsPaneBorderStyleName, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rOuterBorderRectangle, const css::awt::Rectangle &rRepaintArea, const OUString &rsTitle) override
virtual css::awt::Rectangle SAL_CALL removeBorder(const OUString &rsPaneBorderStyleName, const css::awt::Rectangle &rRectangle, css::drawing::framework::BorderType eBorderType) override
virtual css::awt::Rectangle SAL_CALL addBorder(const OUString &rsPaneBorderStyleName, const css::awt::Rectangle &rRectangle, css::drawing::framework::BorderType eBorderType) override
css::uno::Reference< css::uno::XComponentContext > mxContext
virtual void SAL_CALL paintBorderWithCallout(const OUString &rsPaneBorderStyleName, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rOuterBorderRectangle, const css::awt::Rectangle &rRepaintArea, const OUString &rsTitle, const css::awt::Point &rCalloutAnchor) override
std::shared_ptr< FontDescriptor > SharedFontDescriptor
uno::Reference< uno::XComponentContext > mxContext
Reference< XSingleServiceFactory > xFactory
std::mutex m_aMutex
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
std::shared_ptr< T > make_shared(Args &&... args)
::cppu::WeakComponentImplHelper< css::drawing::framework::XPaneBorderPainter > PresenterPaneBorderPainterInterfaceBase
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
Left
Center
Right