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 throw(css::uno::RuntimeException)
199 {
200 ThrowIfDisposed();
201
202 ProvideTheme();
203
204 return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
205 }
206
207
208
209
removeBorder(const rtl::OUString & rsPaneBorderStyleName,const css::awt::Rectangle & rRectangle,drawing::framework::BorderType eBorderType)210 awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder (
211 const rtl::OUString& rsPaneBorderStyleName,
212 const css::awt::Rectangle& rRectangle,
213 drawing::framework::BorderType eBorderType)
214 throw(css::uno::RuntimeException)
215 {
216 ThrowIfDisposed();
217
218 ProvideTheme();
219
220 return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType);
221 }
222
223
224
225
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)226 void SAL_CALL PresenterPaneBorderPainter::paintBorder (
227 const rtl::OUString& rsPaneBorderStyleName,
228 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
229 const css::awt::Rectangle& rOuterBorderRectangle,
230 const css::awt::Rectangle& rRepaintArea,
231 const rtl::OUString& rsTitle)
232 throw(css::uno::RuntimeException)
233 {
234 ThrowIfDisposed();
235
236 // Early reject paints completely outside the repaint area.
237 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
238 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
239 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
240 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
241 {
242 return;
243 }
244 ProvideTheme(rxCanvas);
245
246 if (mpRenderer.get() != NULL)
247 {
248 mpRenderer->SetCanvas(rxCanvas);
249 mpRenderer->SetupClipping(
250 rRepaintArea,
251 rOuterBorderRectangle,
252 rsPaneBorderStyleName);
253 mpRenderer->PaintBorder(
254 rsTitle,
255 rOuterBorderRectangle,
256 rRepaintArea,
257 rsPaneBorderStyleName);
258 }
259 }
260
261
262
263
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)264 void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout (
265 const rtl::OUString& rsPaneBorderStyleName,
266 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
267 const css::awt::Rectangle& rOuterBorderRectangle,
268 const css::awt::Rectangle& rRepaintArea,
269 const rtl::OUString& rsTitle,
270 const css::awt::Point& rCalloutAnchor)
271 throw(css::uno::RuntimeException)
272 {
273 ThrowIfDisposed();
274
275 // Early reject paints completely outside the repaint area.
276 if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width
277 || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height
278 || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X
279 || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y)
280 {
281 return;
282 }
283 ProvideTheme(rxCanvas);
284
285 if (mpRenderer.get() != NULL)
286 {
287 mpRenderer->SetCanvas(rxCanvas);
288 mpRenderer->SetupClipping(
289 rRepaintArea,
290 rOuterBorderRectangle,
291 rsPaneBorderStyleName);
292 mpRenderer->SetCalloutAnchor(rCalloutAnchor);
293 mpRenderer->PaintBorder(
294 rsTitle,
295 rOuterBorderRectangle,
296 rRepaintArea,
297 rsPaneBorderStyleName);
298 }
299 }
300
301
302
303
getCalloutOffset(const rtl::OUString & rsPaneBorderStyleName)304 awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset (
305 const rtl::OUString& rsPaneBorderStyleName)
306 throw(css::uno::RuntimeException)
307 {
308 ThrowIfDisposed();
309 ProvideTheme();
310 if (mpRenderer.get() != NULL)
311 {
312 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(
313 mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName));
314 if (pRendererPaneStyle.get() != NULL
315 && pRendererPaneStyle->mpBottomCallout.get() != NULL)
316 {
317 return awt::Point (
318 0,
319 pRendererPaneStyle->mpBottomCallout->mnHeight
320 - pRendererPaneStyle->mpBottomCallout->mnYHotSpot);
321 }
322 }
323
324 return awt::Point(0,0);
325 }
326
327
328
329
330 //-----------------------------------------------------------------------------
331
ProvideTheme(const Reference<rendering::XCanvas> & rxCanvas)332 bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas)
333 {
334 bool bModified (false);
335
336 if ( ! mxContext.is())
337 return false;
338
339 if (mpTheme.get() != NULL)
340 {
341 // Check if the theme already has a canvas.
342 if ( ! mpTheme->HasCanvas())
343 {
344 mpTheme->ProvideCanvas(rxCanvas);
345 bModified = true;
346 }
347 }
348 else
349 {
350 mpTheme.reset(new PresenterTheme(mxContext, OUString(), rxCanvas));
351 bModified = true;
352 }
353
354 if (mpTheme.get() != NULL && bModified)
355 {
356 if (mpRenderer.get() == NULL)
357 mpRenderer.reset(new Renderer(mxContext, mpTheme));
358 else
359 mpRenderer->SetCanvas(rxCanvas);
360 }
361
362 return bModified;
363 }
364
365
366
367
ProvideTheme(void)368 bool PresenterPaneBorderPainter::ProvideTheme (void)
369 {
370 if (mpTheme.get() == NULL)
371 {
372 // Create a theme without bitmaps (no canvas => no bitmaps).
373 return ProvideTheme(NULL);
374 }
375 else
376 {
377 // When there already is a theme then without a canvas we can not
378 // add anything new.
379 return false;
380 }
381 }
382
383
384
385
HasTheme(void) const386 bool PresenterPaneBorderPainter::HasTheme (void) const
387 {
388 return mpTheme.get()!=NULL && mpRenderer.get()!=NULL;
389 }
390
391
392
393
SetTheme(const::boost::shared_ptr<PresenterTheme> & rpTheme)394 void PresenterPaneBorderPainter::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme)
395 {
396 mpTheme = rpTheme;
397 if (mpRenderer.get() == NULL)
398 mpRenderer.reset(new Renderer(mxContext, mpTheme));
399 }
400
401
402
403
AddBorder(const::rtl::OUString & rsPaneURL,const awt::Rectangle & rInnerBox,const css::drawing::framework::BorderType eBorderType) const404 awt::Rectangle PresenterPaneBorderPainter::AddBorder (
405 const ::rtl::OUString& rsPaneURL,
406 const awt::Rectangle& rInnerBox,
407 const css::drawing::framework::BorderType eBorderType) const
408 {
409 if (mpRenderer.get() != NULL)
410 {
411 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
412 if (pRendererPaneStyle.get() != NULL)
413 return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType);
414 }
415 return rInnerBox;
416 }
417
418
419
420
RemoveBorder(const::rtl::OUString & rsPaneURL,const css::awt::Rectangle & rOuterBox,const css::drawing::framework::BorderType eBorderType) const421 awt::Rectangle PresenterPaneBorderPainter::RemoveBorder (
422 const ::rtl::OUString& rsPaneURL,
423 const css::awt::Rectangle& rOuterBox,
424 const css::drawing::framework::BorderType eBorderType) const
425 {
426 if (mpRenderer.get() != NULL)
427 {
428 const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL));
429 if (pRendererPaneStyle.get() != NULL)
430 return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType);
431 }
432 return rOuterBox;
433 }
434
435
436
437
ThrowIfDisposed(void) const438 void PresenterPaneBorderPainter::ThrowIfDisposed (void) const
439 throw (::com::sun::star::lang::DisposedException)
440 {
441 if (rBHelper.bDisposed || rBHelper.bInDispose)
442 {
443 throw lang::DisposedException (
444 OUString(RTL_CONSTASCII_USTRINGPARAM(
445 "PresenterPaneBorderPainter object has already been disposed")),
446 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
447 }
448 }
449
450
451
452
453 //===== PresenterPaneBorderPainter::Renderer =====================================
454
455
Renderer(const Reference<XComponentContext> & rxContext,const::boost::shared_ptr<PresenterTheme> & rpTheme)456 PresenterPaneBorderPainter::Renderer::Renderer (
457 const Reference<XComponentContext>& rxContext,
458 const ::boost::shared_ptr<PresenterTheme>& rpTheme)
459 : mpTheme(rpTheme),
460 maRendererPaneStyles(),
461 mxCanvas(),
462 mxPresenterHelper(),
463 maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
464 mxViewStateClip(),
465 mbHasCallout(false),
466 maCalloutAnchor()
467 {
468 (void)rxContext;
469
470 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
471 if (xFactory.is())
472 {
473 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
474 xFactory->createInstanceWithContext(
475 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
476 rxContext),
477 UNO_QUERY_THROW);
478 }
479 }
480
481
482
483
~Renderer(void)484 PresenterPaneBorderPainter::Renderer::~Renderer (void)
485 {
486 }
487
488
489
490
SetCanvas(const Reference<rendering::XCanvas> & rxCanvas)491 void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas)
492 {
493 if (mxCanvas != rxCanvas)
494 {
495 mxCanvas = rxCanvas;
496 }
497 }
498
499
500
501
PaintBorder(const OUString & rsTitle,const awt::Rectangle & rBBox,const awt::Rectangle & rUpdateBox,const OUString & rsPaneURL)502 void PresenterPaneBorderPainter::Renderer::PaintBorder (
503 const OUString& rsTitle,
504 const awt::Rectangle& rBBox,
505 const awt::Rectangle& rUpdateBox,
506 const OUString& rsPaneURL)
507 {
508 if ( ! mxCanvas.is())
509 return;
510
511 // Create the outer and inner border of the, ahm, border.
512 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL));
513 if (pStyle.get() == NULL)
514 return;
515
516 awt::Rectangle aOuterBox (rBBox);
517 awt::Rectangle aCenterBox (
518 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER));
519 awt::Rectangle aInnerBox (
520 pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
521
522 // Prepare references for all used bitmaps.
523 SharedBitmapDescriptor pTop (pStyle->mpTop);
524 SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft);
525 SharedBitmapDescriptor pTopRight (pStyle->mpTopRight);
526 SharedBitmapDescriptor pLeft (pStyle->mpLeft);
527 SharedBitmapDescriptor pRight (pStyle->mpRight);
528 SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft);
529 SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight);
530 SharedBitmapDescriptor pBottom (pStyle->mpBottom);
531 SharedBitmapDescriptor pBackground (pStyle->mpBackground);
532
533 // Paint the sides.
534 PaintBitmap(aCenterBox, rUpdateBox, 0,-1,
535 pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop, pBackground);
536 PaintBitmap(aCenterBox, rUpdateBox, -1,0,
537 pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft, pBackground);
538 PaintBitmap(aCenterBox, rUpdateBox, +1,0,
539 pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight, pBackground);
540 if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is())
541 {
542 const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth);
543 sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot
544 - (aCenterBox.X - aOuterBox.X));
545 if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X)
546 nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X;
547 if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width)
548 nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width;
549 // Paint bottom callout.
550 PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout, pBackground);
551 // Paint regular bottom bitmap left and right.
552 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
553 pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom, pBackground);
554 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
555 nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom, pBackground);
556 }
557 else
558 {
559 // Stretch the bottom bitmap over the full width.
560 PaintBitmap(aCenterBox, rUpdateBox, 0,+1,
561 pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom, pBackground);
562 }
563
564 // Paint the corners.
565 PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft, pBackground);
566 PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight, pBackground);
567 PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft, pBackground);
568 PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight, pBackground);
569
570 // Paint the title.
571 PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox, false);
572
573 // In a double buffering environment request to make the changes visible.
574 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
575 if (xSpriteCanvas.is())
576 xSpriteCanvas->updateScreen(sal_False);
577 }
578
579
580
581
PaintTitle(const OUString & rsTitle,const::boost::shared_ptr<RendererPaneStyle> & rpStyle,const awt::Rectangle & rUpdateBox,const awt::Rectangle & rOuterBox,const awt::Rectangle & rInnerBox,bool bPaintBackground)582 void PresenterPaneBorderPainter::Renderer::PaintTitle (
583 const OUString& rsTitle,
584 const ::boost::shared_ptr<RendererPaneStyle>& rpStyle,
585 const awt::Rectangle& rUpdateBox,
586 const awt::Rectangle& rOuterBox,
587 const awt::Rectangle& rInnerBox,
588 bool bPaintBackground)
589 {
590 if ( ! mxCanvas.is())
591 return;
592
593 if (rsTitle.getLength() == 0)
594 return;
595
596 Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas));
597 if ( ! xFont.is())
598 return;
599
600 rendering::StringContext aContext (
601 rsTitle,
602 0,
603 rsTitle.getLength());
604 Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout(
605 aContext,
606 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
607 0));
608 if ( ! xLayout.is())
609 return;
610
611 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
612 const double nTextHeight = aBox.Y2 - aBox.Y1;
613 const double nTextWidth = aBox.X2 - aBox.X1;
614 double nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
615 const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1;
616 double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1;
617 if (nY >= rInnerBox.Y)
618 nY = rInnerBox.Y - 1;
619 switch (rpStyle->meFontAnchor)
620 {
621 default:
622 case RendererPaneStyle::AnchorLeft:
623 nX = rInnerBox.X;
624 break;
625 case RendererPaneStyle::AnchorRight:
626 nX = rInnerBox.X + rInnerBox.Width - nTextWidth;
627 break;
628 case RendererPaneStyle::AnchorCenter:
629 nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2;
630 break;
631 }
632 nX += rpStyle->mnFontXOffset;
633 nY += rpStyle->mnFontYOffset;
634
635 if (rUpdateBox.X >= nX+nTextWidth
636 || rUpdateBox.Y >= nY+nTextHeight
637 || rUpdateBox.X+rUpdateBox.Width <= nX
638 || rUpdateBox.Y+rUpdateBox.Height <= nY)
639 {
640 return;
641 }
642
643 rendering::RenderState aRenderState(
644 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
645 NULL,
646 Sequence<double>(4),
647 rendering::CompositeOperation::SOURCE);
648
649 if (bPaintBackground)
650 {
651 PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff));
652 Sequence<Sequence<geometry::RealPoint2D> > aPolygons(1);
653 aPolygons[0] = Sequence<geometry::RealPoint2D>(4);
654 aPolygons[0][0] = geometry::RealPoint2D(0, -nTextHeight);
655 aPolygons[0][1] = geometry::RealPoint2D(0, 0);
656 aPolygons[0][2] = geometry::RealPoint2D(nTextWidth, 0);
657 aPolygons[0][3] = geometry::RealPoint2D(nTextWidth, -nTextHeight);
658 Reference<rendering::XPolyPolygon2D> xPolygon (
659 mxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPolygons), UNO_QUERY);
660 if (xPolygon.is())
661 xPolygon->setClosed(0, sal_True);
662 mxCanvas->fillPolyPolygon(
663 xPolygon,
664 maViewState,
665 aRenderState);
666 }
667 else
668 {
669 PresenterCanvasHelper::SetDeviceColor(
670 aRenderState,
671 rpStyle->mpFont->mnColor);
672
673 mxCanvas->drawText(
674 aContext,
675 xFont,
676 maViewState,
677 aRenderState,
678 rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
679 }
680 }
681
682
683
684 ::boost::shared_ptr<RendererPaneStyle>
GetRendererPaneStyle(const OUString & rsResourceURL)685 PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL)
686 {
687 OSL_ASSERT(mpTheme.get()!=NULL);
688
689 RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL));
690 if (iStyle == maRendererPaneStyles.end())
691 {
692 OUString sPaneStyleName (OUString::createFromAscii("DefaultRendererPaneStyle"));
693
694 // Get pane layout name for resource URL.
695 const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL));
696 if (sStyleName.getLength() > 0)
697 sPaneStyleName = sStyleName;
698
699 // Create a new pane style object and initialize it with bitmaps.
700 ::boost::shared_ptr<RendererPaneStyle> pStyle (
701 new RendererPaneStyle(mpTheme,sPaneStyleName));
702 iStyle = maRendererPaneStyles.insert(
703 RendererPaneStyleContainer::value_type(rsResourceURL, pStyle)).first;
704 }
705 if (iStyle != maRendererPaneStyles.end())
706 return iStyle->second;
707 else
708 return ::boost::shared_ptr<RendererPaneStyle>();
709 }
710
711
712
713
SetCalloutAnchor(const awt::Point & rCalloutAnchor)714 void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor (
715 const awt::Point& rCalloutAnchor)
716 {
717 mbHasCallout = true;
718 maCalloutAnchor = rCalloutAnchor;
719 }
720
721
722
723
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)724 void PresenterPaneBorderPainter::Renderer::PaintBitmap(
725 const awt::Rectangle& rBox,
726 const awt::Rectangle& rUpdateBox,
727 const sal_Int32 nXPosition,
728 const sal_Int32 nYPosition,
729 const sal_Int32 nStartOffset,
730 const sal_Int32 nEndOffset,
731 const bool bExpand,
732 const SharedBitmapDescriptor& rpBitmap,
733 const SharedBitmapDescriptor& rpBackgroundBitmap)
734 {
735 (void)rpBackgroundBitmap;
736
737 bool bUseCanvas (mxCanvas.is());
738 if ( ! bUseCanvas)
739 return;
740
741 if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0)
742 return;
743
744 Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY);
745 if ( ! xBitmap.is())
746 return;
747
748 // Calculate position, and for side bitmaps, the size.
749 sal_Int32 nX = 0;
750 sal_Int32 nY = 0;
751 sal_Int32 nW = rpBitmap->mnWidth;
752 sal_Int32 nH = rpBitmap->mnHeight;
753 if (nXPosition < 0)
754 {
755 nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset;
756 }
757 else if (nXPosition > 0)
758 {
759 nX = rBox.X + rBox.Width + rpBitmap->mnXOffset;
760 }
761 else
762 {
763 nX = rBox.X + nStartOffset;
764 if (bExpand)
765 nW = rBox.Width - nStartOffset + nEndOffset;
766 }
767
768 if (nYPosition < 0)
769 {
770 nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset;
771 }
772 else if (nYPosition > 0)
773 {
774 nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset;
775 }
776 else
777 {
778 nY = rBox.Y + nStartOffset;
779 if (bExpand)
780 nH = rBox.Height - nStartOffset + nEndOffset;
781 }
782
783 // Do not paint when bitmap area does not intersect with update box.
784 if (nX >= rUpdateBox.X + rUpdateBox.Width
785 || nX+nW <= rUpdateBox.X
786 || nY >= rUpdateBox.Y + rUpdateBox.Height
787 || nY+nH <= rUpdateBox.Y)
788 {
789 return;
790 }
791
792 /*
793 Reference<rendering::XBitmap> xMaskedBitmap (
794 PresenterBitmapHelper::FillMaskedWithColor (
795 mxCanvas,
796 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
797 rBitmap.mxMaskBitmap,
798 0x00ff0000,
799 rBackgroundBitmap.maReplacementColor));
800 if (xMaskedBitmap.is())
801 xBitmap = xMaskedBitmap;
802 else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is())
803 {
804 const static sal_Int32 nOutsideMaskColor (0x00ff0000);
805 Reference<rendering::XIntegerBitmap> xMask (
806 mxPresenterHelper->createMask(
807 mxCanvas,
808 rBitmap.mxMaskBitmap,
809 nOutsideMaskColor,
810 false));
811 xBitmap = mxPresenterHelper->applyBitmapMaskWithColor(
812 mxCanvas,
813 Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY),
814 xMask,
815 rBackgroundBitmap.maReplacementColor);
816 }
817 */
818 rendering::RenderState aRenderState (
819 geometry::AffineMatrix2D(
820 double(nW)/rpBitmap->mnWidth, 0, nX,
821 0, double(nH)/rpBitmap->mnHeight, nY),
822 NULL,
823 Sequence<double>(4),
824 rendering::CompositeOperation::OVER);
825
826 if (xBitmap.is())
827 mxCanvas->drawBitmap(
828 xBitmap,
829 maViewState,
830 aRenderState);
831 }
832
833
834
835
SetupClipping(const awt::Rectangle & rUpdateBox,const awt::Rectangle & rOuterBox,const OUString & rsPaneStyleName)836 void PresenterPaneBorderPainter::Renderer::SetupClipping (
837 const awt::Rectangle& rUpdateBox,
838 const awt::Rectangle& rOuterBox,
839 const OUString& rsPaneStyleName)
840 {
841 mxViewStateClip = NULL;
842 maViewState.Clip = NULL;
843
844 if ( ! mxCanvas.is())
845 return;
846
847 ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName));
848 if (pStyle.get() == NULL)
849 {
850 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
851 rUpdateBox,
852 mxCanvas->getDevice());
853 }
854 else
855 {
856 awt::Rectangle aInnerBox (
857 pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER));
858 ::std::vector<awt::Rectangle> aRectangles;
859 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox));
860 aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox));
861 mxViewStateClip = PresenterGeometryHelper::CreatePolygon(
862 aRectangles,
863 mxCanvas->getDevice());
864 if (mxViewStateClip.is())
865 mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD);
866 }
867 maViewState.Clip = mxViewStateClip;
868 }
869
870
871
872 namespace {
873
874 //===== BorderSize ============================================================
875
BorderSize(void)876 BorderSize::BorderSize (void)
877 : mnLeft(0),
878 mnTop(0),
879 mnRight(0),
880 mnBottom(0)
881 {
882 }
883
884
885
886
BorderSize(const BorderSize & rBorderSize)887 BorderSize::BorderSize (const BorderSize& rBorderSize)
888 : mnLeft(rBorderSize.mnLeft),
889 mnTop(rBorderSize.mnTop),
890 mnRight(rBorderSize.mnRight),
891 mnBottom(rBorderSize.mnBottom)
892 {
893 }
894
895
896
897
operator =(const BorderSize & rBorderSize)898 BorderSize& BorderSize::operator= (const BorderSize& rBorderSize)
899 {
900 if (&rBorderSize != this)
901 {
902 mnLeft = rBorderSize.mnLeft;
903 mnTop = rBorderSize.mnTop;
904 mnRight = rBorderSize.mnRight;
905 mnBottom = rBorderSize.mnBottom;
906 }
907 return *this;
908 }
909
910
911
912
913 //===== RendererPaneStyle ============================================================
914
RendererPaneStyle(const::boost::shared_ptr<PresenterTheme> & rpTheme,const OUString & rsStyleName)915 RendererPaneStyle::RendererPaneStyle (
916 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
917 const OUString& rsStyleName)
918 : mpTopLeft(),
919 mpTop(),
920 mpTopRight(),
921 mpLeft(),
922 mpRight(),
923 mpBottomLeft(),
924 mpBottom(),
925 mpBottomRight(),
926 mpBottomCallout(),
927 mpBackground(),
928 mpEmpty(new PresenterBitmapDescriptor()),
929 mpFont(),
930 mnFontXOffset(0),
931 mnFontYOffset(0),
932 meFontAnchor(AnchorCenter),
933 maInnerBorderSize(),
934 maOuterBorderSize(),
935 maTotalBorderSize()
936 {
937 if (rpTheme.get() != NULL)
938 {
939 mpTopLeft = GetBitmap(rpTheme, rsStyleName, A2S("TopLeft"));
940 mpTop = GetBitmap(rpTheme, rsStyleName, A2S("Top"));
941 mpTopRight = GetBitmap(rpTheme, rsStyleName, A2S("TopRight"));
942 mpLeft = GetBitmap(rpTheme, rsStyleName, A2S("Left"));
943 mpRight = GetBitmap(rpTheme, rsStyleName, A2S("Right"));
944 mpBottomLeft = GetBitmap(rpTheme, rsStyleName, A2S("BottomLeft"));
945 mpBottom = GetBitmap(rpTheme, rsStyleName, A2S("Bottom"));
946 mpBottomRight = GetBitmap(rpTheme, rsStyleName, A2S("BottomRight"));
947 mpBottomCallout = GetBitmap(rpTheme, rsStyleName, A2S("BottomCallout"));
948 mpBackground = GetBitmap(rpTheme, OUString(), A2S("Background"));
949
950 // Get font description.
951 mpFont = rpTheme->GetFont(rsStyleName);
952
953 OUString sAnchor (OUString::createFromAscii("Left"));
954 if (mpFont.get() != NULL)
955 {
956 sAnchor = mpFont->msAnchor;
957 mnFontXOffset = mpFont->mnXOffset;
958 mnFontYOffset = mpFont->mnYOffset;
959 }
960
961 if (sAnchor == OUString::createFromAscii("Left"))
962 meFontAnchor = AnchorLeft;
963 else if (sAnchor == OUString::createFromAscii("Right"))
964 meFontAnchor = AnchorRight;
965 else if (sAnchor == OUString::createFromAscii("Center"))
966 meFontAnchor = AnchorCenter;
967 else
968 meFontAnchor = AnchorCenter;
969
970 // Get border sizes.
971 try
972 {
973 ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false));
974 OSL_ASSERT(aInnerBorder.size()==4);
975 maInnerBorderSize.mnLeft = aInnerBorder[0];
976 maInnerBorderSize.mnTop = aInnerBorder[1];
977 maInnerBorderSize.mnRight = aInnerBorder[2];
978 maInnerBorderSize.mnBottom = aInnerBorder[3];
979
980 ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true));
981 OSL_ASSERT(aOuterBorder.size()==4);
982 maOuterBorderSize.mnLeft = aOuterBorder[0];
983 maOuterBorderSize.mnTop = aOuterBorder[1];
984 maOuterBorderSize.mnRight = aOuterBorder[2];
985 maOuterBorderSize.mnBottom = aOuterBorder[3];
986 }
987 catch(beans::UnknownPropertyException&)
988 {
989 OSL_ASSERT(false);
990 }
991
992 UpdateBorderSizes();
993 }
994 }
995
996
997
998
999
AddBorder(const awt::Rectangle & rBox,const drawing::framework::BorderType eBorderType) const1000 awt::Rectangle RendererPaneStyle::AddBorder (
1001 const awt::Rectangle& rBox,
1002 const drawing::framework::BorderType eBorderType) const
1003 {
1004 const BorderSize* pBorderSize = NULL;
1005 switch (eBorderType)
1006 {
1007 case drawing::framework::BorderType_INNER_BORDER:
1008 pBorderSize = &maInnerBorderSize;
1009 break;
1010 case drawing::framework::BorderType_OUTER_BORDER:
1011 pBorderSize = &maOuterBorderSize;
1012 break;
1013 case drawing::framework::BorderType_TOTAL_BORDER:
1014 pBorderSize = &maTotalBorderSize;
1015 break;
1016 default:
1017 return rBox;
1018 }
1019 return awt::Rectangle (
1020 rBox.X - pBorderSize->mnLeft,
1021 rBox.Y - pBorderSize->mnTop,
1022 rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight,
1023 rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom);
1024 }
1025
1026
1027
1028
RemoveBorder(const awt::Rectangle & rBox,const css::drawing::framework::BorderType eBorderType) const1029 awt::Rectangle RendererPaneStyle::RemoveBorder (
1030 const awt::Rectangle& rBox,
1031 const css::drawing::framework::BorderType eBorderType) const
1032 {
1033 const BorderSize* pBorderSize = NULL;
1034 switch (eBorderType)
1035 {
1036 case drawing::framework::BorderType_INNER_BORDER:
1037 pBorderSize = &maInnerBorderSize;
1038 break;
1039 case drawing::framework::BorderType_OUTER_BORDER:
1040 pBorderSize = &maOuterBorderSize;
1041 break;
1042 case drawing::framework::BorderType_TOTAL_BORDER:
1043 pBorderSize = &maTotalBorderSize;
1044 break;
1045 default:
1046 return rBox;
1047 }
1048 return awt::Rectangle (
1049 rBox.X + pBorderSize->mnLeft,
1050 rBox.Y + pBorderSize->mnTop,
1051 rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight,
1052 rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom);
1053 }
1054
1055
1056
1057
GetFont(const Reference<rendering::XCanvas> & rxCanvas) const1058 const Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont (
1059 const Reference<rendering::XCanvas>& rxCanvas) const
1060 {
1061 if (mpFont.get() != NULL)
1062 mpFont->PrepareFont(rxCanvas);
1063 return mpFont->mxFont;
1064 }
1065
1066
1067
1068
UpdateBorderSizes(void)1069 void RendererPaneStyle::UpdateBorderSizes (void)
1070 {
1071 maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft;
1072 maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop;
1073 maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight;
1074 maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom;
1075 }
1076
1077
1078
1079
GetBitmap(const::boost::shared_ptr<PresenterTheme> & rpTheme,const OUString & rsStyleName,const OUString & rsBitmapName)1080 SharedBitmapDescriptor RendererPaneStyle::GetBitmap(
1081 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
1082 const OUString& rsStyleName,
1083 const OUString& rsBitmapName)
1084 {
1085 SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName));
1086 if (pDescriptor.get() != NULL)
1087 return pDescriptor;
1088 else
1089 return mpEmpty;
1090 }
1091
1092
1093
1094 } // end of anonymous namespace
1095
1096
1097 } } // end of namespace ::sd::presenter
1098