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