LibreOffice Module sdext (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 <vector>
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
37 
38 namespace sdext::presenter {
39 
40 namespace {
41  class BorderSize
42  {
43  public:
44  BorderSize();
45  sal_Int32 mnLeft;
46  sal_Int32 mnTop;
47  sal_Int32 mnRight;
48  sal_Int32 mnBottom;
49  };
50 
51  class RendererPaneStyle
52  {
53  public:
54  RendererPaneStyle (
55  const std::shared_ptr<PresenterTheme>& rpTheme,
56  const OUString& rsStyleName);
57 
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;
66 
78  sal_Int32 mnFontXOffset;
79  sal_Int32 mnFontYOffset;
80  enum class Anchor { Left, Right, Center };
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);
91  };
92 }
93 
95 {
96 public:
97  Renderer (
98  const Reference<XComponentContext>& rxContext,
99  const std::shared_ptr<PresenterTheme>& rpTheme);
100 
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);
120 
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;
130  awt::Point maCalloutAnchor;
131 
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);
141 };
142 
143 // ===== PresenterPaneBorderPainter ===========================================
144 
146  const Reference<XComponentContext>& rxContext)
148  mxContext(rxContext),
149  mpTheme(),
150  mpRenderer()
151 {
152 }
153 
155 {
156 }
157 
158 //----- XPaneBorderPainter ----------------------------------------------------
159 
160 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder (
161  const OUString& rsPaneBorderStyleName,
162  const css::awt::Rectangle& rRectangle,
163  drawing::framework::BorderType eBorderType)
164 {
165  ThrowIfDisposed();
166 
167  ProvideTheme();
168 
169  return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
170 }
171 
173  const OUString& rsPaneBorderStyleName,
174  const css::awt::Rectangle& rRectangle,
175  drawing::framework::BorderType eBorderType)
176 {
177  ThrowIfDisposed();
178 
179  ProvideTheme();
180 
181  return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
182 }
183 
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)
190 {
191  ThrowIfDisposed();
192 
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)
198  {
199  return;
200  }
201  ProvideTheme(rxCanvas);
202 
203  if (mpRenderer == nullptr)
204  return;
205 
206  mpRenderer->SetCanvas(rxCanvas);
207  mpRenderer->SetupClipping(
208  rRepaintArea,
209  rOuterBorderRectangle,
210  rsPaneBorderStyleName);
211  mpRenderer->PaintBorder(
212  rsTitle,
213  rOuterBorderRectangle,
214  rRepaintArea,
215  rsPaneBorderStyleName);
216 }
217 
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)
225 {
226  ThrowIfDisposed();
227 
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)
233  {
234  return;
235  }
236  ProvideTheme(rxCanvas);
237 
238  if (mpRenderer == nullptr)
239  return;
240 
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);
252 }
253 
255  const OUString& rsPaneBorderStyleName)
256 {
257  ThrowIfDisposed();
258  ProvideTheme();
259  if (mpRenderer != nullptr)
260  {
261  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
262  mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
263  if (pRendererPaneStyle != nullptr && pRendererPaneStyle->mpBottomCallout)
264  {
265  return awt::Point (
266  0,
267  pRendererPaneStyle->mpBottomCallout->mnHeight
268  - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
269  }
270  }
271 
272  return awt::Point(0,0);
273 }
274 
275 
276 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
277 {
278  bool bModified (false);
279 
280  if ( ! mxContext.is())
281  return false;
282 
283  if (mpTheme != nullptr)
284  {
285  // Check if the theme already has a canvas.
286  if ( ! mpTheme->HasCanvas())
287  {
288  mpTheme->ProvideCanvas(rxCanvas);
289  bModified = true;
290  }
291  }
292  else
293  {
294  mpTheme = std::make_shared<PresenterTheme>(mxContext, rxCanvas);
295  bModified = true;
296  }
297 
298  if (bModified)
299  {
300  if (mpRenderer == nullptr)
301  mpRenderer.reset(new Renderer(mxContext, mpTheme));
302  else
303  mpRenderer->SetCanvas(rxCanvas);
304  }
305 
306  return bModified;
307 }
308 
310 {
311  if (mpTheme == nullptr)
312  {
313  // Create a theme without bitmaps (no canvas => no bitmaps).
314  ProvideTheme(nullptr);
315  }
316  // When there already is a theme then without a canvas we can not
317  // add anything new.
318 }
319 
320 void PresenterPaneBorderPainter::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
321 {
322  mpTheme = rpTheme;
323  if (mpRenderer == nullptr)
324  mpRenderer.reset(new Renderer(mxContext, mpTheme));
325 }
326 
328  const OUString& rsPaneURL,
329  const awt::Rectangle& rInnerBox,
330  const css::drawing::framework::BorderType eBorderType) const
331 {
332  if (mpRenderer != nullptr)
333  {
334  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
335  if (pRendererPaneStyle != nullptr)
336  return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
337  }
338  return rInnerBox;
339 }
340 
342  const OUString& rsPaneURL,
343  const css::awt::Rectangle& rOuterBox,
344  const css::drawing::framework::BorderType eBorderType) const
345 {
346  if (mpRenderer != nullptr)
347  {
348  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
349  if (pRendererPaneStyle != nullptr)
350  return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
351  }
352  return rOuterBox;
353 }
354 
356 {
357  if (rBHelper.bDisposed || rBHelper.bInDispose)
358  {
359  throw lang::DisposedException (
360  "PresenterPaneBorderPainter object has already been disposed",
361  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
362  }
363 }
364 
365 //===== PresenterPaneBorderPainter::Renderer =====================================
366 
368  const Reference<XComponentContext>& rxContext,
369  const std::shared_ptr<PresenterTheme>& rpTheme)
370  : mpTheme(rpTheme),
371  maRendererPaneStyles(),
372  mxCanvas(),
374  maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
375  mxViewStateClip(),
376  mbHasCallout(false),
377  maCalloutAnchor()
378 {
379  Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
380  if (xFactory.is())
381  {
382  mxPresenterHelper.set(
383  xFactory->createInstanceWithContext(
384  "com.sun.star.comp.Draw.PresenterHelper",
385  rxContext),
386  UNO_QUERY_THROW);
387  }
388 }
389 
390 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
391 {
392  if (mxCanvas != rxCanvas)
393  {
394  mxCanvas = rxCanvas;
395  }
396 }
397 
399  const OUString& rsTitle,
400  const awt::Rectangle& rBBox,
401  const awt::Rectangle& rUpdateBox,
402  const OUString& rsPaneURL)
403 {
404  if ( ! mxCanvas.is())
405  return;
406 
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;
411 
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));
417 
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);
427 
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())
436  {
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);
451  }
452  else
453  {
454  // Stretch the bottom bitmap over the full width.
455  PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
456  pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom);
457  }
458 
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);
464 
465  // Paint the title.
466  PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox);
467 
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);
472 }
473 
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)
480 {
481  if ( ! mxCanvas.is())
482  return;
483 
484  if (rsTitle.isEmpty())
485  return;
486 
487  Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
488  if ( ! xFont.is())
489  return;
490 
491  rendering::StringContext aContext (
492  rsTitle,
493  0,
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;
501 
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)
512  {
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;
522  }
523  nX += rpStyle->mnFontXOffset;
524  nY += rpStyle->mnFontYOffset;
525 
526  if (rUpdateBox.X >= nX+nTextWidth
527  || rUpdateBox.Y >= nY+nTextHeight
528  || rUpdateBox.X+rUpdateBox.Width <= nX
529  || rUpdateBox.Y+rUpdateBox.Height <= nY)
530  {
531  return;
532  }
533 
534  rendering::RenderState aRenderState(
535  geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
536  nullptr,
537  Sequence<double>(4),
538  rendering::CompositeOperation::SOURCE);
539 
541  aRenderState,
542  rpStyle->mpFont->mnColor);
543 
544  mxCanvas->drawTextLayout (
545  xLayout,
546  maViewState,
547  aRenderState);
548 }
549 
550 std::shared_ptr<RendererPaneStyle>
552 {
553  OSL_ASSERT(mpTheme != nullptr);
554 
555  RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
556  if (iStyle == maRendererPaneStyles.end())
557  {
558  OUString sPaneStyleName ("DefaultRendererPaneStyle");
559 
560  // Get pane layout name for resource URL.
561  const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
562  if (!sStyleName.isEmpty())
563  sPaneStyleName = sStyleName;
564 
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;
568  }
569  if (iStyle != maRendererPaneStyles.end())
570  return iStyle->second;
571  else
572  return std::shared_ptr<RendererPaneStyle>();
573 }
574 
576  const awt::Point& rCalloutAnchor)
577 {
578  mbHasCallout = true;
579  maCalloutAnchor = rCalloutAnchor;
580 }
581 
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)
591 {
592  bool bUseCanvas (mxCanvas.is());
593  if ( ! bUseCanvas)
594  return;
595 
596  if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
597  return;
598 
599  Reference<rendering::XBitmap> xBitmap = rpBitmap->GetNormalBitmap();
600  if ( ! xBitmap.is())
601  return;
602 
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)
609  {
610  nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
611  }
612  else if (nXPosition > 0)
613  {
614  nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
615  }
616  else
617  {
618  nX = rBox.X + nStartOffset;
619  if (bExpand)
620  nW = rBox.Width - nStartOffset + nEndOffset;
621  }
622 
623  if (nYPosition < 0)
624  {
625  nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
626  }
627  else if (nYPosition > 0)
628  {
629  nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
630  }
631  else
632  {
633  nY = rBox.Y + nStartOffset;
634  if (bExpand)
635  nH = rBox.Height - nStartOffset + nEndOffset;
636  }
637 
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)
643  {
644  return;
645  }
646 
647  /*
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())
658  {
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);
671  }
672  */
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);
680 
681  if (xBitmap.is())
682  mxCanvas->drawBitmap(
683  xBitmap,
684  maViewState,
685  aRenderState);
686 }
687 
689  const awt::Rectangle& rUpdateBox,
690  const awt::Rectangle& rOuterBox,
691  const OUString& rsPaneStyleName)
692 {
693  mxViewStateClip = nullptr;
694  maViewState.Clip = nullptr;
695 
696  if ( ! mxCanvas.is())
697  return;
698 
699  std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
700  if (pStyle == nullptr)
701  {
702  mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
703  rUpdateBox,
704  mxCanvas->getDevice());
705  }
706  else
707  {
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);
718  }
719  maViewState.Clip = mxViewStateClip;
720 }
721 
722 namespace {
723 
724 //===== BorderSize ============================================================
725 
726 BorderSize::BorderSize()
727  : mnLeft(0),
728  mnTop(0),
729  mnRight(0),
730  mnBottom(0)
731 {
732 }
733 
734 //===== RendererPaneStyle ============================================================
735 
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(),
749  mpFont(),
750  mnFontXOffset(0),
751  mnFontYOffset(0),
756 {
757  if (rpTheme == nullptr)
758  return;
759 
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");
769 
770  // Get font description.
771  mpFont = rpTheme->GetFont(rsStyleName);
772 
773  OUString sAnchor ("Left");
774  if (mpFont)
775  {
776  sAnchor = mpFont->msAnchor;
777  mnFontXOffset = mpFont->mnXOffset;
778  mnFontYOffset = mpFont->mnYOffset;
779  }
780 
781  if ( sAnchor == "Left" )
782  meFontAnchor = Anchor::Left;
783  else if ( sAnchor == "Right" )
784  meFontAnchor = Anchor::Right;
785  else
786  meFontAnchor = Anchor::Center;
787 
788  // Get border sizes.
789  try
790  {
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];
797 
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];
804  }
805  catch(beans::UnknownPropertyException&)
806  {
807  OSL_ASSERT(false);
808  }
809 
810  UpdateBorderSizes();
811 }
812 
813 awt::Rectangle RendererPaneStyle::AddBorder (
814  const awt::Rectangle& rBox,
815  const drawing::framework::BorderType eBorderType) const
816 {
817  const BorderSize* pBorderSize = nullptr;
818  switch (eBorderType)
819  {
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;
831  }
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);
837 }
838 
839 awt::Rectangle RendererPaneStyle::RemoveBorder (
840  const awt::Rectangle& rBox,
841  const css::drawing::framework::BorderType eBorderType) const
842 {
843  const BorderSize* pBorderSize = nullptr;
844  switch (eBorderType)
845  {
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;
857  }
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);
863 }
864 
865 Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
866  const Reference<rendering::XCanvas>& rxCanvas) const
867 {
868  if (mpFont)
869  {
870  mpFont->PrepareFont(rxCanvas);
871  return mpFont->mxFont;
872  }
873  return Reference<rendering::XCanvasFont>();
874 }
875 
876 void RendererPaneStyle::UpdateBorderSizes()
877 {
878  maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
880  maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
881  maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
882 }
883 
884 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
885  const std::shared_ptr<PresenterTheme>& rpTheme,
886  const OUString& rsStyleName,
887  const OUString& rsBitmapName)
888 {
889  SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
890  if (pDescriptor)
891  return pDescriptor;
892  else
893  return mpEmpty;
894 }
895 
896 } // end of anonymous namespace
897 
898 } // end of namespace ::sd::presenter
899 
900 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::cppu::WeakComponentImplHelper< css::drawing::framework::XPaneBorderPainter > PresenterPaneBorderPainterInterfaceBase
Reference< rendering::XCanvas > mxCanvas
sal_Int32 mnRight
There is one bitmap for the normal state, one for a mouse over effect and one to show that a button h...
SharedBitmapDescriptor mpBottomRight
std::shared_ptr< FontDescriptor > SharedFontDescriptor
BorderSize maOuterBorderSize
sal_Int32 mnLeft
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
osl::Mutex m_aMutex
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
uno::Reference< uno::XComponentContext > mxContext
void SetCanvas(const Reference< rendering::XCanvas > &rxCanvas)
std::shared_ptr< T > make_shared(Args &&...args)
SharedBitmapDescriptor mpBottomLeft
std::shared_ptr< RendererPaneStyle > GetRendererPaneStyle(const OUString &rsResourceURL)
Center
exports com.sun.star. geometry
::std::map< OUString, std::shared_ptr< RendererPaneStyle > > RendererPaneStyleContainer
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
SharedBitmapDescriptor mpTopLeft
SharedBitmapDescriptor mpLeft
Reference< drawing::XPresenterHelper > mxPresenterHelper
Anchor meFontAnchor
SharedBitmapDescriptor mpTopRight
sal_Int32 mnBottom
virtual css::awt::Rectangle SAL_CALL removeBorder(const OUString &rsPaneBorderStyleName, const css::awt::Rectangle &rRectangle, css::drawing::framework::BorderType eBorderType) override
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...
Renderer(const Reference< XComponentContext > &rxContext, const std::shared_ptr< PresenterTheme > &rpTheme)
PresenterPaneBorderPainter(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
BorderSize maTotalBorderSize
SharedBitmapDescriptor mpEmpty
Right
sal_Int32 mnFontYOffset
virtual css::awt::Point SAL_CALL getCalloutOffset(const OUString &rsPaneBorderStyleName) override
sal_Int32 mnFontXOffset
void SetupClipping(const awt::Rectangle &rUpdateBox, const awt::Rectangle &rOuterBox, const OUString &rsPaneStyleName)
virtual css::awt::Rectangle SAL_CALL addBorder(const OUString &rsPaneBorderStyleName, const css::awt::Rectangle &rRectangle, css::drawing::framework::BorderType eBorderType) 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...
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
sal_Int32 mnTop
void PaintTitle(const OUString &rsTitle, const std::shared_ptr< RendererPaneStyle > &rpStyle, const awt::Rectangle &rUpdateBox, const awt::Rectangle &rOuterBox, const awt::Rectangle &rInnerBox)
static css::awt::Rectangle Intersection(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
PresenterTheme::SharedFontDescriptor mpFont
css::uno::Reference< css::uno::XComponentContext > mxContext
BorderSize maInnerBorderSize
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
void SetTheme(const std::shared_ptr< PresenterTheme > &rpTheme)
Reference< XSingleServiceFactory > xFactory
SharedBitmapDescriptor mpRight
if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
Left
SharedBitmapDescriptor mpBottomCallout
SharedBitmapDescriptor mpBottom
void PaintBorder(const OUString &rsTitle, const awt::Rectangle &rBBox, const awt::Rectangle &rUpdateBox, const OUString &rsPaneURL)
SharedBitmapDescriptor mpTop
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)