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