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