xref: /trunk/main/sdext/source/presenter/PresenterPaneBorderPainter.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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