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 {
150 }
151 
153 {
154 }
155 
156 //----- XPaneBorderPainter ----------------------------------------------------
157 
158 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder (
159  const OUString& rsPaneBorderStyleName,
160  const css::awt::Rectangle& rRectangle,
161  drawing::framework::BorderType eBorderType)
162 {
163  ThrowIfDisposed();
164 
165  ProvideTheme();
166 
167  return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
168 }
169 
171  const OUString& rsPaneBorderStyleName,
172  const css::awt::Rectangle& rRectangle,
173  drawing::framework::BorderType eBorderType)
174 {
175  ThrowIfDisposed();
176 
177  ProvideTheme();
178 
179  return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
180 }
181 
183  const OUString& rsPaneBorderStyleName,
184  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
185  const css::awt::Rectangle& rOuterBorderRectangle,
186  const css::awt::Rectangle& rRepaintArea,
187  const OUString& rsTitle)
188 {
189  ThrowIfDisposed();
190 
191  // Early reject paints completely outside the repaint area.
192  if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
193  || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
194  || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
195  || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
196  {
197  return;
198  }
199  ProvideTheme(rxCanvas);
200 
201  if (mpRenderer == nullptr)
202  return;
203 
204  mpRenderer->SetCanvas(rxCanvas);
205  mpRenderer->SetupClipping(
206  rRepaintArea,
207  rOuterBorderRectangle,
208  rsPaneBorderStyleName);
209  mpRenderer->PaintBorder(
210  rsTitle,
211  rOuterBorderRectangle,
212  rRepaintArea,
213  rsPaneBorderStyleName);
214 }
215 
217  const OUString& rsPaneBorderStyleName,
218  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
219  const css::awt::Rectangle& rOuterBorderRectangle,
220  const css::awt::Rectangle& rRepaintArea,
221  const OUString& rsTitle,
222  const css::awt::Point& rCalloutAnchor)
223 {
224  ThrowIfDisposed();
225 
226  // Early reject paints completely outside the repaint area.
227  if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
228  || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
229  || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
230  || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
231  {
232  return;
233  }
234  ProvideTheme(rxCanvas);
235 
236  if (mpRenderer == nullptr)
237  return;
238 
239  mpRenderer->SetCanvas(rxCanvas);
240  mpRenderer->SetupClipping(
241  rRepaintArea,
242  rOuterBorderRectangle,
243  rsPaneBorderStyleName);
244  mpRenderer->SetCalloutAnchor(rCalloutAnchor);
245  mpRenderer->PaintBorder(
246  rsTitle,
247  rOuterBorderRectangle,
248  rRepaintArea,
249  rsPaneBorderStyleName);
250 }
251 
253  const OUString& rsPaneBorderStyleName)
254 {
255  ThrowIfDisposed();
256  ProvideTheme();
257  if (mpRenderer != nullptr)
258  {
259  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
260  mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
261  if (pRendererPaneStyle != nullptr && pRendererPaneStyle->mpBottomCallout)
262  {
263  return awt::Point (
264  0,
265  pRendererPaneStyle->mpBottomCallout->mnHeight
266  - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
267  }
268  }
269 
270  return awt::Point(0,0);
271 }
272 
273 
274 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
275 {
276  bool bModified (false);
277 
278  if ( ! mxContext.is())
279  return false;
280 
281  if (mpTheme != nullptr)
282  {
283  // Check if the theme already has a canvas.
284  if ( ! mpTheme->HasCanvas())
285  {
286  mpTheme->ProvideCanvas(rxCanvas);
287  bModified = true;
288  }
289  }
290  else
291  {
292  mpTheme = std::make_shared<PresenterTheme>(mxContext, rxCanvas);
293  bModified = true;
294  }
295 
296  if (bModified)
297  {
298  if (mpRenderer == nullptr)
299  mpRenderer.reset(new Renderer(mxContext, mpTheme));
300  else
301  mpRenderer->SetCanvas(rxCanvas);
302  }
303 
304  return bModified;
305 }
306 
308 {
309  if (mpTheme == nullptr)
310  {
311  // Create a theme without bitmaps (no canvas => no bitmaps).
312  ProvideTheme(nullptr);
313  }
314  // When there already is a theme then without a canvas we can not
315  // add anything new.
316 }
317 
318 void PresenterPaneBorderPainter::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
319 {
320  mpTheme = rpTheme;
321  if (mpRenderer == nullptr)
322  mpRenderer.reset(new Renderer(mxContext, mpTheme));
323 }
324 
326  const OUString& rsPaneURL,
327  const awt::Rectangle& rInnerBox,
328  const css::drawing::framework::BorderType eBorderType) const
329 {
330  if (mpRenderer != nullptr)
331  {
332  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
333  if (pRendererPaneStyle != nullptr)
334  return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
335  }
336  return rInnerBox;
337 }
338 
340  const OUString& rsPaneURL,
341  const css::awt::Rectangle& rOuterBox,
342  const css::drawing::framework::BorderType eBorderType) const
343 {
344  if (mpRenderer != nullptr)
345  {
346  const std::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
347  if (pRendererPaneStyle != nullptr)
348  return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
349  }
350  return rOuterBox;
351 }
352 
354 {
355  if (rBHelper.bDisposed || rBHelper.bInDispose)
356  {
357  throw lang::DisposedException (
358  "PresenterPaneBorderPainter object has already been disposed",
359  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
360  }
361 }
362 
363 //===== PresenterPaneBorderPainter::Renderer =====================================
364 
366  const Reference<XComponentContext>& rxContext,
367  const std::shared_ptr<PresenterTheme>& rpTheme)
368  : mpTheme(rpTheme),
369  maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
370  mbHasCallout(false)
371 {
372  Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
373  if (xFactory.is())
374  {
375  mxPresenterHelper.set(
376  xFactory->createInstanceWithContext(
377  "com.sun.star.comp.Draw.PresenterHelper",
378  rxContext),
379  UNO_QUERY_THROW);
380  }
381 }
382 
383 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
384 {
385  if (mxCanvas != rxCanvas)
386  {
387  mxCanvas = rxCanvas;
388  }
389 }
390 
392  const OUString& rsTitle,
393  const awt::Rectangle& rBBox,
394  const awt::Rectangle& rUpdateBox,
395  const OUString& rsPaneURL)
396 {
397  if ( ! mxCanvas.is())
398  return;
399 
400  // Create the outer and inner border of the, ahm, border.
401  std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
402  if (pStyle == nullptr)
403  return;
404 
405  awt::Rectangle aOuterBox (rBBox);
406  awt::Rectangle aCenterBox (
407  pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
408  awt::Rectangle aInnerBox (
409  pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
410 
411  // Prepare references for all used bitmaps.
412  SharedBitmapDescriptor pTop (pStyle->mpTop);
413  SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
414  SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
415  SharedBitmapDescriptor pLeft (pStyle->mpLeft);
416  SharedBitmapDescriptor pRight (pStyle->mpRight);
417  SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
418  SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
419  SharedBitmapDescriptor pBottom (pStyle->mpBottom);
420 
421  // Paint the sides.
422  PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
423  pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop);
424  PaintBitmap(aCenterBox, rUpdateBox, -1,0,
425  pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft);
426  PaintBitmap(aCenterBox, rUpdateBox, +1,0,
427  pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight);
428  if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
429  {
430  const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
431  sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
432  - (aCenterBox.X - aOuterBox.X));
433  if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
434  nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
435  if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
436  nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
437  // Paint bottom callout.
438  PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout);
439  // Paint regular bottom bitmap left and right.
440  PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
441  pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom);
442  PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
443  nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom);
444  }
445  else
446  {
447  // Stretch the bottom bitmap over the full width.
448  PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
449  pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom);
450  }
451 
452  // Paint the corners.
453  PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft);
454  PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight);
455  PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft);
456  PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight);
457 
458  // Paint the title.
459  PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox);
460 
461  // In a double buffering environment request to make the changes visible.
462  Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
463  if (xSpriteCanvas.is())
464  xSpriteCanvas->updateScreen(false);
465 }
466 
468  const OUString& rsTitle,
469  const std::shared_ptr<RendererPaneStyle>& rpStyle,
470  const awt::Rectangle& rUpdateBox,
471  const awt::Rectangle& rOuterBox,
472  const awt::Rectangle& rInnerBox)
473 {
474  if ( ! mxCanvas.is())
475  return;
476 
477  if (rsTitle.isEmpty())
478  return;
479 
480  Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
481  if ( ! xFont.is())
482  return;
483 
484  rendering::StringContext aContext (
485  rsTitle,
486  0,
487  rsTitle.getLength());
488  Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
489  aContext,
490  rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
491  0));
492  if ( ! xLayout.is())
493  return;
494 
496  geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
497  const double nTextHeight = aBox.Y2 - aBox.Y1;
498  const double nTextWidth = aBox.X1 + aBox.X2;
499  const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
500  double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
501  if (nY >= rInnerBox.Y)
502  nY = rInnerBox.Y - 1;
503  double nX;
504  switch (rpStyle->meFontAnchor)
505  {
506  case RendererPaneStyle::Anchor::Left:
507  nX = rInnerBox.X;
508  break;
509  case RendererPaneStyle::Anchor::Right:
510  nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
511  break;
512  default: // RendererPaneStyle::Anchor::Center
513  nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
514  break;
515  }
516  nX += rpStyle->mnFontXOffset;
517  nY += rpStyle->mnFontYOffset;
518 
519  if (rUpdateBox.X >= nX+nTextWidth
520  || rUpdateBox.Y >= nY+nTextHeight
521  || rUpdateBox.X+rUpdateBox.Width <= nX
522  || rUpdateBox.Y+rUpdateBox.Height <= nY)
523  {
524  return;
525  }
526 
527  rendering::RenderState aRenderState(
528  geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
529  nullptr,
530  Sequence<double>(4),
531  rendering::CompositeOperation::SOURCE);
532 
534  aRenderState,
535  rpStyle->mpFont->mnColor);
536 
537  mxCanvas->drawTextLayout (
538  xLayout,
539  maViewState,
540  aRenderState);
541 }
542 
543 std::shared_ptr<RendererPaneStyle>
545 {
546  OSL_ASSERT(mpTheme != nullptr);
547 
548  RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
549  if (iStyle == maRendererPaneStyles.end())
550  {
551  OUString sPaneStyleName ("DefaultRendererPaneStyle");
552 
553  // Get pane layout name for resource URL.
554  const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
555  if (!sStyleName.isEmpty())
556  sPaneStyleName = sStyleName;
557 
558  // Create a new pane style object and initialize it with bitmaps.
559  auto pStyle = std::make_shared<RendererPaneStyle>(mpTheme,sPaneStyleName);
560  iStyle = maRendererPaneStyles.emplace(rsResourceURL, pStyle).first;
561  }
562  if (iStyle != maRendererPaneStyles.end())
563  return iStyle->second;
564  else
565  return std::shared_ptr<RendererPaneStyle>();
566 }
567 
569  const awt::Point& rCalloutAnchor)
570 {
571  mbHasCallout = true;
572  maCalloutAnchor = rCalloutAnchor;
573 }
574 
576  const awt::Rectangle& rBox,
577  const awt::Rectangle& rUpdateBox,
578  const sal_Int32 nXPosition,
579  const sal_Int32 nYPosition,
580  const sal_Int32 nStartOffset,
581  const sal_Int32 nEndOffset,
582  const bool bExpand,
583  const SharedBitmapDescriptor& rpBitmap)
584 {
585  bool bUseCanvas (mxCanvas.is());
586  if ( ! bUseCanvas)
587  return;
588 
589  if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
590  return;
591 
592  Reference<rendering::XBitmap> xBitmap = rpBitmap->GetNormalBitmap();
593  if ( ! xBitmap.is())
594  return;
595 
596  // Calculate position, and for side bitmaps, the size.
597  sal_Int32 nX = 0;
598  sal_Int32 nY = 0;
599  sal_Int32 nW = rpBitmap->mnWidth;
600  sal_Int32 nH = rpBitmap->mnHeight;
601  if (nXPosition < 0)
602  {
603  nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
604  }
605  else if (nXPosition > 0)
606  {
607  nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
608  }
609  else
610  {
611  nX = rBox.X + nStartOffset;
612  if (bExpand)
613  nW = rBox.Width - nStartOffset + nEndOffset;
614  }
615 
616  if (nYPosition < 0)
617  {
618  nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
619  }
620  else if (nYPosition > 0)
621  {
622  nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
623  }
624  else
625  {
626  nY = rBox.Y + nStartOffset;
627  if (bExpand)
628  nH = rBox.Height - nStartOffset + nEndOffset;
629  }
630 
631  // Do not paint when bitmap area does not intersect with update box.
632  if (nX >= rUpdateBox.X + rUpdateBox.Width
633  || nX+nW <= rUpdateBox.X
634  || nY >= rUpdateBox.Y + rUpdateBox.Height
635  || nY+nH <= rUpdateBox.Y)
636  {
637  return;
638  }
639 
640  /*
641  Reference<rendering::XBitmap> xMaskedBitmap (
642  PresenterBitmapHelper::FillMaskedWithColor (
643  mxCanvas,
644  Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
645  rBitmap.mxMaskBitmap,
646  0x00ff0000,
647  rBackgroundBitmap.maReplacementColor));
648  if (xMaskedBitmap.is())
649  xBitmap = xMaskedBitmap;
650  else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
651  {
652  const static sal_Int32 nOutsideMaskColor (0x00ff0000);
653  Reference<rendering::XIntegerBitmap> xMask (
654  mxPresenterHelper->createMask(
655  mxCanvas,
656  rBitmap.mxMaskBitmap,
657  nOutsideMaskColor,
658  false));
659  xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
660  mxCanvas,
661  Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
662  xMask,
663  rBackgroundBitmap.maReplacementColor);
664  }
665  */
666  rendering::RenderState aRenderState (
667  geometry::AffineMatrix2D(
668  double(nW)/rpBitmap->mnWidth, 0, nX,
669  0, double(nH)/rpBitmap->mnHeight, nY),
670  nullptr,
671  Sequence<double>(4),
672  rendering::CompositeOperation::OVER);
673 
674  if (xBitmap.is())
675  mxCanvas->drawBitmap(
676  xBitmap,
677  maViewState,
678  aRenderState);
679 }
680 
682  const awt::Rectangle& rUpdateBox,
683  const awt::Rectangle& rOuterBox,
684  const OUString& rsPaneStyleName)
685 {
686  mxViewStateClip = nullptr;
687  maViewState.Clip = nullptr;
688 
689  if ( ! mxCanvas.is())
690  return;
691 
692  std::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
693  if (pStyle == nullptr)
694  {
695  mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
696  rUpdateBox,
697  mxCanvas->getDevice());
698  }
699  else
700  {
701  awt::Rectangle aInnerBox (
702  pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
703  ::std::vector<awt::Rectangle> aRectangles;
704  aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox));
705  aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox));
706  mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
707  aRectangles,
708  mxCanvas->getDevice());
709  if (mxViewStateClip.is())
710  mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
711  }
712  maViewState.Clip = mxViewStateClip;
713 }
714 
715 namespace {
716 
717 //===== BorderSize ============================================================
718 
719 BorderSize::BorderSize()
720  : mnLeft(0),
721  mnTop(0),
722  mnRight(0),
723  mnBottom(0)
724 {
725 }
726 
727 //===== RendererPaneStyle ============================================================
728 
729 RendererPaneStyle::RendererPaneStyle (
730  const std::shared_ptr<PresenterTheme>& rpTheme,
731  const OUString& rsStyleName)
733  mnFontXOffset(0),
734  mnFontYOffset(0),
736 {
737  if (rpTheme == nullptr)
738  return;
739 
740  mpTopLeft = GetBitmap(rpTheme, rsStyleName, "TopLeft");
741  mpTop = GetBitmap(rpTheme, rsStyleName, "Top");
742  mpTopRight = GetBitmap(rpTheme, rsStyleName, "TopRight");
743  mpLeft = GetBitmap(rpTheme, rsStyleName,"Left");
744  mpRight = GetBitmap(rpTheme, rsStyleName, "Right");
745  mpBottomLeft = GetBitmap(rpTheme, rsStyleName, "BottomLeft");
746  mpBottom = GetBitmap(rpTheme, rsStyleName, "Bottom");
747  mpBottomRight = GetBitmap(rpTheme, rsStyleName, "BottomRight");
748  mpBottomCallout = GetBitmap(rpTheme, rsStyleName, "BottomCallout");
749 
750  // Get font description.
751  mpFont = rpTheme->GetFont(rsStyleName);
752 
753  OUString sAnchor ("Left");
754  if (mpFont)
755  {
756  sAnchor = mpFont->msAnchor;
757  mnFontXOffset = mpFont->mnXOffset;
758  mnFontYOffset = mpFont->mnYOffset;
759  }
760 
761  if ( sAnchor == "Left" )
762  meFontAnchor = Anchor::Left;
763  else if ( sAnchor == "Right" )
764  meFontAnchor = Anchor::Right;
765  else
766  meFontAnchor = Anchor::Center;
767 
768  // Get border sizes.
769  try
770  {
771  ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
772  OSL_ASSERT(aInnerBorder.size()==4);
773  maInnerBorderSize.mnLeft = aInnerBorder[0];
774  maInnerBorderSize.mnTop = aInnerBorder[1];
775  maInnerBorderSize.mnRight = aInnerBorder[2];
776  maInnerBorderSize.mnBottom = aInnerBorder[3];
777 
778  ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
779  OSL_ASSERT(aOuterBorder.size()==4);
780  maOuterBorderSize.mnLeft = aOuterBorder[0];
781  maOuterBorderSize.mnTop = aOuterBorder[1];
782  maOuterBorderSize.mnRight = aOuterBorder[2];
783  maOuterBorderSize.mnBottom = aOuterBorder[3];
784  }
785  catch(beans::UnknownPropertyException&)
786  {
787  OSL_ASSERT(false);
788  }
789 
790  UpdateBorderSizes();
791 }
792 
793 awt::Rectangle RendererPaneStyle::AddBorder (
794  const awt::Rectangle& rBox,
795  const drawing::framework::BorderType eBorderType) const
796 {
797  const BorderSize* pBorderSize = nullptr;
798  switch (eBorderType)
799  {
800  case drawing::framework::BorderType_INNER_BORDER:
801  pBorderSize = &maInnerBorderSize;
802  break;
803  case drawing::framework::BorderType_OUTER_BORDER:
804  pBorderSize = &maOuterBorderSize;
805  break;
806  case drawing::framework::BorderType_TOTAL_BORDER:
807  pBorderSize = &maTotalBorderSize;
808  break;
809  default:
810  return rBox;
811  }
812  return awt::Rectangle (
813  rBox.X - pBorderSize->mnLeft,
814  rBox.Y - pBorderSize->mnTop,
815  rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
816  rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
817 }
818 
819 awt::Rectangle RendererPaneStyle::RemoveBorder (
820  const awt::Rectangle& rBox,
821  const css::drawing::framework::BorderType eBorderType) const
822 {
823  const BorderSize* pBorderSize = nullptr;
824  switch (eBorderType)
825  {
826  case drawing::framework::BorderType_INNER_BORDER:
827  pBorderSize = &maInnerBorderSize;
828  break;
829  case drawing::framework::BorderType_OUTER_BORDER:
830  pBorderSize = &maOuterBorderSize;
831  break;
832  case drawing::framework::BorderType_TOTAL_BORDER:
833  pBorderSize = &maTotalBorderSize;
834  break;
835  default:
836  return rBox;
837  }
838  return awt::Rectangle (
839  rBox.X + pBorderSize->mnLeft,
840  rBox.Y + pBorderSize->mnTop,
841  rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
842  rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
843 }
844 
845 Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
846  const Reference<rendering::XCanvas>& rxCanvas) const
847 {
848  if (mpFont)
849  {
850  mpFont->PrepareFont(rxCanvas);
851  return mpFont->mxFont;
852  }
853  return Reference<rendering::XCanvasFont>();
854 }
855 
856 void RendererPaneStyle::UpdateBorderSizes()
857 {
858  maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
860  maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
861  maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
862 }
863 
864 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
865  const std::shared_ptr<PresenterTheme>& rpTheme,
866  const OUString& rsStyleName,
867  const OUString& rsBitmapName)
868 {
869  SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
870  if (pDescriptor)
871  return pDescriptor;
872  else
873  return mpEmpty;
874 }
875 
876 } // end of anonymous namespace
877 
878 } // end of namespace ::sd::presenter
879 
880 /* 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
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
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
std::mutex m_aMutex
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
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
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)
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
void SetTheme(const std::shared_ptr< PresenterTheme > &rpTheme)
Reference< XSingleServiceFactory > xFactory
SharedBitmapDescriptor mpRight
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)