1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26
27 #include "PresenterPaneBorderPainter.hxx"
28 #include "PresenterCanvasHelper.hxx"
29 #include "PresenterConfigurationAccess.hxx"
30 #include "PresenterGeometryHelper.hxx"
31 #include "PresenterTheme.hxx"
32 #include <com/sun/star/awt/FontDescriptor.hpp>
33 #include <com/sun/star/awt/Point.hpp>
34 #include <com/sun/star/awt/Rectangle.hpp>
35 #include <com/sun/star/awt/SimpleFontMetric.hpp>
36 #include <com/sun/star/awt/XFont.hpp>
37 #include <com/sun/star/drawing/XPresenterHelper.hpp>
38 #include <com/sun/star/graphic/XGraphic.hpp>
39 #include <com/sun/star/graphic/XGraphicRenderer.hpp>
40 #include <com/sun/star/rendering/CompositeOperation.hpp>
41 #include <com/sun/star/rendering/FillRule.hpp>
42 #include <com/sun/star/rendering/TextDirection.hpp>
43 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
44 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
45 #include <map>
46 #include <vector>
47 #include <boost/shared_ptr.hpp>
48
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using ::rtl::OUString;
52
53 #define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)))
54
55 namespace sdext { namespace presenter {
56
57 namespace {
58 class BorderSize
59 {
60 public:
61 BorderSize (void);
62 BorderSize (const BorderSize& rBorderSize);
63 BorderSize& operator= (const BorderSize& rBoderSize);
64 sal_Int32 mnLeft;
65 sal_Int32 mnTop;
66 sal_Int32 mnRight;
67 sal_Int32 mnBottom;
68 };
69
70 class RendererPaneStyle
71 {
72 public:
73 RendererPaneStyle (
74 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
75 const OUString& rsStyleName);
76
77 awt::Rectangle AddBorder (
78 const awt::Rectangle& rBox,
79 drawing::framework::BorderType eBorderType) const;
80 awt::Rectangle RemoveBorder (
81 const awt::Rectangle& rBox,
82 drawing::framework::BorderType eBorderType) const;
83 const Reference<rendering::XCanvasFont> GetFont (
84 const Reference<rendering::XCanvas>& rxCanvas) const;
85
86 SharedBitmapDescriptor mpTopLeft;
87 SharedBitmapDescriptor mpTop;
88 SharedBitmapDescriptor mpTopRight;
89 SharedBitmapDescriptor mpLeft;
90 SharedBitmapDescriptor mpRight;
91 SharedBitmapDescriptor mpBottomLeft;
92 SharedBitmapDescriptor mpBottom;
93 SharedBitmapDescriptor mpBottomRight;
94 SharedBitmapDescriptor mpBottomCallout;
95 SharedBitmapDescriptor mpBackground;
96 SharedBitmapDescriptor mpEmpty;
97 PresenterTheme::SharedFontDescriptor mpFont;
98 sal_Int32 mnFontXOffset;
99 sal_Int32 mnFontYOffset;
100 enum Anchor { AnchorLeft, AnchorRight, AnchorCenter } meFontAnchor;
101 BorderSize maInnerBorderSize;
102 BorderSize maOuterBorderSize;
103 BorderSize maTotalBorderSize;
104 enum Side { Left, Top, Right, Bottom };
105 private:
106 void UpdateBorderSizes (void);
107 SharedBitmapDescriptor GetBitmap(
108 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
109 const OUString& rsStyleName,
110 const OUString& rsBitmapName);
111 };
112 }
113
114
115
116 class PresenterPaneBorderPainter::Renderer
117 {
118 public:
119 Renderer (
120 const Reference<XComponentContext>& rxContext,
121 const ::boost::shared_ptr<PresenterTheme>& rpTheme);
122 ~Renderer (void);
123
124 void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas);
125 void PaintBorder (
126 const OUString& rsTitle,
127 const awt::Rectangle& rBBox,
128 const awt::Rectangle& rUpdateBox,
129 const OUString& rsPaneURL);
130 void PaintTitle (
131 const OUString& rsTitle,
132 const ::boost::shared_ptr<RendererPaneStyle>& rpStyle,
133 const awt::Rectangle& rUpdateBox,
134 const awt::Rectangle& rOuterBox,
135 const awt::Rectangle& rInnerBox,
136 const bool bPaintBackground);
137 void SetupClipping (
138 const awt::Rectangle& rUpdateBox,
139 const awt::Rectangle& rOuterBox,
140 const OUString& rsPaneStyleName);
141 ::boost::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL);
142 void SetCalloutAnchor (
143 const awt::Point& rCalloutAnchor);
144
145 private:
146 ::boost::shared_ptr<PresenterTheme> mpTheme;
147 typedef ::std::map<OUString, ::boost::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer;
148 RendererPaneStyleContainer maRendererPaneStyles;
149 Reference<rendering::XCanvas> mxCanvas;
150 Reference<drawing::XPresenterHelper> mxPresenterHelper;
151 css::rendering::ViewState maViewState;
152 Reference<rendering::XPolyPolygon2D> mxViewStateClip;
153 bool mbHasCallout;
154 awt::Point maCalloutAnchor;
155
156 void PaintBitmap(
157 const awt::Rectangle& rBox,
158 const awt::Rectangle& rUpdateBox,
159 const sal_Int32 nXPosition,
160 const sal_Int32 nYPosition,
161 const sal_Int32 nStartOffset,
162 const sal_Int32 nEndOffset,
163 const bool bExpand,
164 const SharedBitmapDescriptor& rpBitmap,
165 const SharedBitmapDescriptor& rpBackgroundBitmap);
166 };
167
168
169
170
171 // ===== PresenterPaneBorderPainter ===========================================
172
PresenterPaneBorderPainter(const Reference<XComponentContext> & rxContext)173 PresenterPaneBorderPainter::PresenterPaneBorderPainter (
174 const Reference<XComponentContext>& rxContext)
175 : PresenterPaneBorderPainterInterfaceBase(m_aMutex),
176 mxContext(rxContext),
177 mpTheme(),
178 mpRenderer()
179 {
180 }
181
182
183
184
~PresenterPaneBorderPainter(void)185 PresenterPaneBorderPainter::~PresenterPaneBorderPainter (void)
186 {
187 }
188
189
190
191
192 //----- XPaneBorderPainter ----------------------------------------------------
193
addBorder(const rtl::OUString & rsPaneBorderStyleName,const css::awt::Rectangle & rRectangle,drawing::framework::BorderType eBorderType)194 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder (
195 const rtl::OUString& rsPaneBorderStyleName,
196 const css::awt::Rectangle& rRectangle,
197 drawing::framework::BorderType eBorderType)
198 {
199 ThrowIfDisposed();
200
201 ProvideTheme();
202
203 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
204 }
205
206
207
208
removeBorder(const rtl::OUString & rsPaneBorderStyleName,const css::awt::Rectangle & rRectangle,drawing::framework::BorderType eBorderType)209 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder (
210 const rtl::OUString& rsPaneBorderStyleName,
211 const css::awt::Rectangle& rRectangle,
212 drawing::framework::BorderType eBorderType)
213 {
214 ThrowIfDisposed();
215
216 ProvideTheme();
217
218 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
219 }
220
221
222
223
paintBorder(const rtl::OUString & rsPaneBorderStyleName,const css::uno::Reference<css::rendering::XCanvas> & rxCanvas,const css::awt::Rectangle & rOuterBorderRectangle,const css::awt::Rectangle & rRepaintArea,const rtl::OUString & rsTitle)224 void SAL_CALL PresenterPaneBorderPainter::paintBorder (
225 const rtl::OUString& rsPaneBorderStyleName,
226 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
227 const css::awt::Rectangle& rOuterBorderRectangle,
228 const css::awt::Rectangle& rRepaintArea,
229 const rtl::OUString& rsTitle)
230 {
231 ThrowIfDisposed();
232
233 // Early reject paints completely outside the repaint area.
234 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
235 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
236 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
237 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
238 {
239 return;
240 }
241 ProvideTheme(rxCanvas);
242
243 if (mpRenderer.get() != NULL)
244 {
245 mpRenderer->SetCanvas(rxCanvas);
246 mpRenderer->SetupClipping(
247 rRepaintArea,
248 rOuterBorderRectangle,
249 rsPaneBorderStyleName);
250 mpRenderer->PaintBorder(
251 rsTitle,
252 rOuterBorderRectangle,
253 rRepaintArea,
254 rsPaneBorderStyleName);
255 }
256 }
257
258
259
260
paintBorderWithCallout(const rtl::OUString & rsPaneBorderStyleName,const css::uno::Reference<css::rendering::XCanvas> & rxCanvas,const css::awt::Rectangle & rOuterBorderRectangle,const css::awt::Rectangle & rRepaintArea,const rtl::OUString & rsTitle,const css::awt::Point & rCalloutAnchor)261 void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout (
262 const rtl::OUString& rsPaneBorderStyleName,
263 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
264 const css::awt::Rectangle& rOuterBorderRectangle,
265 const css::awt::Rectangle& rRepaintArea,
266 const rtl::OUString& rsTitle,
267 const css::awt::Point& rCalloutAnchor)
268 {
269 ThrowIfDisposed();
270
271 // Early reject paints completely outside the repaint area.
272 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
273 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
274 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
275 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
276 {
277 return;
278 }
279 ProvideTheme(rxCanvas);
280
281 if (mpRenderer.get() != NULL)
282 {
283 mpRenderer->SetCanvas(rxCanvas);
284 mpRenderer->SetupClipping(
285 rRepaintArea,
286 rOuterBorderRectangle,
287 rsPaneBorderStyleName);
288 mpRenderer->SetCalloutAnchor(rCalloutAnchor);
289 mpRenderer->PaintBorder(
290 rsTitle,
291 rOuterBorderRectangle,
292 rRepaintArea,
293 rsPaneBorderStyleName);
294 }
295 }
296
297
298
299
getCalloutOffset(const rtl::OUString & rsPaneBorderStyleName)300 awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset (
301 const rtl::OUString& rsPaneBorderStyleName)
302 {
303 ThrowIfDisposed();
304 ProvideTheme();
305 if (mpRenderer.get() != NULL)
306 {
307 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
308 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
309 if (pRendererPaneStyle.get() != NULL
310 && pRendererPaneStyle->mpBottomCallout.get() != NULL)
311 {
312 return awt::Point (
313 0,
314 pRendererPaneStyle->mpBottomCallout->mnHeight
315 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
316 }
317 }
318
319 return awt::Point(0,0);
320 }
321
322
323
324
325 //-----------------------------------------------------------------------------
326
ProvideTheme(const Reference<rendering::XCanvas> & rxCanvas)327 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
328 {
329 bool bModified (false);
330
331 if ( ! mxContext.is())
332 return false;
333
334 if (mpTheme.get() != NULL)
335 {
336 // Check if the theme already has a canvas.
337 if ( ! mpTheme->HasCanvas())
338 {
339 mpTheme->ProvideCanvas(rxCanvas);
340 bModified = true;
341 }
342 }
343 else
344 {
345 mpTheme.reset(new PresenterTheme(mxContext, OUString(), rxCanvas));
346 bModified = true;
347 }
348
349 if (mpTheme.get() != NULL && bModified)
350 {
351 if (mpRenderer.get() == NULL)
352 mpRenderer.reset(new Renderer(mxContext, mpTheme));
353 else
354 mpRenderer->SetCanvas(rxCanvas);
355 }
356
357 return bModified;
358 }
359
360
361
362
ProvideTheme(void)363 bool PresenterPaneBorderPainter::ProvideTheme (void)
364 {
365 if (mpTheme.get() == NULL)
366 {
367 // Create a theme without bitmaps (no canvas => no bitmaps).
368 return ProvideTheme(NULL);
369 }
370 else
371 {
372 // When there already is a theme then without a canvas we can not
373 // add anything new.
374 return false;
375 }
376 }
377
378
379
380
HasTheme(void) const381 bool PresenterPaneBorderPainter::HasTheme (void) const
382 {
383 return mpTheme.get()!=NULL && mpRenderer.get()!=NULL;
384 }
385
386
387
388
SetTheme(const::boost::shared_ptr<PresenterTheme> & rpTheme)389 void PresenterPaneBorderPainter::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme)
390 {
391 mpTheme = rpTheme;
392 if (mpRenderer.get() == NULL)
393 mpRenderer.reset(new Renderer(mxContext, mpTheme));
394 }
395
396
397
398
AddBorder(const::rtl::OUString & rsPaneURL,const awt::Rectangle & rInnerBox,const css::drawing::framework::BorderType eBorderType) const399 awt::Rectangle PresenterPaneBorderPainter::AddBorder (
400 const ::rtl::OUString& rsPaneURL,
401 const awt::Rectangle& rInnerBox,
402 const css::drawing::framework::BorderType eBorderType) const
403 {
404 if (mpRenderer.get() != NULL)
405 {
406 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
407 if (pRendererPaneStyle.get() != NULL)
408 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
409 }
410 return rInnerBox;
411 }
412
413
414
415
RemoveBorder(const::rtl::OUString & rsPaneURL,const css::awt::Rectangle & rOuterBox,const css::drawing::framework::BorderType eBorderType) const416 awt::Rectangle PresenterPaneBorderPainter::RemoveBorder (
417 const ::rtl::OUString& rsPaneURL,
418 const css::awt::Rectangle& rOuterBox,
419 const css::drawing::framework::BorderType eBorderType) const
420 {
421 if (mpRenderer.get() != NULL)
422 {
423 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
424 if (pRendererPaneStyle.get() != NULL)
425 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
426 }
427 return rOuterBox;
428 }
429
430
431
432
ThrowIfDisposed(void) const433 void PresenterPaneBorderPainter::ThrowIfDisposed (void) const
434 {
435 if (rBHelper.bDisposed || rBHelper.bInDispose)
436 {
437 throw lang::DisposedException (
438 OUString(RTL_CONSTASCII_USTRINGPARAM(
439 "PresenterPaneBorderPainter object has already been disposed")),
440 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
441 }
442 }
443
444
445
446
447 //===== PresenterPaneBorderPainter::Renderer =====================================
448
449
Renderer(const Reference<XComponentContext> & rxContext,const::boost::shared_ptr<PresenterTheme> & rpTheme)450 PresenterPaneBorderPainter::Renderer::Renderer (
451 const Reference<XComponentContext>& rxContext,
452 const ::boost::shared_ptr<PresenterTheme>& rpTheme)
453 : mpTheme(rpTheme),
454 maRendererPaneStyles(),
455 mxCanvas(),
456 mxPresenterHelper(),
457 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
458 mxViewStateClip(),
459 mbHasCallout(false),
460 maCalloutAnchor()
461 {
462 (void)rxContext;
463
464 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
465 if (xFactory.is())
466 {
467 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
468 xFactory->createInstanceWithContext(
469 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
470 rxContext),
471 UNO_QUERY_THROW);
472 }
473 }
474
475
476
477
~Renderer(void)478 PresenterPaneBorderPainter::Renderer::~Renderer (void)
479 {
480 }
481
482
483
484
SetCanvas(const Reference<rendering::XCanvas> & rxCanvas)485 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
486 {
487 if (mxCanvas != rxCanvas)
488 {
489 mxCanvas = rxCanvas;
490 }
491 }
492
493
494
495
PaintBorder(const OUString & rsTitle,const awt::Rectangle & rBBox,const awt::Rectangle & rUpdateBox,const OUString & rsPaneURL)496 void PresenterPaneBorderPainter::Renderer::PaintBorder (
497 const OUString& rsTitle,
498 const awt::Rectangle& rBBox,
499 const awt::Rectangle& rUpdateBox,
500 const OUString& rsPaneURL)
501 {
502 if ( ! mxCanvas.is())
503 return;
504
505 // Create the outer and inner border of the, ahm, border.
506 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
507 if (pStyle.get() == NULL)
508 return;
509
510 awt::Rectangle aOuterBox (rBBox);
511 awt::Rectangle aCenterBox (
512 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
513 awt::Rectangle aInnerBox (
514 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
515
516 // Prepare references for all used bitmaps.
517 SharedBitmapDescriptor pTop (pStyle->mpTop);
518 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
519 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
520 SharedBitmapDescriptor pLeft (pStyle->mpLeft);
521 SharedBitmapDescriptor pRight (pStyle->mpRight);
522 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
523 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
524 SharedBitmapDescriptor pBottom (pStyle->mpBottom);
525 SharedBitmapDescriptor pBackground (pStyle->mpBackground);
526
527 // Paint the sides.
528 PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
529 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop, pBackground);
530 PaintBitmap(aCenterBox, rUpdateBox, -1,0,
531 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft, pBackground);
532 PaintBitmap(aCenterBox, rUpdateBox, +1,0,
533 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight, pBackground);
534 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
535 {
536 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
537 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
538 - (aCenterBox.X - aOuterBox.X));
539 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
540 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
541 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
542 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
543 // Paint bottom callout.
544 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout, pBackground);
545 // Paint regular bottom bitmap left and right.
546 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
547 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom, pBackground);
548 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
549 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom, pBackground);
550 }
551 else
552 {
553 // Stretch the bottom bitmap over the full width.
554 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
555 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom, pBackground);
556 }
557
558 // Paint the corners.
559 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft, pBackground);
560 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight, pBackground);
561 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft, pBackground);
562 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight, pBackground);
563
564 // Paint the title.
565 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox, false);
566
567 // In a double buffering environment request to make the changes visible.
568 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
569 if (xSpriteCanvas.is())
570 xSpriteCanvas->updateScreen(sal_False);
571 }
572
573
574
575
PaintTitle(const OUString & rsTitle,const::boost::shared_ptr<RendererPaneStyle> & rpStyle,const awt::Rectangle & rUpdateBox,const awt::Rectangle & rOuterBox,const awt::Rectangle & rInnerBox,bool bPaintBackground)576 void PresenterPaneBorderPainter::Renderer::PaintTitle (
577 const OUString& rsTitle,
578 const ::boost::shared_ptr<RendererPaneStyle>& rpStyle,
579 const awt::Rectangle& rUpdateBox,
580 const awt::Rectangle& rOuterBox,
581 const awt::Rectangle& rInnerBox,
582 bool bPaintBackground)
583 {
584 if ( ! mxCanvas.is())
585 return;
586
587 if (rsTitle.getLength() == 0)
588 return;
589
590 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
591 if ( ! xFont.is())
592 return;
593
594 rendering::StringContext aContext (
595 rsTitle,
596 0,
597 rsTitle.getLength());
598 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
599 aContext,
600 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
601 0));
602 if ( ! xLayout.is())
603 return;
604
605 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
606 const double nTextHeight = aBox.Y2 - aBox.Y1;
607 const double nTextWidth = aBox.X2 - aBox.X1;
608 double nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
609 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
610 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
611 if (nY >= rInnerBox.Y)
612 nY = rInnerBox.Y - 1;
613 switch (rpStyle->meFontAnchor)
614 {
615 default:
616 case RendererPaneStyle::AnchorLeft:
617 nX = rInnerBox.X;
618 break;
619 case RendererPaneStyle::AnchorRight:
620 nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
621 break;
622 case RendererPaneStyle::AnchorCenter:
623 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
624 break;
625 }
626 nX += rpStyle->mnFontXOffset;
627 nY += rpStyle->mnFontYOffset;
628
629 if (rUpdateBox.X >= nX+nTextWidth
630 || rUpdateBox.Y >= nY+nTextHeight
631 || rUpdateBox.X+rUpdateBox.Width <= nX
632 || rUpdateBox.Y+rUpdateBox.Height <= nY)
633 {
634 return;
635 }
636
637 rendering::RenderState aRenderState(
638 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
639 NULL,
640 Sequence<double>(4),
641 rendering::CompositeOperation::SOURCE);
642
643 if (bPaintBackground)
644 {
645 PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff));
646 Sequence<Sequence<geometry::RealPoint2D> > aPolygons(1);
647 aPolygons[0] = Sequence<geometry::RealPoint2D>(4);
648 aPolygons[0][0] = geometry::RealPoint2D(0, -nTextHeight);
649 aPolygons[0][1] = geometry::RealPoint2D(0, 0);
650 aPolygons[0][2] = geometry::RealPoint2D(nTextWidth, 0);
651 aPolygons[0][3] = geometry::RealPoint2D(nTextWidth, -nTextHeight);
652 Reference<rendering::XPolyPolygon2D> xPolygon (
653 mxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPolygons), UNO_QUERY);
654 if (xPolygon.is())
655 xPolygon->setClosed(0, sal_True);
656 mxCanvas->fillPolyPolygon(
657 xPolygon,
658 maViewState,
659 aRenderState);
660 }
661 else
662 {
663 PresenterCanvasHelper::SetDeviceColor(
664 aRenderState,
665 rpStyle->mpFont->mnColor);
666
667 mxCanvas->drawText(
668 aContext,
669 xFont,
670 maViewState,
671 aRenderState,
672 rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
673 }
674 }
675
676
677
678 ::boost::shared_ptr<RendererPaneStyle>
GetRendererPaneStyle(const OUString & rsResourceURL)679 PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL)
680 {
681 OSL_ASSERT(mpTheme.get()!=NULL);
682
683 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
684 if (iStyle == maRendererPaneStyles.end())
685 {
686 OUString sPaneStyleName (OUString::createFromAscii("DefaultRendererPaneStyle"));
687
688 // Get pane layout name for resource URL.
689 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
690 if (sStyleName.getLength() > 0)
691 sPaneStyleName = sStyleName;
692
693 // Create a new pane style object and initialize it with bitmaps.
694 ::boost::shared_ptr<RendererPaneStyle> pStyle (
695 new RendererPaneStyle(mpTheme,sPaneStyleName));
696 iStyle = maRendererPaneStyles.insert(
697 RendererPaneStyleContainer::value_type(rsResourceURL, pStyle)).first;
698 }
699 if (iStyle != maRendererPaneStyles.end())
700 return iStyle->second;
701 else
702 return ::boost::shared_ptr<RendererPaneStyle>();
703 }
704
705
706
707
SetCalloutAnchor(const awt::Point & rCalloutAnchor)708 void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor (
709 const awt::Point& rCalloutAnchor)
710 {
711 mbHasCallout = true;
712 maCalloutAnchor = rCalloutAnchor;
713 }
714
715
716
717
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,const SharedBitmapDescriptor & rpBackgroundBitmap)718 void PresenterPaneBorderPainter::Renderer::PaintBitmap(
719 const awt::Rectangle& rBox,
720 const awt::Rectangle& rUpdateBox,
721 const sal_Int32 nXPosition,
722 const sal_Int32 nYPosition,
723 const sal_Int32 nStartOffset,
724 const sal_Int32 nEndOffset,
725 const bool bExpand,
726 const SharedBitmapDescriptor& rpBitmap,
727 const SharedBitmapDescriptor& rpBackgroundBitmap)
728 {
729 (void)rpBackgroundBitmap;
730
731 bool bUseCanvas (mxCanvas.is());
732 if ( ! bUseCanvas)
733 return;
734
735 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
736 return;
737
738 Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY);
739 if ( ! xBitmap.is())
740 return;
741
742 // Calculate position, and for side bitmaps, the size.
743 sal_Int32 nX = 0;
744 sal_Int32 nY = 0;
745 sal_Int32 nW = rpBitmap->mnWidth;
746 sal_Int32 nH = rpBitmap->mnHeight;
747 if (nXPosition < 0)
748 {
749 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
750 }
751 else if (nXPosition > 0)
752 {
753 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
754 }
755 else
756 {
757 nX = rBox.X + nStartOffset;
758 if (bExpand)
759 nW = rBox.Width - nStartOffset + nEndOffset;
760 }
761
762 if (nYPosition < 0)
763 {
764 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
765 }
766 else if (nYPosition > 0)
767 {
768 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
769 }
770 else
771 {
772 nY = rBox.Y + nStartOffset;
773 if (bExpand)
774 nH = rBox.Height - nStartOffset + nEndOffset;
775 }
776
777 // Do not paint when bitmap area does not intersect with update box.
778 if (nX >= rUpdateBox.X + rUpdateBox.Width
779 || nX+nW <= rUpdateBox.X
780 || nY >= rUpdateBox.Y + rUpdateBox.Height
781 || nY+nH <= rUpdateBox.Y)
782 {
783 return;
784 }
785
786 /*
787 Reference<rendering::XBitmap> xMaskedBitmap (
788 PresenterBitmapHelper::FillMaskedWithColor (
789 mxCanvas,
790 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
791 rBitmap.mxMaskBitmap,
792 0x00ff0000,
793 rBackgroundBitmap.maReplacementColor));
794 if (xMaskedBitmap.is())
795 xBitmap = xMaskedBitmap;
796 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
797 {
798 const static sal_Int32 nOutsideMaskColor (0x00ff0000);
799 Reference<rendering::XIntegerBitmap> xMask (
800 mxPresenterHelper->createMask(
801 mxCanvas,
802 rBitmap.mxMaskBitmap,
803 nOutsideMaskColor,
804 false));
805 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
806 mxCanvas,
807 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
808 xMask,
809 rBackgroundBitmap.maReplacementColor);
810 }
811 */
812 rendering::RenderState aRenderState (
813 geometry::AffineMatrix2D(
814 double(nW)/rpBitmap->mnWidth, 0, nX,
815 0, double(nH)/rpBitmap->mnHeight, nY),
816 NULL,
817 Sequence<double>(4),
818 rendering::CompositeOperation::OVER);
819
820 if (xBitmap.is())
821 mxCanvas->drawBitmap(
822 xBitmap,
823 maViewState,
824 aRenderState);
825 }
826
827
828
829
SetupClipping(const awt::Rectangle & rUpdateBox,const awt::Rectangle & rOuterBox,const OUString & rsPaneStyleName)830 void PresenterPaneBorderPainter::Renderer::SetupClipping (
831 const awt::Rectangle& rUpdateBox,
832 const awt::Rectangle& rOuterBox,
833 const OUString& rsPaneStyleName)
834 {
835 mxViewStateClip = NULL;
836 maViewState.Clip = NULL;
837
838 if ( ! mxCanvas.is())
839 return;
840
841 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
842 if (pStyle.get() == NULL)
843 {
844 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
845 rUpdateBox,
846 mxCanvas->getDevice());
847 }
848 else
849 {
850 awt::Rectangle aInnerBox (
851 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
852 ::std::vector<awt::Rectangle> aRectangles;
853 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox));
854 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox));
855 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
856 aRectangles,
857 mxCanvas->getDevice());
858 if (mxViewStateClip.is())
859 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
860 }
861 maViewState.Clip = mxViewStateClip;
862 }
863
864
865
866 namespace {
867
868 //===== BorderSize ============================================================
869
BorderSize(void)870 BorderSize::BorderSize (void)
871 : mnLeft(0),
872 mnTop(0),
873 mnRight(0),
874 mnBottom(0)
875 {
876 }
877
878
879
880
BorderSize(const BorderSize & rBorderSize)881 BorderSize::BorderSize (const BorderSize& rBorderSize)
882 : mnLeft(rBorderSize.mnLeft),
883 mnTop(rBorderSize.mnTop),
884 mnRight(rBorderSize.mnRight),
885 mnBottom(rBorderSize.mnBottom)
886 {
887 }
888
889
890
891
operator =(const BorderSize & rBorderSize)892 BorderSize& BorderSize::operator= (const BorderSize& rBorderSize)
893 {
894 if (&rBorderSize != this)
895 {
896 mnLeft = rBorderSize.mnLeft;
897 mnTop = rBorderSize.mnTop;
898 mnRight = rBorderSize.mnRight;
899 mnBottom = rBorderSize.mnBottom;
900 }
901 return *this;
902 }
903
904
905
906
907 //===== RendererPaneStyle ============================================================
908
RendererPaneStyle(const::boost::shared_ptr<PresenterTheme> & rpTheme,const OUString & rsStyleName)909 RendererPaneStyle::RendererPaneStyle (
910 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
911 const OUString& rsStyleName)
912 : mpTopLeft(),
913 mpTop(),
914 mpTopRight(),
915 mpLeft(),
916 mpRight(),
917 mpBottomLeft(),
918 mpBottom(),
919 mpBottomRight(),
920 mpBottomCallout(),
921 mpBackground(),
922 mpEmpty(new PresenterBitmapDescriptor()),
923 mpFont(),
924 mnFontXOffset(0),
925 mnFontYOffset(0),
926 meFontAnchor(AnchorCenter),
927 maInnerBorderSize(),
928 maOuterBorderSize(),
929 maTotalBorderSize()
930 {
931 if (rpTheme.get() != NULL)
932 {
933 mpTopLeft = GetBitmap(rpTheme, rsStyleName, A2S("TopLeft"));
934 mpTop = GetBitmap(rpTheme, rsStyleName, A2S("Top"));
935 mpTopRight = GetBitmap(rpTheme, rsStyleName, A2S("TopRight"));
936 mpLeft = GetBitmap(rpTheme, rsStyleName, A2S("Left"));
937 mpRight = GetBitmap(rpTheme, rsStyleName, A2S("Right"));
938 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, A2S("BottomLeft"));
939 mpBottom = GetBitmap(rpTheme, rsStyleName, A2S("Bottom"));
940 mpBottomRight = GetBitmap(rpTheme, rsStyleName, A2S("BottomRight"));
941 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, A2S("BottomCallout"));
942 mpBackground = GetBitmap(rpTheme, OUString(), A2S("Background"));
943
944 // Get font description.
945 mpFont = rpTheme->GetFont(rsStyleName);
946
947 OUString sAnchor (OUString::createFromAscii("Left"));
948 if (mpFont.get() != NULL)
949 {
950 sAnchor = mpFont->msAnchor;
951 mnFontXOffset = mpFont->mnXOffset;
952 mnFontYOffset = mpFont->mnYOffset;
953 }
954
955 if (sAnchor == OUString::createFromAscii("Left"))
956 meFontAnchor = AnchorLeft;
957 else if (sAnchor == OUString::createFromAscii("Right"))
958 meFontAnchor = AnchorRight;
959 else if (sAnchor == OUString::createFromAscii("Center"))
960 meFontAnchor = AnchorCenter;
961 else
962 meFontAnchor = AnchorCenter;
963
964 // Get border sizes.
965 try
966 {
967 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
968 OSL_ASSERT(aInnerBorder.size()==4);
969 maInnerBorderSize.mnLeft = aInnerBorder[0];
970 maInnerBorderSize.mnTop = aInnerBorder[1];
971 maInnerBorderSize.mnRight = aInnerBorder[2];
972 maInnerBorderSize.mnBottom = aInnerBorder[3];
973
974 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
975 OSL_ASSERT(aOuterBorder.size()==4);
976 maOuterBorderSize.mnLeft = aOuterBorder[0];
977 maOuterBorderSize.mnTop = aOuterBorder[1];
978 maOuterBorderSize.mnRight = aOuterBorder[2];
979 maOuterBorderSize.mnBottom = aOuterBorder[3];
980 }
981 catch(beans::UnknownPropertyException&)
982 {
983 OSL_ASSERT(false);
984 }
985
986 UpdateBorderSizes();
987 }
988 }
989
990
991
992
993
AddBorder(const awt::Rectangle & rBox,const drawing::framework::BorderType eBorderType) const994 awt::Rectangle RendererPaneStyle::AddBorder (
995 const awt::Rectangle& rBox,
996 const drawing::framework::BorderType eBorderType) const
997 {
998 const BorderSize* pBorderSize = NULL;
999 switch (eBorderType)
1000 {
1001 case drawing::framework::BorderType_INNER_BORDER:
1002 pBorderSize = &maInnerBorderSize;
1003 break;
1004 case drawing::framework::BorderType_OUTER_BORDER:
1005 pBorderSize = &maOuterBorderSize;
1006 break;
1007 case drawing::framework::BorderType_TOTAL_BORDER:
1008 pBorderSize = &maTotalBorderSize;
1009 break;
1010 default:
1011 return rBox;
1012 }
1013 return awt::Rectangle (
1014 rBox.X - pBorderSize->mnLeft,
1015 rBox.Y - pBorderSize->mnTop,
1016 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
1017 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
1018 }
1019
1020
1021
1022
RemoveBorder(const awt::Rectangle & rBox,const css::drawing::framework::BorderType eBorderType) const1023 awt::Rectangle RendererPaneStyle::RemoveBorder (
1024 const awt::Rectangle& rBox,
1025 const css::drawing::framework::BorderType eBorderType) const
1026 {
1027 const BorderSize* pBorderSize = NULL;
1028 switch (eBorderType)
1029 {
1030 case drawing::framework::BorderType_INNER_BORDER:
1031 pBorderSize = &maInnerBorderSize;
1032 break;
1033 case drawing::framework::BorderType_OUTER_BORDER:
1034 pBorderSize = &maOuterBorderSize;
1035 break;
1036 case drawing::framework::BorderType_TOTAL_BORDER:
1037 pBorderSize = &maTotalBorderSize;
1038 break;
1039 default:
1040 return rBox;
1041 }
1042 return awt::Rectangle (
1043 rBox.X + pBorderSize->mnLeft,
1044 rBox.Y + pBorderSize->mnTop,
1045 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
1046 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
1047 }
1048
1049
1050
1051
GetFont(const Reference<rendering::XCanvas> & rxCanvas) const1052 const Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
1053 const Reference<rendering::XCanvas>& rxCanvas) const
1054 {
1055 if (mpFont.get() != NULL)
1056 mpFont->PrepareFont(rxCanvas);
1057 return mpFont->mxFont;
1058 }
1059
1060
1061
1062
UpdateBorderSizes(void)1063 void RendererPaneStyle::UpdateBorderSizes (void)
1064 {
1065 maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
1066 maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop;
1067 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
1068 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
1069 }
1070
1071
1072
1073
GetBitmap(const::boost::shared_ptr<PresenterTheme> & rpTheme,const OUString & rsStyleName,const OUString & rsBitmapName)1074 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
1075 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
1076 const OUString& rsStyleName,
1077 const OUString& rsBitmapName)
1078 {
1079 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
1080 if (pDescriptor.get() != NULL)
1081 return pDescriptor;
1082 else
1083 return mpEmpty;
1084 }
1085
1086
1087
1088 } // end of anonymous namespace
1089
1090
1091 } } // end of namespace ::sd::presenter
1092