LibreOffice Module sd (master) 1
PresenterCanvas.cxx
Go to the documentation of this file.
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 "PresenterCanvas.hxx"
22
29#include <com/sun/star/awt/XWindow.hpp>
31#include <rtl/ref.hxx>
33#include <utility>
34#include <vcl/window.hxx>
35
36using namespace ::com::sun::star;
37using namespace ::com::sun::star::uno;
38
39namespace sd::presenter {
40
41//===== PresenterCustomSprite =================================================
42
45namespace {
47 css::rendering::XCustomSprite
48 > PresenterCustomSpriteInterfaceBase;
49
50class PresenterCustomSprite final
51 : public PresenterCustomSpriteInterfaceBase
52{
53public:
54 PresenterCustomSprite (
56 const Reference<rendering::XCustomSprite>& rxSprite,
57 const Reference<awt::XWindow>& rxBaseWindow);
58 PresenterCustomSprite(const PresenterCustomSprite&) = delete;
59 PresenterCustomSprite& operator=(const PresenterCustomSprite&) = delete;
60 virtual void disposing(std::unique_lock<std::mutex>&) override;
61
62 // XSprite
63
64 virtual void SAL_CALL setAlpha (double nAlpha) override;
65
66 virtual void SAL_CALL move (const geometry::RealPoint2D& rNewPos,
67 const rendering::ViewState& rViewState,
68 const rendering::RenderState& rRenderState) override;
69
70 virtual void SAL_CALL transform (const geometry::AffineMatrix2D& rTransformation) override;
71
72 virtual void SAL_CALL clip (const Reference<rendering::XPolyPolygon2D>& rClip) override;
73
74 virtual void SAL_CALL setPriority (double nPriority) override;
75
76 virtual void SAL_CALL show() override;
77
78 virtual void SAL_CALL hide() override;
79
80 // XCustomSprite
81
82 virtual Reference<rendering::XCanvas> SAL_CALL getContentCanvas() override;
83
84private:
86 Reference<rendering::XCustomSprite> mxSprite;
87 Reference<awt::XWindow> mxBaseWindow;
88 geometry::RealPoint2D maPosition;
89
91 void ThrowIfDisposed();
92};
93
94}
95
96//===== PresenterCanvas =======================================================
97
99 const Reference<rendering::XSpriteCanvas>& rxUpdateCanvas,
100 const Reference<awt::XWindow>& rxUpdateWindow,
101 const Reference<rendering::XCanvas>& rxSharedCanvas,
102 const Reference<awt::XWindow>& rxSharedWindow,
103 const Reference<awt::XWindow>& rxWindow)
104 : mxUpdateCanvas(rxUpdateCanvas),
105 mxUpdateWindow(rxUpdateWindow),
106 mxSharedCanvas(rxSharedCanvas),
107 mxSharedWindow(rxSharedWindow),
108 mxWindow(rxWindow),
109 mbOffsetUpdatePending(true)
110{
111 if (mxWindow.is())
112 mxWindow->addWindowListener(this);
113
114 if (mxUpdateCanvas.is())
115 {
116 m_pUpdateRequester = CanvasUpdateRequester::Instance(mxUpdateCanvas);
117 }
118}
119
120PresenterCanvas::~PresenterCanvas()
121{
122}
123
124void PresenterCanvas::disposing(std::unique_lock<std::mutex>&)
125{
126 if (mxWindow.is())
127 {
128 mxWindow->removeWindowListener(this);
129 mxWindow.clear();
130 }
131}
132
133//----- XCanvas ---------------------------------------------------------------
134
135void SAL_CALL PresenterCanvas::clear()
136{
137 ThrowIfDisposed();
138 // ToDo: Clear the area covered by the child window. A simple forward
139 // would clear the whole shared canvas.
140}
141
142void SAL_CALL PresenterCanvas::drawPoint (
143 const css::geometry::RealPoint2D& aPoint,
144 const css::rendering::ViewState& aViewState,
145 const css::rendering::RenderState& aRenderState)
146{
147 ThrowIfDisposed();
148 mxSharedCanvas->drawPoint(aPoint,MergeViewState(aViewState),aRenderState);
149}
150
151void SAL_CALL PresenterCanvas::drawLine (
152 const css::geometry::RealPoint2D& aStartPoint,
153 const css::geometry::RealPoint2D& aEndPoint,
154 const css::rendering::ViewState& aViewState,
155 const css::rendering::RenderState& aRenderState)
156{
157 ThrowIfDisposed();
158 mxSharedCanvas->drawLine(aStartPoint,aEndPoint,MergeViewState(aViewState),aRenderState);
159}
160
161void SAL_CALL PresenterCanvas::drawBezier (
162 const css::geometry::RealBezierSegment2D& aBezierSegment,
163 const css::geometry::RealPoint2D& aEndPoint,
164 const css::rendering::ViewState& aViewState,
165 const css::rendering::RenderState& aRenderState)
166{
167 ThrowIfDisposed();
168 mxSharedCanvas->drawBezier(aBezierSegment,aEndPoint,MergeViewState(aViewState),aRenderState);
169}
170
171css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL PresenterCanvas::drawPolyPolygon (
172 const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
173 const css::rendering::ViewState& aViewState,
174 const css::rendering::RenderState& aRenderState)
175{
176 ThrowIfDisposed();
177 return mxSharedCanvas->drawPolyPolygon(
178 xPolyPolygon, MergeViewState(aViewState), aRenderState);
179}
180
181css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL PresenterCanvas::strokePolyPolygon (
182 const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
183 const css::rendering::ViewState& aViewState,
184 const css::rendering::RenderState& aRenderState,
185 const css::rendering::StrokeAttributes& aStrokeAttributes)
186{
187 ThrowIfDisposed();
188 return mxSharedCanvas->strokePolyPolygon(
189 xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes);
190}
191
192css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
193 PresenterCanvas::strokeTexturedPolyPolygon (
194 const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
195 const css::rendering::ViewState& aViewState,
196 const css::rendering::RenderState& aRenderState,
197 const css::uno::Sequence< css::rendering::Texture >& aTextures,
198 const css::rendering::StrokeAttributes& aStrokeAttributes)
199{
200 ThrowIfDisposed();
201 return mxSharedCanvas->strokeTexturedPolyPolygon(
202 xPolyPolygon, MergeViewState(aViewState), aRenderState, aTextures, aStrokeAttributes);
203}
204
205css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
206 PresenterCanvas::strokeTextureMappedPolyPolygon(
207 const css::uno::Reference<css::rendering::XPolyPolygon2D >& xPolyPolygon,
208 const css::rendering::ViewState& aViewState,
209 const css::rendering::RenderState& aRenderState,
210 const css::uno::Sequence<css::rendering::Texture>& aTextures,
211 const css::uno::Reference<css::geometry::XMapping2D>& xMapping,
212 const css::rendering::StrokeAttributes& aStrokeAttributes)
213{
214 ThrowIfDisposed();
215 return mxSharedCanvas->strokeTextureMappedPolyPolygon(
216 xPolyPolygon,
217 MergeViewState(aViewState),
218 aRenderState,
219 aTextures,
220 xMapping,
221 aStrokeAttributes);
222}
223
224css::uno::Reference<css::rendering::XPolyPolygon2D> SAL_CALL
225 PresenterCanvas::queryStrokeShapes(
226 const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
227 const css::rendering::ViewState& aViewState,
228 const css::rendering::RenderState& aRenderState,
229 const css::rendering::StrokeAttributes& aStrokeAttributes)
230{
231 ThrowIfDisposed();
232 return mxSharedCanvas->queryStrokeShapes(
233 xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes);
234}
235
236css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
237 PresenterCanvas::fillPolyPolygon(
238 const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
239 const css::rendering::ViewState& aViewState,
240 const css::rendering::RenderState& aRenderState)
241{
242 ThrowIfDisposed();
243 return mxSharedCanvas->fillPolyPolygon(
244 xPolyPolygon, MergeViewState(aViewState), aRenderState);
245}
246
247css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
248 PresenterCanvas::fillTexturedPolyPolygon(
249 const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
250 const css::rendering::ViewState& aViewState,
251 const css::rendering::RenderState& aRenderState,
252 const css::uno::Sequence<css::rendering::Texture>& xTextures)
253{
254 ThrowIfDisposed();
255 return mxSharedCanvas->fillTexturedPolyPolygon(
256 xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures);
257}
258
259css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
260 PresenterCanvas::fillTextureMappedPolyPolygon(
261 const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
262 const css::rendering::ViewState& aViewState,
263 const css::rendering::RenderState& aRenderState,
264 const css::uno::Sequence< css::rendering::Texture >& xTextures,
265 const css::uno::Reference< css::geometry::XMapping2D >& xMapping)
266{
267 ThrowIfDisposed();
268 return mxSharedCanvas->fillTextureMappedPolyPolygon(
269 xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures, xMapping);
270}
271
272css::uno::Reference<css::rendering::XCanvasFont> SAL_CALL
273 PresenterCanvas::createFont(
274 const css::rendering::FontRequest& aFontRequest,
275 const css::uno::Sequence< css::beans::PropertyValue >& aExtraFontProperties,
276 const css::geometry::Matrix2D& aFontMatrix)
277{
278 ThrowIfDisposed();
279 return mxSharedCanvas->createFont(
280 aFontRequest, aExtraFontProperties, aFontMatrix);
281}
282
283css::uno::Sequence<css::rendering::FontInfo> SAL_CALL
284 PresenterCanvas::queryAvailableFonts(
285 const css::rendering::FontInfo& aFilter,
286 const css::uno::Sequence< css::beans::PropertyValue >& aFontProperties)
287{
288 ThrowIfDisposed();
289 return mxSharedCanvas->queryAvailableFonts(aFilter, aFontProperties);
290}
291
292css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
293 PresenterCanvas::drawText(
294 const css::rendering::StringContext& aText,
295 const css::uno::Reference< css::rendering::XCanvasFont >& xFont,
296 const css::rendering::ViewState& aViewState,
297 const css::rendering::RenderState& aRenderState,
298 ::sal_Int8 nTextDirection)
299{
300 ThrowIfDisposed();
301 return mxSharedCanvas->drawText(
302 aText, xFont, MergeViewState(aViewState), aRenderState, nTextDirection);
303}
304
305css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
306 PresenterCanvas::drawTextLayout(
307 const css::uno::Reference< css::rendering::XTextLayout >& xLayoutetText,
308 const css::rendering::ViewState& aViewState,
309 const css::rendering::RenderState& aRenderState)
310{
311 ThrowIfDisposed();
312 return mxSharedCanvas->drawTextLayout(
313 xLayoutetText, MergeViewState(aViewState), aRenderState);
314}
315
316css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
317 PresenterCanvas::drawBitmap(
318 const css::uno::Reference< css::rendering::XBitmap >& xBitmap,
319 const css::rendering::ViewState& aViewState,
320 const css::rendering::RenderState& aRenderState)
321{
322 ThrowIfDisposed();
323 return mxSharedCanvas->drawBitmap(
324 xBitmap, MergeViewState(aViewState), aRenderState);
325}
326
327css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
328 PresenterCanvas::drawBitmapModulated(
329 const css::uno::Reference< css::rendering::XBitmap>& xBitmap,
330 const css::rendering::ViewState& aViewState,
331 const css::rendering::RenderState& aRenderState)
332{
333 ThrowIfDisposed();
334 return mxSharedCanvas->drawBitmapModulated(
335 xBitmap, MergeViewState(aViewState), aRenderState);
336}
337
338css::uno::Reference<css::rendering::XGraphicDevice> SAL_CALL
339 PresenterCanvas::getDevice()
340{
341 ThrowIfDisposed();
342 return mxSharedCanvas->getDevice();
343}
344
345//----- XSpriteCanvas ---------------------------------------------------------
346
347Reference<rendering::XAnimatedSprite> SAL_CALL
348 PresenterCanvas::createSpriteFromAnimation (
349 const css::uno::Reference<css::rendering::XAnimation>& rAnimation)
350{
351 ThrowIfDisposed();
352
353 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
354 if (xSpriteCanvas.is())
355 return xSpriteCanvas->createSpriteFromAnimation(rAnimation);
356 else
357 return nullptr;
358}
359
360Reference<rendering::XAnimatedSprite> SAL_CALL
361 PresenterCanvas::createSpriteFromBitmaps (
362 const css::uno::Sequence<
363 css::uno::Reference< css::rendering::XBitmap > >& rAnimationBitmaps,
364 ::sal_Int8 nInterpolationMode)
365{
366 ThrowIfDisposed();
367
368 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
369 if (xSpriteCanvas.is())
370 return xSpriteCanvas->createSpriteFromBitmaps(rAnimationBitmaps, nInterpolationMode);
371 else
372 return nullptr;
373}
374
375Reference<rendering::XCustomSprite> SAL_CALL
376 PresenterCanvas::createCustomSprite (
377 const css::geometry::RealSize2D& rSpriteSize)
378{
379 ThrowIfDisposed();
380
381 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
382 if (xSpriteCanvas.is())
383 return new PresenterCustomSprite(
384 this,
385 xSpriteCanvas->createCustomSprite(rSpriteSize),
386 mxSharedWindow);
387 else if (mxUpdateCanvas.is())
388 return new PresenterCustomSprite(
389 this,
390 mxUpdateCanvas->createCustomSprite(rSpriteSize),
391 mxUpdateWindow);
392 else
393 return nullptr;
394}
395
396Reference<rendering::XSprite> SAL_CALL
397 PresenterCanvas::createClonedSprite (
398 const css::uno::Reference< css::rendering::XSprite >& rxOriginal)
399{
400 ThrowIfDisposed();
401
402 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
403 if (xSpriteCanvas.is())
404 return xSpriteCanvas->createClonedSprite(rxOriginal);
405 if (mxUpdateCanvas.is())
406 return mxUpdateCanvas->createClonedSprite(rxOriginal);
407 return nullptr;
408}
409
410sal_Bool SAL_CALL PresenterCanvas::updateScreen (sal_Bool bUpdateAll)
411{
412 ThrowIfDisposed();
413
414 mbOffsetUpdatePending = true;
415 if (m_pUpdateRequester != nullptr)
416 {
417 m_pUpdateRequester->RequestUpdate(bUpdateAll);
418 return true;
419 }
420 else
421 {
422 return false;
423 }
424}
425
426//----- XEventListener --------------------------------------------------------
427
428void SAL_CALL PresenterCanvas::disposing (const css::lang::EventObject& rEvent)
429{
430 ThrowIfDisposed();
431 if (rEvent.Source == mxWindow)
432 mxWindow = nullptr;
433}
434
435//----- XWindowListener -------------------------------------------------------
436
437void SAL_CALL PresenterCanvas::windowResized (const css::awt::WindowEvent&)
438{
439 ThrowIfDisposed();
440 mbOffsetUpdatePending = true;
441}
442
443void SAL_CALL PresenterCanvas::windowMoved (const css::awt::WindowEvent&)
444{
445 ThrowIfDisposed();
446 mbOffsetUpdatePending = true;
447}
448
449void SAL_CALL PresenterCanvas::windowShown (const css::lang::EventObject&)
450{
451 ThrowIfDisposed();
452 mbOffsetUpdatePending = true;
453}
454
455void SAL_CALL PresenterCanvas::windowHidden (const css::lang::EventObject&)
456{
457 ThrowIfDisposed();
458}
459
460//----- XBitmap ---------------------------------------------------------------
461
462geometry::IntegerSize2D SAL_CALL PresenterCanvas::getSize()
463{
464 ThrowIfDisposed();
465
466 if (mxWindow.is())
467 {
468 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
469 return geometry::IntegerSize2D(aWindowBox.Width, aWindowBox.Height);
470 }
471 else
472 return geometry::IntegerSize2D(0,0);
473}
474
475sal_Bool SAL_CALL PresenterCanvas::hasAlpha()
476{
477 Reference<rendering::XBitmap> xBitmap (mxSharedCanvas, UNO_QUERY);
478 if (xBitmap.is())
479 return xBitmap->hasAlpha();
480 else
481 return false;
482}
483
484Reference<rendering::XBitmap> SAL_CALL PresenterCanvas::getScaledBitmap(
485 const css::geometry::RealSize2D&,
486 sal_Bool)
487{
488 ThrowIfDisposed();
489
490 // Not implemented.
491
492 return nullptr;
493}
494
495rendering::ViewState PresenterCanvas::MergeViewState (
496 const rendering::ViewState& rViewState)
497{
498 // Make sure the offset is up-to-date.
499 if (mbOffsetUpdatePending)
500 maOffset = GetOffset(mxSharedWindow);
501 return MergeViewState(rViewState, maOffset);
502}
503
504css::rendering::ViewState PresenterCanvas::MergeViewState (
505 const css::rendering::ViewState& rViewState,
506 const css::awt::Point& rOffset)
507{
508 // Early rejects.
509 if ( ! mxSharedCanvas.is())
510 return rViewState;
511
512 Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice());
513 if ( ! xDevice.is())
514 return rViewState;
515
516 // Create a modifiable copy of the given view state.
517 rendering::ViewState aViewState (rViewState);
518
519 // Prepare the local clip rectangle.
520 ::basegfx::B2DRectangle aWindowRange (GetClipRectangle(aViewState.AffineTransform, rOffset));
521
522 // Adapt the offset of the view state.
523 aViewState.AffineTransform.m02 += rOffset.X;
524 aViewState.AffineTransform.m12 += rOffset.Y;
525
526 // Adapt the clip polygon.
527 if ( ! aViewState.Clip.is())
528 {
529 // Cancel out the later multiplication with the view state
530 // transformation.
531 aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
532 xDevice,
533 ::basegfx::B2DPolyPolygon(::basegfx::utils::createPolygonFromRect(aWindowRange)));
534 }
535 else
536 {
537 // Have to compute the intersection of the given clipping polygon in
538 // the view state and the local clip rectangle.
539
540 // Clip the view state clipping polygon against the local clip rectangle.
541 const ::basegfx::B2DPolyPolygon aClipPolygon (
542 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
543 aViewState.Clip));
544 const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
545 ::basegfx::utils::clipPolyPolygonOnRange(
546 aClipPolygon,
547 aWindowRange,
548 true, /* bInside */
549 false /* bStroke */));
550
551 aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
552 xDevice,
553 aClippedClipPolygon);
554 }
555
556 return aViewState;
557}
558
559awt::Point PresenterCanvas::GetOffset (const Reference<awt::XWindow>& rxBaseWindow)
560{
561 mbOffsetUpdatePending = false;
562 if (mxWindow.is() && rxBaseWindow.is())
563 {
565 VclPtr<vcl::Window> pSharedWindow = VCLUnoHelper::GetWindow(rxBaseWindow);
566 if (pWindow && pSharedWindow)
567 {
568 ::tools::Rectangle aBox = pWindow->GetWindowExtentsRelative(*pSharedWindow);
569
570 // Calculate offset of this canvas with respect to the shared
571 // canvas.
572 return awt::Point(aBox.Left(), aBox.Top());
573 }
574 }
575
576 return awt::Point(0, 0);
577}
578
579::basegfx::B2DRectangle PresenterCanvas::GetClipRectangle (
580 const css::geometry::AffineMatrix2D& rViewTransform,
581 const awt::Point& rOffset)
582{
584 if (!pWindow)
585 return ::basegfx::B2DRectangle();
586
587 VclPtr<vcl::Window> pSharedWindow = VCLUnoHelper::GetWindow(mxSharedWindow);
588 if (!pSharedWindow)
589 return ::basegfx::B2DRectangle();
590
591 // Get the bounding box of the window and create a range in the
592 // coordinate system of the child window.
593 // Use the window extents.
594 ::tools::Rectangle aLocalClip = pWindow->GetWindowExtentsRelative(*pSharedWindow);
595
596 // The local clip rectangle is used to clip the view state clipping
597 // polygon.
598 ::basegfx::B2DRectangle aWindowRectangle (
599 aLocalClip.Left() - rOffset.X,
600 aLocalClip.Top() - rOffset.Y,
601 aLocalClip.Right() - rOffset.X + 1,
602 aLocalClip.Bottom() - rOffset.Y + 1);
603
604 // Calculate the inverted view state transformation to cancel out a
605 // later transformation of the local clip polygon with the view state
606 // transformation.
607 ::basegfx::B2DHomMatrix aInvertedViewStateTransformation;
608 ::basegfx::unotools::homMatrixFromAffineMatrix(
609 aInvertedViewStateTransformation,
610 rViewTransform);
611 if (aInvertedViewStateTransformation.invert())
612 {
613 // Cancel out the later multiplication with the view state
614 // transformation.
615 aWindowRectangle.transform(aInvertedViewStateTransformation);
616 }
617
618 return aWindowRectangle;
619}
620
621Reference<rendering::XPolyPolygon2D> PresenterCanvas::UpdateSpriteClip (
622 const Reference<rendering::XPolyPolygon2D>& rxOriginalClip,
623 const geometry::RealPoint2D& rLocation)
624{
625 // Check used resources and just return the original clip when not
626 // every one of them is available.
627 if ( ! mxWindow.is())
628 return rxOriginalClip;
629
630 Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice());
631 if ( ! xDevice.is())
632 return rxOriginalClip;
633
634 // Determine the bounds of the clip rectangle (the window border) in the
635 // coordinate system of the sprite.
636 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
637 const double nMinX (-rLocation.X);
638 const double nMinY (-rLocation.Y);
639 const double nMaxX (aWindowBox.Width-rLocation.X);
640 const double nMaxY (aWindowBox.Height-rLocation.Y);
641
642 // Create a clip polygon.
643 Reference<rendering::XPolyPolygon2D> xPolygon;
644 if (rxOriginalClip.is())
645 {
646 // Combine the original clip with the window clip.
647 const ::basegfx::B2DPolyPolygon aOriginalClip (
648 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rxOriginalClip));
649 ::basegfx::B2DRectangle aWindowRange (nMinX, nMinY, nMaxX, nMaxY);
650 const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
651 ::basegfx::utils::clipPolyPolygonOnRange(
652 aOriginalClip,
653 aWindowRange,
654 true, /* bInside */
655 false /* bStroke */));
656 xPolygon = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
657 xDevice,
658 aClippedClipPolygon);
659 }
660 else
661 {
662 // Create a new clip polygon from the window clip rectangle.
663 Sequence<Sequence<geometry::RealPoint2D> > aPoints
664 {
665 {
666 { nMinX,nMinY },
667 { nMaxX,nMinY },
668 { nMaxX,nMaxY },
669 { nMinX,nMaxY }
670 }
671 };
672 Reference<rendering::XLinePolyPolygon2D> xLinePolygon(
673 xDevice->createCompatibleLinePolyPolygon(aPoints));
674 if (xLinePolygon.is())
675 xLinePolygon->setClosed(0, true);
676 xPolygon = xLinePolygon;
677 }
678
679 return xPolygon;
680}
681
682void PresenterCanvas::ThrowIfDisposed()
683{
684 if (m_bDisposed || ! mxSharedCanvas.is())
685 {
686 throw lang::DisposedException ("PresenterCanvas object has already been disposed",
687 static_cast<uno::XWeak*>(this));
688 }
689}
690
691//===== PresenterCustomSprite =================================================
692
693PresenterCustomSprite::PresenterCustomSprite (
695 const Reference<rendering::XCustomSprite>& rxSprite,
696 const Reference<awt::XWindow>& rxBaseWindow)
697 : mpCanvas(std::move(pCanvas)),
698 mxSprite(rxSprite),
699 mxBaseWindow(rxBaseWindow),
700 maPosition(0,0)
701{
702}
703
704void PresenterCustomSprite::disposing(std::unique_lock<std::mutex>&)
705{
706 Reference<XComponent> xComponent (mxSprite, UNO_QUERY);
707 mxSprite = nullptr;
708 if (xComponent.is())
709 xComponent->dispose();
710 mpCanvas.clear();
711}
712
713//----- XSprite ---------------------------------------------------------------
714
715void SAL_CALL PresenterCustomSprite::setAlpha (const double nAlpha)
716{
717 ThrowIfDisposed();
718 mxSprite->setAlpha(nAlpha);
719}
720
721void SAL_CALL PresenterCustomSprite::move (
722 const geometry::RealPoint2D& rNewPos,
723 const rendering::ViewState& rViewState,
724 const rendering::RenderState& rRenderState)
725{
726 ThrowIfDisposed();
727 maPosition = rNewPos;
728 mxSprite->move(
729 rNewPos,
730 mpCanvas->MergeViewState(rViewState, mpCanvas->GetOffset(mxBaseWindow)),
731 rRenderState);
732 // Clip sprite against window bounds. This call is necessary because
733 // sprite clipping is done in the coordinate system of the sprite.
734 // Therefore, after each change of the sprites location the window
735 // bounds have to be transformed into the sprites coordinate system.
736 clip(nullptr);
737}
738
739void SAL_CALL PresenterCustomSprite::transform (const geometry::AffineMatrix2D& rTransformation)
740{
741 ThrowIfDisposed();
742 mxSprite->transform(rTransformation);
743}
744
745void SAL_CALL PresenterCustomSprite::clip (const Reference<rendering::XPolyPolygon2D>& rxClip)
746{
747 ThrowIfDisposed();
748 // The clip region is expected in the coordinate system of the sprite.
749 // UpdateSpriteClip() integrates the window bounds, transformed into the
750 // sprites coordinate system, with the given clip.
751 mxSprite->clip(mpCanvas->UpdateSpriteClip(rxClip, maPosition));
752}
753
754void SAL_CALL PresenterCustomSprite::setPriority (const double nPriority)
755{
756 ThrowIfDisposed();
757 mxSprite->setPriority(nPriority);
758}
759
760void SAL_CALL PresenterCustomSprite::show()
761{
762 ThrowIfDisposed();
763 mxSprite->show();
764}
765
766void SAL_CALL PresenterCustomSprite::hide()
767{
768 ThrowIfDisposed();
769 mxSprite->hide();
770}
771
772//----- XCustomSprite ---------------------------------------------------------
773
774Reference<rendering::XCanvas> PresenterCustomSprite::getContentCanvas()
775{
776 ThrowIfDisposed();
777 return mxSprite->getContentCanvas();
778}
779
780void PresenterCustomSprite::ThrowIfDisposed()
781{
782 if (m_bDisposed || ! mxSprite.is())
783 {
784 throw lang::DisposedException ("PresenterCustomSprite object has already been disposed",
785 static_cast<uno::XWeak*>(this));
786 }
787}
788
789} // end of namespace ::sd::presenter
790
791/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< rendering::XCustomSprite > mxSprite
rtl::Reference< PresenterCanvas > mpCanvas
geometry::RealPoint2D maPosition
Reference< awt::XWindow > mxBaseWindow
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix &rMatrix)
PresenterCanvas(const css::uno::Reference< css::rendering::XSpriteCanvas > &rxUpdateCanvas, const css::uno::Reference< css::awt::XWindow > &rxUpdateWindow, const css::uno::Reference< css::rendering::XCanvas > &rxSharedCanvas, const css::uno::Reference< css::awt::XWindow > &rxSharedWindow, const css::uno::Reference< css::awt::XWindow > &rxWindow)
This constructor is used when a PresenterCanvas object is created directly, typically by the Presente...
constexpr tools::Long Top() const
constexpr tools::Long Right() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
bool m_bDisposed
unsigned char sal_Bool
signed char sal_Int8