update credits
[LibreOffice.git] / sdext / source / presenter / PresenterPaneBorderPainter.cxx
blob53d60faa2315b445ea90eb9d5a476b6bac5add5f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "PresenterPaneBorderPainter.hxx"
21 #include "PresenterCanvasHelper.hxx"
22 #include "PresenterGeometryHelper.hxx"
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 <vector>
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
38 namespace sdext::presenter {
40 namespace {
41 class BorderSize
43 public:
44 BorderSize();
45 sal_Int32 mnLeft;
46 sal_Int32 mnTop;
47 sal_Int32 mnRight;
48 sal_Int32 mnBottom;
51 class RendererPaneStyle
53 public:
54 RendererPaneStyle (
55 const std::shared_ptr<PresenterTheme>& rpTheme,
56 const OUString& rsStyleName);
58 awt::Rectangle AddBorder (
59 const awt::Rectangle& rBox,
60 drawing::framework::BorderType eBorderType) const;
61 awt::Rectangle RemoveBorder (
62 const awt::Rectangle& rBox,
63 drawing::framework::BorderType eBorderType) const;
64 Reference<rendering::XCanvasFont> GetFont (
65 const Reference<rendering::XCanvas>& rxCanvas) const;
67 SharedBitmapDescriptor mpTopLeft;
68 SharedBitmapDescriptor mpTop;
69 SharedBitmapDescriptor mpTopRight;
70 SharedBitmapDescriptor mpLeft;
71 SharedBitmapDescriptor mpRight;
72 SharedBitmapDescriptor mpBottomLeft;
73 SharedBitmapDescriptor mpBottom;
74 SharedBitmapDescriptor mpBottomRight;
75 SharedBitmapDescriptor mpBottomCallout;
76 SharedBitmapDescriptor mpEmpty;
77 PresenterTheme::SharedFontDescriptor mpFont;
78 sal_Int32 mnFontXOffset;
79 sal_Int32 mnFontYOffset;
80 enum class Anchor { Left, Right, Center };
81 Anchor meFontAnchor;
82 BorderSize maInnerBorderSize;
83 BorderSize maOuterBorderSize;
84 BorderSize maTotalBorderSize;
85 private:
86 void UpdateBorderSizes();
87 SharedBitmapDescriptor GetBitmap(
88 const std::shared_ptr<PresenterTheme>& rpTheme,
89 const OUString& rsStyleName,
90 const OUString& rsBitmapName);
94 class PresenterPaneBorderPainter::Renderer
96 public:
97 Renderer (
98 const Reference<XComponentContext>& rxContext,
99 const std::shared_ptr<PresenterTheme>& rpTheme);
101 void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas);
102 void PaintBorder (
103 const OUString& rsTitle,
104 const awt::Rectangle& rBBox,
105 const awt::Rectangle& rUpdateBox,
106 const OUString& rsPaneURL);
107 void PaintTitle (
108 const OUString& rsTitle,
109 const std::shared_ptr<RendererPaneStyle>& rpStyle,
110 const awt::Rectangle& rUpdateBox,
111 const awt::Rectangle& rOuterBox,
112 const awt::Rectangle& rInnerBox);
113 void SetupClipping (
114 const awt::Rectangle& rUpdateBox,
115 const awt::Rectangle& rOuterBox,
116 const OUString& rsPaneStyleName);
117 std::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL);
118 void SetCalloutAnchor (
119 const awt::Point& rCalloutAnchor);
121 private:
122 std::shared_ptr<PresenterTheme> mpTheme;
123 typedef ::std::map<OUString, std::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer;
124 RendererPaneStyleContainer maRendererPaneStyles;
125 Reference<rendering::XCanvas> mxCanvas;
126 Reference<drawing::XPresenterHelper> mxPresenterHelper;
127 css::rendering::ViewState maViewState;
128 Reference<rendering::XPolyPolygon2D> mxViewStateClip;
129 bool mbHasCallout;
130 awt::Point maCalloutAnchor;
132 void PaintBitmap(
133 const awt::Rectangle& rBox,
134 const awt::Rectangle& rUpdateBox,
135 const sal_Int32 nXPosition,
136 const sal_Int32 nYPosition,
137 const sal_Int32 nStartOffset,
138 const sal_Int32 nEndOffset,
139 const bool bExpand,
140 const SharedBitmapDescriptor& rpBitmap);
143 // ===== PresenterPaneBorderPainter ===========================================
145 PresenterPaneBorderPainter::PresenterPaneBorderPainter (
146 const Reference<XComponentContext>& rxContext)
147 : PresenterPaneBorderPainterInterfaceBase(m_aMutex),
148 mxContext(rxContext),
149 mpTheme(),
150 mpRenderer()
154 PresenterPaneBorderPainter::~PresenterPaneBorderPainter()
158 //----- XPaneBorderPainter ----------------------------------------------------
160 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder (
161 const OUString& rsPaneBorderStyleName,
162 const css::awt::Rectangle& rRectangle,
163 drawing::framework::BorderType eBorderType)
165 ThrowIfDisposed();
167 ProvideTheme();
169 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
172 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder (
173 const OUString& rsPaneBorderStyleName,
174 const css::awt::Rectangle& rRectangle,
175 drawing::framework::BorderType eBorderType)
177 ThrowIfDisposed();
179 ProvideTheme();
181 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
184 void SAL_CALL PresenterPaneBorderPainter::paintBorder (
185 const OUString& rsPaneBorderStyleName,
186 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
187 const css::awt::Rectangle& rOuterBorderRectangle,
188 const css::awt::Rectangle& rRepaintArea,
189 const OUString& rsTitle)
191 ThrowIfDisposed();
193 // Early reject paints completely outside the repaint area.
194 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
195 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
196 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
197 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
199 return;
201 ProvideTheme(rxCanvas);
203 if (mpRenderer == nullptr)
204 return;
206 mpRenderer->SetCanvas(rxCanvas);
207 mpRenderer->SetupClipping(
208 rRepaintArea,
209 rOuterBorderRectangle,
210 rsPaneBorderStyleName);
211 mpRenderer->PaintBorder(
212 rsTitle,
213 rOuterBorderRectangle,
214 rRepaintArea,
215 rsPaneBorderStyleName);
218 void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout (
219 const OUString& rsPaneBorderStyleName,
220 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
221 const css::awt::Rectangle& rOuterBorderRectangle,
222 const css::awt::Rectangle& rRepaintArea,
223 const OUString& rsTitle,
224 const css::awt::Point& rCalloutAnchor)
226 ThrowIfDisposed();
228 // Early reject paints completely outside the repaint area.
229 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
230 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
231 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
232 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
234 return;
236 ProvideTheme(rxCanvas);
238 if (mpRenderer == nullptr)
239 return;
241 mpRenderer->SetCanvas(rxCanvas);
242 mpRenderer->SetupClipping(
243 rRepaintArea,
244 rOuterBorderRectangle,
245 rsPaneBorderStyleName);
246 mpRenderer->SetCalloutAnchor(rCalloutAnchor);
247 mpRenderer->PaintBorder(
248 rsTitle,
249 rOuterBorderRectangle,
250 rRepaintArea,
251 rsPaneBorderStyleName);
254 awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset (
255 const OUString& rsPaneBorderStyleName)
257 ThrowIfDisposed();
258 ProvideTheme();
259 if (mpRenderer != nullptr)
261 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
262 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
263 if (pRendererPaneStyle != nullptr && pRendererPaneStyle->mpBottomCallout)
265 return awt::Point (
267 pRendererPaneStyle->mpBottomCallout->mnHeight
268 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
272 return awt::Point(0,0);
276 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
278 bool bModified (false);
280 if ( ! mxContext.is())
281 return false;
283 if (mpTheme != nullptr)
285 // Check if the theme already has a canvas.
286 if ( ! mpTheme->HasCanvas())
288 mpTheme->ProvideCanvas(rxCanvas);
289 bModified = true;
292 else
294 mpTheme = std::make_shared<PresenterTheme>(mxContext, rxCanvas);
295 bModified = true;
298 if (bModified)
300 if (mpRenderer == nullptr)
301 mpRenderer.reset(new Renderer(mxContext, mpTheme));
302 else
303 mpRenderer->SetCanvas(rxCanvas);
306 return bModified;
309 void PresenterPaneBorderPainter::ProvideTheme()
311 if (mpTheme == nullptr)
313 // Create a theme without bitmaps (no canvas => no bitmaps).
314 ProvideTheme(nullptr);
316 // When there already is a theme then without a canvas we can not
317 // add anything new.
320 void PresenterPaneBorderPainter::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
322 mpTheme = rpTheme;
323 if (mpRenderer == nullptr)
324 mpRenderer.reset(new Renderer(mxContext, mpTheme));
327 awt::Rectangle PresenterPaneBorderPainter::AddBorder (
328 const OUString& rsPaneURL,
329 const awt::Rectangle& rInnerBox,
330 const css::drawing::framework::BorderType eBorderType) const
332 if (mpRenderer != nullptr)
334 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
335 if (pRendererPaneStyle != nullptr)
336 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
338 return rInnerBox;
341 awt::Rectangle PresenterPaneBorderPainter::RemoveBorder (
342 const OUString& rsPaneURL,
343 const css::awt::Rectangle& rOuterBox,
344 const css::drawing::framework::BorderType eBorderType) const
346 if (mpRenderer != nullptr)
348 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
349 if (pRendererPaneStyle != nullptr)
350 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
352 return rOuterBox;
355 void PresenterPaneBorderPainter::ThrowIfDisposed() const
357 if (rBHelper.bDisposed || rBHelper.bInDispose)
359 throw lang::DisposedException (
360 "PresenterPaneBorderPainter object has already been disposed",
361 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
365 //===== PresenterPaneBorderPainter::Renderer =====================================
367 PresenterPaneBorderPainter::Renderer::Renderer (
368 const Reference<XComponentContext>& rxContext,
369 const std::shared_ptr<PresenterTheme>& rpTheme)
370 : mpTheme(rpTheme),
371 maRendererPaneStyles(),
372 mxCanvas(),
373 mxPresenterHelper(),
374 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
375 mxViewStateClip(),
376 mbHasCallout(false),
377 maCalloutAnchor()
379 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
380 if (xFactory.is())
382 mxPresenterHelper.set(
383 xFactory->createInstanceWithContext(
384 "com.sun.star.comp.Draw.PresenterHelper",
385 rxContext),
386 UNO_QUERY_THROW);
390 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
392 if (mxCanvas != rxCanvas)
394 mxCanvas = rxCanvas;
398 void PresenterPaneBorderPainter::Renderer::PaintBorder (
399 const OUString& rsTitle,
400 const awt::Rectangle& rBBox,
401 const awt::Rectangle& rUpdateBox,
402 const OUString& rsPaneURL)
404 if ( ! mxCanvas.is())
405 return;
407 // Create the outer and inner border of the, ahm, border.
408 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
409 if (pStyle == nullptr)
410 return;
412 awt::Rectangle aOuterBox (rBBox);
413 awt::Rectangle aCenterBox (
414 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
415 awt::Rectangle aInnerBox (
416 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
418 // Prepare references for all used bitmaps.
419 SharedBitmapDescriptor pTop (pStyle->mpTop);
420 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
421 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
422 SharedBitmapDescriptor pLeft (pStyle->mpLeft);
423 SharedBitmapDescriptor pRight (pStyle->mpRight);
424 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
425 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
426 SharedBitmapDescriptor pBottom (pStyle->mpBottom);
428 // Paint the sides.
429 PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
430 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop);
431 PaintBitmap(aCenterBox, rUpdateBox, -1,0,
432 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft);
433 PaintBitmap(aCenterBox, rUpdateBox, +1,0,
434 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight);
435 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
437 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
438 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
439 - (aCenterBox.X - aOuterBox.X));
440 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
441 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
442 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
443 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
444 // Paint bottom callout.
445 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout);
446 // Paint regular bottom bitmap left and right.
447 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
448 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom);
449 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
450 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom);
452 else
454 // Stretch the bottom bitmap over the full width.
455 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
456 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom);
459 // Paint the corners.
460 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft);
461 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight);
462 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft);
463 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight);
465 // Paint the title.
466 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox);
468 // In a double buffering environment request to make the changes visible.
469 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
470 if (xSpriteCanvas.is())
471 xSpriteCanvas->updateScreen(false);
474 void PresenterPaneBorderPainter::Renderer::PaintTitle (
475 const OUString& rsTitle,
476 const std::shared_ptr<RendererPaneStyle>& rpStyle,
477 const awt::Rectangle& rUpdateBox,
478 const awt::Rectangle& rOuterBox,
479 const awt::Rectangle& rInnerBox)
481 if ( ! mxCanvas.is())
482 return;
484 if (rsTitle.isEmpty())
485 return;
487 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
488 if ( ! xFont.is())
489 return;
491 rendering::StringContext aContext (
492 rsTitle,
494 rsTitle.getLength());
495 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
496 aContext,
497 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
498 0));
499 if ( ! xLayout.is())
500 return;
502 /// this is responsible of the texts above the slide windows
503 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
504 const double nTextHeight = aBox.Y2 - aBox.Y1;
505 const double nTextWidth = aBox.X1 + aBox.X2;
506 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
507 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
508 if (nY >= rInnerBox.Y)
509 nY = rInnerBox.Y - 1;
510 double nX;
511 switch (rpStyle->meFontAnchor)
513 case RendererPaneStyle::Anchor::Left:
514 nX = rInnerBox.X;
515 break;
516 case RendererPaneStyle::Anchor::Right:
517 nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
518 break;
519 default: // RendererPaneStyle::Anchor::Center
520 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
521 break;
523 nX += rpStyle->mnFontXOffset;
524 nY += rpStyle->mnFontYOffset;
526 if (rUpdateBox.X >= nX+nTextWidth
527 || rUpdateBox.Y >= nY+nTextHeight
528 || rUpdateBox.X+rUpdateBox.Width <= nX
529 || rUpdateBox.Y+rUpdateBox.Height <= nY)
531 return;
534 rendering::RenderState aRenderState(
535 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
536 nullptr,
537 Sequence<double>(4),
538 rendering::CompositeOperation::SOURCE);
540 PresenterCanvasHelper::SetDeviceColor(
541 aRenderState,
542 rpStyle->mpFont->mnColor);
544 mxCanvas->drawTextLayout (
545 xLayout,
546 maViewState,
547 aRenderState);
550 std::shared_ptr<RendererPaneStyle>
551 PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL)
553 OSL_ASSERT(mpTheme != nullptr);
555 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
556 if (iStyle == maRendererPaneStyles.end())
558 OUString sPaneStyleName ("DefaultRendererPaneStyle");
560 // Get pane layout name for resource URL.
561 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
562 if (!sStyleName.isEmpty())
563 sPaneStyleName = sStyleName;
565 // Create a new pane style object and initialize it with bitmaps.
566 auto pStyle = std::make_shared<RendererPaneStyle>(mpTheme,sPaneStyleName);
567 iStyle = maRendererPaneStyles.emplace(rsResourceURL, pStyle).first;
569 if (iStyle != maRendererPaneStyles.end())
570 return iStyle->second;
571 else
572 return std::shared_ptr<RendererPaneStyle>();
575 void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor (
576 const awt::Point& rCalloutAnchor)
578 mbHasCallout = true;
579 maCalloutAnchor = rCalloutAnchor;
582 void PresenterPaneBorderPainter::Renderer::PaintBitmap(
583 const awt::Rectangle& rBox,
584 const awt::Rectangle& rUpdateBox,
585 const sal_Int32 nXPosition,
586 const sal_Int32 nYPosition,
587 const sal_Int32 nStartOffset,
588 const sal_Int32 nEndOffset,
589 const bool bExpand,
590 const SharedBitmapDescriptor& rpBitmap)
592 bool bUseCanvas (mxCanvas.is());
593 if ( ! bUseCanvas)
594 return;
596 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
597 return;
599 Reference<rendering::XBitmap> xBitmap = rpBitmap->GetNormalBitmap();
600 if ( ! xBitmap.is())
601 return;
603 // Calculate position, and for side bitmaps, the size.
604 sal_Int32 nX = 0;
605 sal_Int32 nY = 0;
606 sal_Int32 nW = rpBitmap->mnWidth;
607 sal_Int32 nH = rpBitmap->mnHeight;
608 if (nXPosition < 0)
610 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
612 else if (nXPosition > 0)
614 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
616 else
618 nX = rBox.X + nStartOffset;
619 if (bExpand)
620 nW = rBox.Width - nStartOffset + nEndOffset;
623 if (nYPosition < 0)
625 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
627 else if (nYPosition > 0)
629 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
631 else
633 nY = rBox.Y + nStartOffset;
634 if (bExpand)
635 nH = rBox.Height - nStartOffset + nEndOffset;
638 // Do not paint when bitmap area does not intersect with update box.
639 if (nX >= rUpdateBox.X + rUpdateBox.Width
640 || nX+nW <= rUpdateBox.X
641 || nY >= rUpdateBox.Y + rUpdateBox.Height
642 || nY+nH <= rUpdateBox.Y)
644 return;
648 Reference<rendering::XBitmap> xMaskedBitmap (
649 PresenterBitmapHelper::FillMaskedWithColor (
650 mxCanvas,
651 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
652 rBitmap.mxMaskBitmap,
653 0x00ff0000,
654 rBackgroundBitmap.maReplacementColor));
655 if (xMaskedBitmap.is())
656 xBitmap = xMaskedBitmap;
657 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
659 const static sal_Int32 nOutsideMaskColor (0x00ff0000);
660 Reference<rendering::XIntegerBitmap> xMask (
661 mxPresenterHelper->createMask(
662 mxCanvas,
663 rBitmap.mxMaskBitmap,
664 nOutsideMaskColor,
665 false));
666 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
667 mxCanvas,
668 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
669 xMask,
670 rBackgroundBitmap.maReplacementColor);
673 rendering::RenderState aRenderState (
674 geometry::AffineMatrix2D(
675 double(nW)/rpBitmap->mnWidth, 0, nX,
676 0, double(nH)/rpBitmap->mnHeight, nY),
677 nullptr,
678 Sequence<double>(4),
679 rendering::CompositeOperation::OVER);
681 if (xBitmap.is())
682 mxCanvas->drawBitmap(
683 xBitmap,
684 maViewState,
685 aRenderState);
688 void PresenterPaneBorderPainter::Renderer::SetupClipping (
689 const awt::Rectangle& rUpdateBox,
690 const awt::Rectangle& rOuterBox,
691 const OUString& rsPaneStyleName)
693 mxViewStateClip = nullptr;
694 maViewState.Clip = nullptr;
696 if ( ! mxCanvas.is())
697 return;
699 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
700 if (pStyle == nullptr)
702 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
703 rUpdateBox,
704 mxCanvas->getDevice());
706 else
708 awt::Rectangle aInnerBox (
709 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
710 ::std::vector<awt::Rectangle> aRectangles;
711 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox));
712 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox));
713 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
714 aRectangles,
715 mxCanvas->getDevice());
716 if (mxViewStateClip.is())
717 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
719 maViewState.Clip = mxViewStateClip;
722 namespace {
724 //===== BorderSize ============================================================
726 BorderSize::BorderSize()
727 : mnLeft(0),
728 mnTop(0),
729 mnRight(0),
730 mnBottom(0)
734 //===== RendererPaneStyle ============================================================
736 RendererPaneStyle::RendererPaneStyle (
737 const std::shared_ptr<PresenterTheme>& rpTheme,
738 const OUString& rsStyleName)
739 : mpTopLeft(),
740 mpTop(),
741 mpTopRight(),
742 mpLeft(),
743 mpRight(),
744 mpBottomLeft(),
745 mpBottom(),
746 mpBottomRight(),
747 mpBottomCallout(),
748 mpEmpty(std::make_shared<PresenterBitmapDescriptor>()),
749 mpFont(),
750 mnFontXOffset(0),
751 mnFontYOffset(0),
752 meFontAnchor(Anchor::Center),
753 maInnerBorderSize(),
754 maOuterBorderSize(),
755 maTotalBorderSize()
757 if (rpTheme == nullptr)
758 return;
760 mpTopLeft = GetBitmap(rpTheme, rsStyleName, "TopLeft");
761 mpTop = GetBitmap(rpTheme, rsStyleName, "Top");
762 mpTopRight = GetBitmap(rpTheme, rsStyleName, "TopRight");
763 mpLeft = GetBitmap(rpTheme, rsStyleName,"Left");
764 mpRight = GetBitmap(rpTheme, rsStyleName, "Right");
765 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, "BottomLeft");
766 mpBottom = GetBitmap(rpTheme, rsStyleName, "Bottom");
767 mpBottomRight = GetBitmap(rpTheme, rsStyleName, "BottomRight");
768 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, "BottomCallout");
770 // Get font description.
771 mpFont = rpTheme->GetFont(rsStyleName);
773 OUString sAnchor ("Left");
774 if (mpFont)
776 sAnchor = mpFont->msAnchor;
777 mnFontXOffset = mpFont->mnXOffset;
778 mnFontYOffset = mpFont->mnYOffset;
781 if ( sAnchor == "Left" )
782 meFontAnchor = Anchor::Left;
783 else if ( sAnchor == "Right" )
784 meFontAnchor = Anchor::Right;
785 else
786 meFontAnchor = Anchor::Center;
788 // Get border sizes.
791 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
792 OSL_ASSERT(aInnerBorder.size()==4);
793 maInnerBorderSize.mnLeft = aInnerBorder[0];
794 maInnerBorderSize.mnTop = aInnerBorder[1];
795 maInnerBorderSize.mnRight = aInnerBorder[2];
796 maInnerBorderSize.mnBottom = aInnerBorder[3];
798 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
799 OSL_ASSERT(aOuterBorder.size()==4);
800 maOuterBorderSize.mnLeft = aOuterBorder[0];
801 maOuterBorderSize.mnTop = aOuterBorder[1];
802 maOuterBorderSize.mnRight = aOuterBorder[2];
803 maOuterBorderSize.mnBottom = aOuterBorder[3];
805 catch(beans::UnknownPropertyException&)
807 OSL_ASSERT(false);
810 UpdateBorderSizes();
813 awt::Rectangle RendererPaneStyle::AddBorder (
814 const awt::Rectangle& rBox,
815 const drawing::framework::BorderType eBorderType) const
817 const BorderSize* pBorderSize = nullptr;
818 switch (eBorderType)
820 case drawing::framework::BorderType_INNER_BORDER:
821 pBorderSize = &maInnerBorderSize;
822 break;
823 case drawing::framework::BorderType_OUTER_BORDER:
824 pBorderSize = &maOuterBorderSize;
825 break;
826 case drawing::framework::BorderType_TOTAL_BORDER:
827 pBorderSize = &maTotalBorderSize;
828 break;
829 default:
830 return rBox;
832 return awt::Rectangle (
833 rBox.X - pBorderSize->mnLeft,
834 rBox.Y - pBorderSize->mnTop,
835 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
836 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
839 awt::Rectangle RendererPaneStyle::RemoveBorder (
840 const awt::Rectangle& rBox,
841 const css::drawing::framework::BorderType eBorderType) const
843 const BorderSize* pBorderSize = nullptr;
844 switch (eBorderType)
846 case drawing::framework::BorderType_INNER_BORDER:
847 pBorderSize = &maInnerBorderSize;
848 break;
849 case drawing::framework::BorderType_OUTER_BORDER:
850 pBorderSize = &maOuterBorderSize;
851 break;
852 case drawing::framework::BorderType_TOTAL_BORDER:
853 pBorderSize = &maTotalBorderSize;
854 break;
855 default:
856 return rBox;
858 return awt::Rectangle (
859 rBox.X + pBorderSize->mnLeft,
860 rBox.Y + pBorderSize->mnTop,
861 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
862 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
865 Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
866 const Reference<rendering::XCanvas>& rxCanvas) const
868 if (mpFont)
870 mpFont->PrepareFont(rxCanvas);
871 return mpFont->mxFont;
873 return Reference<rendering::XCanvasFont>();
876 void RendererPaneStyle::UpdateBorderSizes()
878 maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
879 maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop;
880 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
881 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
884 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
885 const std::shared_ptr<PresenterTheme>& rpTheme,
886 const OUString& rsStyleName,
887 const OUString& rsBitmapName)
889 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
890 if (pDescriptor)
891 return pDescriptor;
892 else
893 return mpEmpty;
896 } // end of anonymous namespace
898 } // end of namespace ::sd::presenter
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */