Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sdext / source / presenter / PresenterPaneBorderPainter.cxx
blob30e303337478113bd841fa7f18c4cbe1a84270cb
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 <vcl/svapp.hxx>
21 #include "PresenterPaneBorderPainter.hxx"
22 #include "PresenterCanvasHelper.hxx"
23 #include "PresenterConfigurationAccess.hxx"
24 #include "PresenterGeometryHelper.hxx"
25 #include "PresenterTheme.hxx"
26 #include <com/sun/star/awt/FontDescriptor.hpp>
27 #include <com/sun/star/awt/Point.hpp>
28 #include <com/sun/star/awt/Rectangle.hpp>
29 #include <com/sun/star/awt/SimpleFontMetric.hpp>
30 #include <com/sun/star/awt/XFont.hpp>
31 #include <com/sun/star/drawing/XPresenterHelper.hpp>
32 #include <com/sun/star/graphic/XGraphic.hpp>
33 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
34 #include <com/sun/star/rendering/CompositeOperation.hpp>
35 #include <com/sun/star/rendering/FillRule.hpp>
36 #include <com/sun/star/rendering/TextDirection.hpp>
37 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
38 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
39 #include <map>
40 #include <memory>
41 #include <vector>
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
46 namespace sdext { namespace presenter {
48 namespace {
49 class BorderSize
51 public:
52 BorderSize();
53 sal_Int32 mnLeft;
54 sal_Int32 mnTop;
55 sal_Int32 mnRight;
56 sal_Int32 mnBottom;
59 class RendererPaneStyle
61 public:
62 RendererPaneStyle (
63 const std::shared_ptr<PresenterTheme>& rpTheme,
64 const OUString& rsStyleName);
66 awt::Rectangle AddBorder (
67 const awt::Rectangle& rBox,
68 drawing::framework::BorderType eBorderType) const;
69 awt::Rectangle RemoveBorder (
70 const awt::Rectangle& rBox,
71 drawing::framework::BorderType eBorderType) const;
72 Reference<rendering::XCanvasFont> const & GetFont (
73 const Reference<rendering::XCanvas>& rxCanvas) const;
75 SharedBitmapDescriptor mpTopLeft;
76 SharedBitmapDescriptor mpTop;
77 SharedBitmapDescriptor mpTopRight;
78 SharedBitmapDescriptor mpLeft;
79 SharedBitmapDescriptor mpRight;
80 SharedBitmapDescriptor mpBottomLeft;
81 SharedBitmapDescriptor mpBottom;
82 SharedBitmapDescriptor mpBottomRight;
83 SharedBitmapDescriptor mpBottomCallout;
84 SharedBitmapDescriptor mpEmpty;
85 PresenterTheme::SharedFontDescriptor mpFont;
86 sal_Int32 mnFontXOffset;
87 sal_Int32 mnFontYOffset;
88 enum class Anchor { Left, Right, Center };
89 Anchor meFontAnchor;
90 BorderSize maInnerBorderSize;
91 BorderSize maOuterBorderSize;
92 BorderSize maTotalBorderSize;
93 enum Side { Left, Top, Right, Bottom };
94 private:
95 void UpdateBorderSizes();
96 SharedBitmapDescriptor GetBitmap(
97 const std::shared_ptr<PresenterTheme>& rpTheme,
98 const OUString& rsStyleName,
99 const OUString& rsBitmapName);
103 class PresenterPaneBorderPainter::Renderer
105 public:
106 Renderer (
107 const Reference<XComponentContext>& rxContext,
108 const std::shared_ptr<PresenterTheme>& rpTheme);
110 void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas);
111 void PaintBorder (
112 const OUString& rsTitle,
113 const awt::Rectangle& rBBox,
114 const awt::Rectangle& rUpdateBox,
115 const OUString& rsPaneURL);
116 void PaintTitle (
117 const OUString& rsTitle,
118 const std::shared_ptr<RendererPaneStyle>& rpStyle,
119 const awt::Rectangle& rUpdateBox,
120 const awt::Rectangle& rOuterBox,
121 const awt::Rectangle& rInnerBox);
122 void SetupClipping (
123 const awt::Rectangle& rUpdateBox,
124 const awt::Rectangle& rOuterBox,
125 const OUString& rsPaneStyleName);
126 std::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL);
127 void SetCalloutAnchor (
128 const awt::Point& rCalloutAnchor);
130 private:
131 std::shared_ptr<PresenterTheme> mpTheme;
132 typedef ::std::map<OUString, std::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer;
133 RendererPaneStyleContainer maRendererPaneStyles;
134 Reference<rendering::XCanvas> mxCanvas;
135 Reference<drawing::XPresenterHelper> mxPresenterHelper;
136 css::rendering::ViewState maViewState;
137 Reference<rendering::XPolyPolygon2D> mxViewStateClip;
138 bool mbHasCallout;
139 awt::Point maCalloutAnchor;
141 void PaintBitmap(
142 const awt::Rectangle& rBox,
143 const awt::Rectangle& rUpdateBox,
144 const sal_Int32 nXPosition,
145 const sal_Int32 nYPosition,
146 const sal_Int32 nStartOffset,
147 const sal_Int32 nEndOffset,
148 const bool bExpand,
149 const SharedBitmapDescriptor& rpBitmap);
152 // ===== PresenterPaneBorderPainter ===========================================
154 PresenterPaneBorderPainter::PresenterPaneBorderPainter (
155 const Reference<XComponentContext>& rxContext)
156 : PresenterPaneBorderPainterInterfaceBase(m_aMutex),
157 mxContext(rxContext),
158 mpTheme(),
159 mpRenderer()
163 PresenterPaneBorderPainter::~PresenterPaneBorderPainter()
167 //----- XPaneBorderPainter ----------------------------------------------------
169 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder (
170 const OUString& rsPaneBorderStyleName,
171 const css::awt::Rectangle& rRectangle,
172 drawing::framework::BorderType eBorderType)
174 ThrowIfDisposed();
176 ProvideTheme();
178 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
181 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder (
182 const OUString& rsPaneBorderStyleName,
183 const css::awt::Rectangle& rRectangle,
184 drawing::framework::BorderType eBorderType)
186 ThrowIfDisposed();
188 ProvideTheme();
190 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
193 void SAL_CALL PresenterPaneBorderPainter::paintBorder (
194 const OUString& rsPaneBorderStyleName,
195 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
196 const css::awt::Rectangle& rOuterBorderRectangle,
197 const css::awt::Rectangle& rRepaintArea,
198 const OUString& rsTitle)
200 ThrowIfDisposed();
202 // Early reject paints completely outside the repaint area.
203 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
204 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
205 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
206 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
208 return;
210 ProvideTheme(rxCanvas);
212 if (mpRenderer.get() != nullptr)
214 mpRenderer->SetCanvas(rxCanvas);
215 mpRenderer->SetupClipping(
216 rRepaintArea,
217 rOuterBorderRectangle,
218 rsPaneBorderStyleName);
219 mpRenderer->PaintBorder(
220 rsTitle,
221 rOuterBorderRectangle,
222 rRepaintArea,
223 rsPaneBorderStyleName);
227 void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout (
228 const OUString& rsPaneBorderStyleName,
229 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
230 const css::awt::Rectangle& rOuterBorderRectangle,
231 const css::awt::Rectangle& rRepaintArea,
232 const OUString& rsTitle,
233 const css::awt::Point& rCalloutAnchor)
235 ThrowIfDisposed();
237 // Early reject paints completely outside the repaint area.
238 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
239 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
240 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
241 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
243 return;
245 ProvideTheme(rxCanvas);
247 if (mpRenderer.get() != nullptr)
249 mpRenderer->SetCanvas(rxCanvas);
250 mpRenderer->SetupClipping(
251 rRepaintArea,
252 rOuterBorderRectangle,
253 rsPaneBorderStyleName);
254 mpRenderer->SetCalloutAnchor(rCalloutAnchor);
255 mpRenderer->PaintBorder(
256 rsTitle,
257 rOuterBorderRectangle,
258 rRepaintArea,
259 rsPaneBorderStyleName);
263 awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset (
264 const OUString& rsPaneBorderStyleName)
266 ThrowIfDisposed();
267 ProvideTheme();
268 if (mpRenderer.get() != nullptr)
270 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
271 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
272 if (pRendererPaneStyle.get() != nullptr
273 && pRendererPaneStyle->mpBottomCallout.get() != nullptr)
275 return awt::Point (
277 pRendererPaneStyle->mpBottomCallout->mnHeight
278 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
282 return awt::Point(0,0);
286 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
288 bool bModified (false);
290 if ( ! mxContext.is())
291 return false;
293 if (mpTheme.get() != nullptr)
295 // Check if the theme already has a canvas.
296 if ( ! mpTheme->HasCanvas())
298 mpTheme->ProvideCanvas(rxCanvas);
299 bModified = true;
302 else
304 mpTheme.reset(new PresenterTheme(mxContext, rxCanvas));
305 bModified = true;
308 if (mpTheme.get() != nullptr && bModified)
310 if (mpRenderer.get() == nullptr)
311 mpRenderer.reset(new Renderer(mxContext, mpTheme));
312 else
313 mpRenderer->SetCanvas(rxCanvas);
316 return bModified;
319 void PresenterPaneBorderPainter::ProvideTheme()
321 if (mpTheme.get() == nullptr)
323 // Create a theme without bitmaps (no canvas => no bitmaps).
324 ProvideTheme(nullptr);
326 // When there already is a theme then without a canvas we can not
327 // add anything new.
330 void PresenterPaneBorderPainter::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
332 mpTheme = rpTheme;
333 if (mpRenderer.get() == nullptr)
334 mpRenderer.reset(new Renderer(mxContext, mpTheme));
337 awt::Rectangle PresenterPaneBorderPainter::AddBorder (
338 const OUString& rsPaneURL,
339 const awt::Rectangle& rInnerBox,
340 const css::drawing::framework::BorderType eBorderType) const
342 if (mpRenderer.get() != nullptr)
344 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
345 if (pRendererPaneStyle.get() != nullptr)
346 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
348 return rInnerBox;
351 awt::Rectangle PresenterPaneBorderPainter::RemoveBorder (
352 const OUString& rsPaneURL,
353 const css::awt::Rectangle& rOuterBox,
354 const css::drawing::framework::BorderType eBorderType) const
356 if (mpRenderer.get() != nullptr)
358 const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
359 if (pRendererPaneStyle.get() != nullptr)
360 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
362 return rOuterBox;
365 void PresenterPaneBorderPainter::ThrowIfDisposed() const
367 if (rBHelper.bDisposed || rBHelper.bInDispose)
369 throw lang::DisposedException (
370 "PresenterPaneBorderPainter object has already been disposed",
371 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
375 //===== PresenterPaneBorderPainter::Renderer =====================================
377 PresenterPaneBorderPainter::Renderer::Renderer (
378 const Reference<XComponentContext>& rxContext,
379 const std::shared_ptr<PresenterTheme>& rpTheme)
380 : mpTheme(rpTheme),
381 maRendererPaneStyles(),
382 mxCanvas(),
383 mxPresenterHelper(),
384 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
385 mxViewStateClip(),
386 mbHasCallout(false),
387 maCalloutAnchor()
389 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
390 if (xFactory.is())
392 mxPresenterHelper.set(
393 xFactory->createInstanceWithContext(
394 "com.sun.star.comp.Draw.PresenterHelper",
395 rxContext),
396 UNO_QUERY_THROW);
400 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
402 if (mxCanvas != rxCanvas)
404 mxCanvas = rxCanvas;
408 void PresenterPaneBorderPainter::Renderer::PaintBorder (
409 const OUString& rsTitle,
410 const awt::Rectangle& rBBox,
411 const awt::Rectangle& rUpdateBox,
412 const OUString& rsPaneURL)
414 if ( ! mxCanvas.is())
415 return;
417 // Create the outer and inner border of the, ahm, border.
418 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
419 if (pStyle.get() == nullptr)
420 return;
422 awt::Rectangle aOuterBox (rBBox);
423 awt::Rectangle aCenterBox (
424 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
425 awt::Rectangle aInnerBox (
426 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
428 // Prepare references for all used bitmaps.
429 SharedBitmapDescriptor pTop (pStyle->mpTop);
430 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
431 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
432 SharedBitmapDescriptor pLeft (pStyle->mpLeft);
433 SharedBitmapDescriptor pRight (pStyle->mpRight);
434 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
435 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
436 SharedBitmapDescriptor pBottom (pStyle->mpBottom);
438 // Paint the sides.
439 PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
440 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop);
441 PaintBitmap(aCenterBox, rUpdateBox, -1,0,
442 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft);
443 PaintBitmap(aCenterBox, rUpdateBox, +1,0,
444 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight);
445 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
447 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
448 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
449 - (aCenterBox.X - aOuterBox.X));
450 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
451 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
452 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
453 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
454 // Paint bottom callout.
455 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout);
456 // Paint regular bottom bitmap left and right.
457 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
458 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom);
459 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
460 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom);
462 else
464 // Stretch the bottom bitmap over the full width.
465 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
466 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom);
469 // Paint the corners.
470 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft);
471 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight);
472 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft);
473 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight);
475 // Paint the title.
476 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox);
478 // In a double buffering environment request to make the changes visible.
479 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
480 if (xSpriteCanvas.is())
481 xSpriteCanvas->updateScreen(false);
484 void PresenterPaneBorderPainter::Renderer::PaintTitle (
485 const OUString& rsTitle,
486 const std::shared_ptr<RendererPaneStyle>& rpStyle,
487 const awt::Rectangle& rUpdateBox,
488 const awt::Rectangle& rOuterBox,
489 const awt::Rectangle& rInnerBox)
491 if ( ! mxCanvas.is())
492 return;
494 if (rsTitle.isEmpty())
495 return;
497 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
498 if ( ! xFont.is())
499 return;
501 rendering::StringContext aContext (
502 rsTitle,
504 rsTitle.getLength());
505 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
506 aContext,
507 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
508 0));
509 if ( ! xLayout.is())
510 return;
512 /// this is responsible of the texts above the slide windows
513 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
514 const double nTextHeight = aBox.Y2 - aBox.Y1;
515 const double nTextWidth = aBox.X1 + aBox.X2;
516 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
517 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
518 if (nY >= rInnerBox.Y)
519 nY = rInnerBox.Y - 1;
520 double nX;
521 switch (rpStyle->meFontAnchor)
523 case RendererPaneStyle::Anchor::Left:
524 nX = rInnerBox.X;
525 break;
526 case RendererPaneStyle::Anchor::Right:
527 nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
528 break;
529 default: // RendererPaneStyle::Anchor::Center
530 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
531 break;
533 nX += rpStyle->mnFontXOffset;
534 nY += rpStyle->mnFontYOffset;
536 if (rUpdateBox.X >= nX+nTextWidth
537 || rUpdateBox.Y >= nY+nTextHeight
538 || rUpdateBox.X+rUpdateBox.Width <= nX
539 || rUpdateBox.Y+rUpdateBox.Height <= nY)
541 return;
544 rendering::RenderState aRenderState(
545 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
546 nullptr,
547 Sequence<double>(4),
548 rendering::CompositeOperation::SOURCE);
550 PresenterCanvasHelper::SetDeviceColor(
551 aRenderState,
552 rpStyle->mpFont->mnColor);
554 mxCanvas->drawTextLayout (
555 xLayout,
556 maViewState,
557 aRenderState);
560 std::shared_ptr<RendererPaneStyle>
561 PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL)
563 OSL_ASSERT(mpTheme.get()!=nullptr);
565 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
566 if (iStyle == maRendererPaneStyles.end())
568 OUString sPaneStyleName ("DefaultRendererPaneStyle");
570 // Get pane layout name for resource URL.
571 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
572 if (!sStyleName.isEmpty())
573 sPaneStyleName = sStyleName;
575 // Create a new pane style object and initialize it with bitmaps.
576 std::shared_ptr<RendererPaneStyle> pStyle (
577 new RendererPaneStyle(mpTheme,sPaneStyleName));
578 iStyle = maRendererPaneStyles.emplace(rsResourceURL, pStyle).first;
580 if (iStyle != maRendererPaneStyles.end())
581 return iStyle->second;
582 else
583 return std::shared_ptr<RendererPaneStyle>();
586 void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor (
587 const awt::Point& rCalloutAnchor)
589 mbHasCallout = true;
590 maCalloutAnchor = rCalloutAnchor;
593 void PresenterPaneBorderPainter::Renderer::PaintBitmap(
594 const awt::Rectangle& rBox,
595 const awt::Rectangle& rUpdateBox,
596 const sal_Int32 nXPosition,
597 const sal_Int32 nYPosition,
598 const sal_Int32 nStartOffset,
599 const sal_Int32 nEndOffset,
600 const bool bExpand,
601 const SharedBitmapDescriptor& rpBitmap)
603 bool bUseCanvas (mxCanvas.is());
604 if ( ! bUseCanvas)
605 return;
607 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
608 return;
610 Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY);
611 if ( ! xBitmap.is())
612 return;
614 // Calculate position, and for side bitmaps, the size.
615 sal_Int32 nX = 0;
616 sal_Int32 nY = 0;
617 sal_Int32 nW = rpBitmap->mnWidth;
618 sal_Int32 nH = rpBitmap->mnHeight;
619 if (nXPosition < 0)
621 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
623 else if (nXPosition > 0)
625 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
627 else
629 nX = rBox.X + nStartOffset;
630 if (bExpand)
631 nW = rBox.Width - nStartOffset + nEndOffset;
634 if (nYPosition < 0)
636 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
638 else if (nYPosition > 0)
640 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
642 else
644 nY = rBox.Y + nStartOffset;
645 if (bExpand)
646 nH = rBox.Height - nStartOffset + nEndOffset;
649 // Do not paint when bitmap area does not intersect with update box.
650 if (nX >= rUpdateBox.X + rUpdateBox.Width
651 || nX+nW <= rUpdateBox.X
652 || nY >= rUpdateBox.Y + rUpdateBox.Height
653 || nY+nH <= rUpdateBox.Y)
655 return;
659 Reference<rendering::XBitmap> xMaskedBitmap (
660 PresenterBitmapHelper::FillMaskedWithColor (
661 mxCanvas,
662 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
663 rBitmap.mxMaskBitmap,
664 0x00ff0000,
665 rBackgroundBitmap.maReplacementColor));
666 if (xMaskedBitmap.is())
667 xBitmap = xMaskedBitmap;
668 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
670 const static sal_Int32 nOutsideMaskColor (0x00ff0000);
671 Reference<rendering::XIntegerBitmap> xMask (
672 mxPresenterHelper->createMask(
673 mxCanvas,
674 rBitmap.mxMaskBitmap,
675 nOutsideMaskColor,
676 false));
677 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
678 mxCanvas,
679 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
680 xMask,
681 rBackgroundBitmap.maReplacementColor);
684 rendering::RenderState aRenderState (
685 geometry::AffineMatrix2D(
686 double(nW)/rpBitmap->mnWidth, 0, nX,
687 0, double(nH)/rpBitmap->mnHeight, nY),
688 nullptr,
689 Sequence<double>(4),
690 rendering::CompositeOperation::OVER);
692 if (xBitmap.is())
693 mxCanvas->drawBitmap(
694 xBitmap,
695 maViewState,
696 aRenderState);
699 void PresenterPaneBorderPainter::Renderer::SetupClipping (
700 const awt::Rectangle& rUpdateBox,
701 const awt::Rectangle& rOuterBox,
702 const OUString& rsPaneStyleName)
704 mxViewStateClip = nullptr;
705 maViewState.Clip = nullptr;
707 if ( ! mxCanvas.is())
708 return;
710 std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
711 if (pStyle.get() == nullptr)
713 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
714 rUpdateBox,
715 mxCanvas->getDevice());
717 else
719 awt::Rectangle aInnerBox (
720 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
721 ::std::vector<awt::Rectangle> aRectangles;
722 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox));
723 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox));
724 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
725 aRectangles,
726 mxCanvas->getDevice());
727 if (mxViewStateClip.is())
728 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
730 maViewState.Clip = mxViewStateClip;
733 namespace {
735 //===== BorderSize ============================================================
737 BorderSize::BorderSize()
738 : mnLeft(0),
739 mnTop(0),
740 mnRight(0),
741 mnBottom(0)
745 //===== RendererPaneStyle ============================================================
747 RendererPaneStyle::RendererPaneStyle (
748 const std::shared_ptr<PresenterTheme>& rpTheme,
749 const OUString& rsStyleName)
750 : mpTopLeft(),
751 mpTop(),
752 mpTopRight(),
753 mpLeft(),
754 mpRight(),
755 mpBottomLeft(),
756 mpBottom(),
757 mpBottomRight(),
758 mpBottomCallout(),
759 mpEmpty(new PresenterBitmapDescriptor()),
760 mpFont(),
761 mnFontXOffset(0),
762 mnFontYOffset(0),
763 meFontAnchor(Anchor::Center),
764 maInnerBorderSize(),
765 maOuterBorderSize(),
766 maTotalBorderSize()
768 if (rpTheme.get() != nullptr)
770 mpTopLeft = GetBitmap(rpTheme, rsStyleName, "TopLeft");
771 mpTop = GetBitmap(rpTheme, rsStyleName, "Top");
772 mpTopRight = GetBitmap(rpTheme, rsStyleName, "TopRight");
773 mpLeft = GetBitmap(rpTheme, rsStyleName,"Left");
774 mpRight = GetBitmap(rpTheme, rsStyleName, "Right");
775 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, "BottomLeft");
776 mpBottom = GetBitmap(rpTheme, rsStyleName, "Bottom");
777 mpBottomRight = GetBitmap(rpTheme, rsStyleName, "BottomRight");
778 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, "BottomCallout");
780 // Get font description.
781 mpFont = rpTheme->GetFont(rsStyleName);
783 OUString sAnchor ("Left");
784 if (mpFont.get() != nullptr)
786 sAnchor = mpFont->msAnchor;
787 mnFontXOffset = mpFont->mnXOffset;
788 mnFontYOffset = mpFont->mnYOffset;
791 if ( sAnchor == "Left" )
792 meFontAnchor = Anchor::Left;
793 else if ( sAnchor == "Right" )
794 meFontAnchor = Anchor::Right;
795 else
796 meFontAnchor = Anchor::Center;
798 // Get border sizes.
801 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
802 OSL_ASSERT(aInnerBorder.size()==4);
803 maInnerBorderSize.mnLeft = aInnerBorder[0];
804 maInnerBorderSize.mnTop = aInnerBorder[1];
805 maInnerBorderSize.mnRight = aInnerBorder[2];
806 maInnerBorderSize.mnBottom = aInnerBorder[3];
808 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
809 OSL_ASSERT(aOuterBorder.size()==4);
810 maOuterBorderSize.mnLeft = aOuterBorder[0];
811 maOuterBorderSize.mnTop = aOuterBorder[1];
812 maOuterBorderSize.mnRight = aOuterBorder[2];
813 maOuterBorderSize.mnBottom = aOuterBorder[3];
815 catch(beans::UnknownPropertyException&)
817 OSL_ASSERT(false);
820 UpdateBorderSizes();
824 awt::Rectangle RendererPaneStyle::AddBorder (
825 const awt::Rectangle& rBox,
826 const drawing::framework::BorderType eBorderType) const
828 const BorderSize* pBorderSize = nullptr;
829 switch (eBorderType)
831 case drawing::framework::BorderType_INNER_BORDER:
832 pBorderSize = &maInnerBorderSize;
833 break;
834 case drawing::framework::BorderType_OUTER_BORDER:
835 pBorderSize = &maOuterBorderSize;
836 break;
837 case drawing::framework::BorderType_TOTAL_BORDER:
838 pBorderSize = &maTotalBorderSize;
839 break;
840 default:
841 return rBox;
843 return awt::Rectangle (
844 rBox.X - pBorderSize->mnLeft,
845 rBox.Y - pBorderSize->mnTop,
846 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
847 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
850 awt::Rectangle RendererPaneStyle::RemoveBorder (
851 const awt::Rectangle& rBox,
852 const css::drawing::framework::BorderType eBorderType) const
854 const BorderSize* pBorderSize = nullptr;
855 switch (eBorderType)
857 case drawing::framework::BorderType_INNER_BORDER:
858 pBorderSize = &maInnerBorderSize;
859 break;
860 case drawing::framework::BorderType_OUTER_BORDER:
861 pBorderSize = &maOuterBorderSize;
862 break;
863 case drawing::framework::BorderType_TOTAL_BORDER:
864 pBorderSize = &maTotalBorderSize;
865 break;
866 default:
867 return rBox;
869 return awt::Rectangle (
870 rBox.X + pBorderSize->mnLeft,
871 rBox.Y + pBorderSize->mnTop,
872 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
873 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
876 Reference<rendering::XCanvasFont> const & RendererPaneStyle::GetFont (
877 const Reference<rendering::XCanvas>& rxCanvas) const
879 if (mpFont.get() != nullptr)
880 mpFont->PrepareFont(rxCanvas);
881 return mpFont->mxFont;
884 void RendererPaneStyle::UpdateBorderSizes()
886 maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
887 maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop;
888 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
889 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
892 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
893 const std::shared_ptr<PresenterTheme>& rpTheme,
894 const OUString& rsStyleName,
895 const OUString& rsBitmapName)
897 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
898 if (pDescriptor.get() != nullptr)
899 return pDescriptor;
900 else
901 return mpEmpty;
904 } // end of anonymous namespace
906 } } // end of namespace ::sd::presenter
908 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */