1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_sd.hxx"
25 
26 #include "PresenterCanvas.hxx"
27 
28 #include <basegfx/matrix/b2dhommatrix.hxx>
29 #include <basegfx/polygon/b2dpolygontools.hxx>
30 #include <basegfx/polygon/b2dpolypolygon.hxx>
31 #include <basegfx/polygon/b2dpolygonclipper.hxx>
32 #include <basegfx/range/b2drectangle.hxx>
33 #include <basegfx/tools/canvastools.hxx>
34 #include <canvas/canvastools.hxx>
35 #include <cppuhelper/basemutex.hxx>
36 #include <cppuhelper/compbase1.hxx>
37 #include <rtl/ref.hxx>
38 #include <toolkit/helper/vclunohelper.hxx>
39 #include <vcl/window.hxx>
40 #include <vcl/svapp.hxx>
41 
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::uno;
44 using ::rtl::OUString;
45 
46 namespace sd { namespace presenter {
47 
48 //===== Service ===============================================================
49 
50 Reference<XInterface> SAL_CALL PresenterCanvas_createInstance (
51     const Reference<XComponentContext>& rxContext)
52 {
53     (void)rxContext;
54     return Reference<XInterface>(static_cast<XWeak*>(new PresenterCanvas()));
55 }
56 
57 
58 
59 
60 ::rtl::OUString PresenterCanvas_getImplementationName (void) throw(RuntimeException)
61 {
62     return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterCanvasFactory");
63 }
64 
65 
66 
67 
68 Sequence<rtl::OUString> SAL_CALL PresenterCanvas_getSupportedServiceNames (void)
69     throw (RuntimeException)
70 {
71 	static const ::rtl::OUString sServiceName(
72         ::rtl::OUString::createFromAscii("com.sun.star.rendering.Canvas"));
73 	return Sequence<rtl::OUString>(&sServiceName, 1);
74 }
75 
76 
77 
78 
79 //===== PresenterCustomSprite =================================================
80 
81 /** Wrapper around a sprite that is displayed on a PresenterCanvas.
82 */
83 namespace {
84     typedef ::cppu::WeakComponentImplHelper1 <
85         css::rendering::XCustomSprite
86     > PresenterCustomSpriteInterfaceBase;
87 }
88 class PresenterCustomSprite
89     : private ::boost::noncopyable,
90       protected ::cppu::BaseMutex,
91       public PresenterCustomSpriteInterfaceBase
92 {
93 public:
94     PresenterCustomSprite (
95         const rtl::Reference<PresenterCanvas>& rpCanvas,
96         const Reference<rendering::XCustomSprite>& rxSprite,
97         const Reference<awt::XWindow>& rxBaseWindow,
98         const css::geometry::RealSize2D& rSpriteSize);
99     virtual ~PresenterCustomSprite (void);
100     virtual void SAL_CALL disposing (void)
101         throw (RuntimeException);
102 
103     // XSprite
104 
105     virtual void SAL_CALL setAlpha (double nAlpha)
106         throw (lang::IllegalArgumentException,RuntimeException);
107 
108     virtual void SAL_CALL move (const geometry::RealPoint2D& rNewPos,
109         const rendering::ViewState& rViewState,
110         const rendering::RenderState& rRenderState)
111         throw (lang::IllegalArgumentException,RuntimeException);
112 
113     virtual void SAL_CALL transform (const geometry::AffineMatrix2D& rTransformation)
114         throw (lang::IllegalArgumentException,RuntimeException);
115 
116     virtual void SAL_CALL clip (const Reference<rendering::XPolyPolygon2D>& rClip)
117         throw (RuntimeException);
118 
119     virtual void SAL_CALL setPriority (double nPriority)
120         throw (RuntimeException);
121 
122     virtual void SAL_CALL show (void)
123         throw (RuntimeException);
124 
125     virtual void SAL_CALL hide (void)
126         throw (RuntimeException);
127 
128 
129     // XCustomSprite
130 
131     virtual Reference<rendering::XCanvas> SAL_CALL getContentCanvas (void)
132         throw (RuntimeException);
133 
134 private:
135     rtl::Reference<PresenterCanvas> mpCanvas;
136     Reference<rendering::XCustomSprite> mxSprite;
137     Reference<awt::XWindow> mxBaseWindow;
138     geometry::RealPoint2D maPosition;
139     geometry::RealSize2D maSpriteSize;
140 
141     void ThrowIfDisposed (void)
142         throw (css::lang::DisposedException);
143 };
144 
145 
146 
147 
148 //===== PresenterCanvas =======================================================
149 
150 
151 PresenterCanvas::PresenterCanvas (void)
152     : PresenterCanvasInterfaceBase(m_aMutex),
153       mxUpdateCanvas(),
154       mxSharedCanvas(),
155       mxSharedWindow(),
156       mxWindow(),
157       maOffset(),
158       mpUpdateRequester(),
159       maClipRectangle(),
160       mbOffsetUpdatePending(true)
161 {
162 }
163 
164 
165 
166 
167 PresenterCanvas::PresenterCanvas (
168     const Reference<rendering::XSpriteCanvas>& rxUpdateCanvas,
169     const Reference<awt::XWindow>& rxUpdateWindow,
170     const Reference<rendering::XCanvas>& rxSharedCanvas,
171     const Reference<awt::XWindow>& rxSharedWindow,
172     const Reference<awt::XWindow>& rxWindow)
173     : PresenterCanvasInterfaceBase(m_aMutex),
174       mxUpdateCanvas(rxUpdateCanvas),
175       mxUpdateWindow(rxUpdateWindow),
176       mxSharedCanvas(rxSharedCanvas),
177       mxSharedWindow(rxSharedWindow),
178       mxWindow(rxWindow),
179       maOffset(),
180       mpUpdateRequester(),
181       maClipRectangle(),
182       mbOffsetUpdatePending(true)
183 {
184     if (mxWindow.is())
185         mxWindow->addWindowListener(this);
186 
187     if (mxUpdateCanvas.is())
188         mpUpdateRequester = CanvasUpdateRequester::Instance(mxUpdateCanvas);
189 }
190 
191 
192 
193 
194 PresenterCanvas::~PresenterCanvas (void)
195 {
196 }
197 
198 
199 
200 
201 void SAL_CALL PresenterCanvas::disposing (void)
202     throw (css::uno::RuntimeException)
203 {
204     if (mxWindow.is())
205         mxWindow->removeWindowListener(this);
206 }
207 
208 
209 
210 
211 //----- XInitialization -------------------------------------------------------
212 
213 void SAL_CALL PresenterCanvas::initialize (
214     const Sequence<Any>& rArguments)
215     throw(Exception, RuntimeException)
216 {
217 	if (rBHelper.bDisposed || rBHelper.bInDispose)
218         ThrowIfDisposed();
219 
220     if (rArguments.getLength() == 5)
221     {
222         try
223         {
224             // First and second argument may be NULL.
225             rArguments[0] >>= mxUpdateCanvas;
226             rArguments[1] >>= mxUpdateWindow;
227 
228             if ( ! (rArguments[2] >>= mxSharedWindow))
229             {
230                 throw lang::IllegalArgumentException(
231                     OUString::createFromAscii("PresenterCanvas: invalid shared window"),
232                     static_cast<XWeak*>(this),
233                     1);
234             }
235 
236             if ( ! (rArguments[3] >>= mxSharedCanvas))
237             {
238                 throw lang::IllegalArgumentException(
239                     OUString::createFromAscii("PresenterCanvas: invalid shared canvas"),
240                     static_cast<XWeak*>(this),
241                     2);
242             }
243 
244             if ( ! (rArguments[4] >>= mxWindow))
245             {
246                 throw lang::IllegalArgumentException(
247                     OUString::createFromAscii("PresenterCanvas: invalid window"),
248                     static_cast<XWeak*>(this),
249                     3);
250             }
251 
252             mpUpdateRequester = CanvasUpdateRequester::Instance(mxUpdateCanvas);
253 
254             mbOffsetUpdatePending = true;
255             if (mxWindow.is())
256                 mxWindow->addWindowListener(this);
257         }
258         catch (RuntimeException&)
259         {
260             mxSharedWindow = NULL;
261             mxWindow = NULL;
262             throw;
263         }
264     }
265     else
266     {
267         throw RuntimeException(
268             OUString::createFromAscii("PresenterCanvas: invalid number of arguments"),
269                 static_cast<XWeak*>(this));
270     }
271 }
272 
273 
274 
275 
276 //----- XCanvas ---------------------------------------------------------------
277 
278 void SAL_CALL PresenterCanvas::clear (void)
279     throw (css::uno::RuntimeException)
280 {
281     ThrowIfDisposed();
282     // ToDo: Clear the area covered by the child window.  A simple forward
283     // would clear the whole shared canvas.
284 }
285 
286 
287 
288 
289 void SAL_CALL PresenterCanvas::drawPoint (
290     const css::geometry::RealPoint2D& aPoint,
291     const css::rendering::ViewState& aViewState,
292     const css::rendering::RenderState& aRenderState)
293     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
294 {
295     ThrowIfDisposed();
296     mxSharedCanvas->drawPoint(aPoint,MergeViewState(aViewState),aRenderState);
297 }
298 
299 
300 
301 
302 void SAL_CALL PresenterCanvas::drawLine (
303         const css::geometry::RealPoint2D& aStartPoint,
304         const css::geometry::RealPoint2D& aEndPoint,
305         const css::rendering::ViewState& aViewState,
306         const css::rendering::RenderState& aRenderState)
307         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
308 {
309     ThrowIfDisposed();
310     mxSharedCanvas->drawLine(aStartPoint,aEndPoint,MergeViewState(aViewState),aRenderState);
311 }
312 
313 
314 
315 
316 void SAL_CALL PresenterCanvas::drawBezier (
317         const css::geometry::RealBezierSegment2D& aBezierSegment,
318         const css::geometry::RealPoint2D& aEndPoint,
319         const css::rendering::ViewState& aViewState,
320         const css::rendering::RenderState& aRenderState)
321         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
322 {
323     ThrowIfDisposed();
324     mxSharedCanvas->drawBezier(aBezierSegment,aEndPoint,MergeViewState(aViewState),aRenderState);
325 }
326 
327 
328 
329 
330 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL PresenterCanvas::drawPolyPolygon (
331         const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
332         const css::rendering::ViewState& aViewState,
333         const css::rendering::RenderState& aRenderState)
334         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
335 {
336     ThrowIfDisposed();
337     return mxSharedCanvas->drawPolyPolygon(
338         xPolyPolygon, MergeViewState(aViewState), aRenderState);
339 }
340 
341 
342 
343 
344 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL PresenterCanvas::strokePolyPolygon (
345         const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
346         const css::rendering::ViewState& aViewState,
347         const css::rendering::RenderState& aRenderState,
348         const css::rendering::StrokeAttributes& aStrokeAttributes)
349         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
350 {
351     ThrowIfDisposed();
352     return mxSharedCanvas->strokePolyPolygon(
353         xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes);
354 }
355 
356 
357 
358 
359 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
360         PresenterCanvas::strokeTexturedPolyPolygon (
361             const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
362             const css::rendering::ViewState& aViewState,
363             const css::rendering::RenderState& aRenderState,
364             const css::uno::Sequence< css::rendering::Texture >& aTextures,
365             const css::rendering::StrokeAttributes& aStrokeAttributes)
366         throw (css::lang::IllegalArgumentException,
367             css::rendering::VolatileContentDestroyedException,
368             css::uno::RuntimeException)
369 {
370     ThrowIfDisposed();
371     return mxSharedCanvas->strokeTexturedPolyPolygon(
372         xPolyPolygon, MergeViewState(aViewState), aRenderState, aTextures, aStrokeAttributes);
373 }
374 
375 
376 
377 
378 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
379         PresenterCanvas::strokeTextureMappedPolyPolygon(
380             const css::uno::Reference<css::rendering::XPolyPolygon2D >& xPolyPolygon,
381             const css::rendering::ViewState& aViewState,
382             const css::rendering::RenderState& aRenderState,
383             const css::uno::Sequence<css::rendering::Texture>& aTextures,
384             const css::uno::Reference<css::geometry::XMapping2D>& xMapping,
385             const css::rendering::StrokeAttributes& aStrokeAttributes)
386         throw (css::lang::IllegalArgumentException,
387             css::rendering::VolatileContentDestroyedException,
388             css::uno::RuntimeException)
389 {
390     ThrowIfDisposed();
391     return mxSharedCanvas->strokeTextureMappedPolyPolygon(
392         xPolyPolygon,
393         MergeViewState(aViewState),
394         aRenderState,
395         aTextures,
396         xMapping,
397         aStrokeAttributes);
398 }
399 
400 
401 
402 
403 css::uno::Reference<css::rendering::XPolyPolygon2D> SAL_CALL
404         PresenterCanvas::queryStrokeShapes(
405             const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
406             const css::rendering::ViewState& aViewState,
407             const css::rendering::RenderState& aRenderState,
408             const css::rendering::StrokeAttributes& aStrokeAttributes)
409         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
410 {
411     ThrowIfDisposed();
412     return mxSharedCanvas->queryStrokeShapes(
413         xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes);
414 }
415 
416 
417 
418 
419 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
420         PresenterCanvas::fillPolyPolygon(
421             const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
422             const css::rendering::ViewState& aViewState,
423             const css::rendering::RenderState& aRenderState)
424         throw (css::lang::IllegalArgumentException,
425             css::uno::RuntimeException)
426 {
427     ThrowIfDisposed();
428     return mxSharedCanvas->fillPolyPolygon(
429         xPolyPolygon, MergeViewState(aViewState), aRenderState);
430 }
431 
432 
433 
434 
435 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
436         PresenterCanvas::fillTexturedPolyPolygon(
437             const css::uno::Reference<css::rendering::XPolyPolygon2D>& xPolyPolygon,
438             const css::rendering::ViewState& aViewState,
439             const css::rendering::RenderState& aRenderState,
440             const css::uno::Sequence<css::rendering::Texture>& xTextures)
441         throw (css::lang::IllegalArgumentException,
442             css::rendering::VolatileContentDestroyedException,
443             css::uno::RuntimeException)
444 {
445     ThrowIfDisposed();
446     return mxSharedCanvas->fillTexturedPolyPolygon(
447         xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures);
448 }
449 
450 
451 
452 
453 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
454         PresenterCanvas::fillTextureMappedPolyPolygon(
455             const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon,
456             const css::rendering::ViewState& aViewState,
457             const css::rendering::RenderState& aRenderState,
458             const css::uno::Sequence< css::rendering::Texture >& xTextures,
459             const css::uno::Reference< css::geometry::XMapping2D >& xMapping)
460         throw (css::lang::IllegalArgumentException,
461             css::rendering::VolatileContentDestroyedException,
462             css::uno::RuntimeException)
463 {
464     ThrowIfDisposed();
465     return mxSharedCanvas->fillTextureMappedPolyPolygon(
466         xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures, xMapping);
467 }
468 
469 
470 
471 
472 css::uno::Reference<css::rendering::XCanvasFont> SAL_CALL
473         PresenterCanvas::createFont(
474             const css::rendering::FontRequest& aFontRequest,
475             const css::uno::Sequence< css::beans::PropertyValue >& aExtraFontProperties,
476             const css::geometry::Matrix2D& aFontMatrix)
477         throw (css::lang::IllegalArgumentException,
478             css::uno::RuntimeException)
479 {
480     ThrowIfDisposed();
481     return mxSharedCanvas->createFont(
482         aFontRequest, aExtraFontProperties, aFontMatrix);
483 }
484 
485 
486 
487 
488 css::uno::Sequence<css::rendering::FontInfo> SAL_CALL
489         PresenterCanvas::queryAvailableFonts(
490             const css::rendering::FontInfo& aFilter,
491             const css::uno::Sequence< css::beans::PropertyValue >& aFontProperties)
492         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
493 {
494     ThrowIfDisposed();
495     return mxSharedCanvas->queryAvailableFonts(aFilter, aFontProperties);
496 }
497 
498 
499 
500 
501 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
502         PresenterCanvas::drawText(
503             const css::rendering::StringContext& aText,
504             const css::uno::Reference< css::rendering::XCanvasFont >& xFont,
505             const css::rendering::ViewState& aViewState,
506             const css::rendering::RenderState& aRenderState,
507             ::sal_Int8 nTextDirection)
508         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
509 {
510     ThrowIfDisposed();
511     return mxSharedCanvas->drawText(
512         aText, xFont, MergeViewState(aViewState), aRenderState, nTextDirection);
513 }
514 
515 
516 
517 
518 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
519         PresenterCanvas::drawTextLayout(
520             const css::uno::Reference< css::rendering::XTextLayout >& xLayoutetText,
521             const css::rendering::ViewState& aViewState,
522             const css::rendering::RenderState& aRenderState)
523         throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
524 {
525     ThrowIfDisposed();
526     return mxSharedCanvas->drawTextLayout(
527         xLayoutetText, MergeViewState(aViewState), aRenderState);
528 }
529 
530 
531 
532 
533 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
534         PresenterCanvas::drawBitmap(
535             const css::uno::Reference< css::rendering::XBitmap >& xBitmap,
536             const css::rendering::ViewState& aViewState,
537             const css::rendering::RenderState& aRenderState)
538         throw (css::lang::IllegalArgumentException,
539             css::rendering::VolatileContentDestroyedException,
540             css::uno::RuntimeException)
541 {
542     ThrowIfDisposed();
543     return mxSharedCanvas->drawBitmap(
544         xBitmap, MergeViewState(aViewState), aRenderState);
545 }
546 
547 
548 
549 
550 css::uno::Reference<css::rendering::XCachedPrimitive> SAL_CALL
551         PresenterCanvas::drawBitmapModulated(
552             const css::uno::Reference< css::rendering::XBitmap>& xBitmap,
553             const css::rendering::ViewState& aViewState,
554             const css::rendering::RenderState& aRenderState)
555         throw (css::lang::IllegalArgumentException,
556             css::rendering::VolatileContentDestroyedException,
557             css::uno::RuntimeException)
558 {
559     ThrowIfDisposed();
560     return mxSharedCanvas->drawBitmapModulated(
561         xBitmap, MergeViewState(aViewState), aRenderState);
562 }
563 
564 
565 
566 
567 css::uno::Reference<css::rendering::XGraphicDevice> SAL_CALL
568         PresenterCanvas::getDevice (void)
569         throw (css::uno::RuntimeException)
570 {
571     ThrowIfDisposed();
572     return mxSharedCanvas->getDevice();
573 }
574 
575 
576 
577 
578 //----- XBitmapCanvas ---------------------------------------------------------
579 
580 void SAL_CALL PresenterCanvas::copyRect(
581     const css::uno::Reference<css::rendering::XBitmapCanvas>& rxSourceCanvas,
582     const css::geometry::RealRectangle2D& rSourceRect,
583     const css::rendering::ViewState& rSourceViewState,
584     const css::rendering::RenderState& rSourceRenderState,
585     const css::geometry::RealRectangle2D& rDestRect,
586     const css::rendering::ViewState& rDestViewState,
587     const css::rendering::RenderState& rDestRenderState)
588     throw (css::lang::IllegalArgumentException,
589         css::rendering::VolatileContentDestroyedException,
590         css::uno::RuntimeException)
591 {
592     ThrowIfDisposed();
593 
594     Reference<rendering::XBitmapCanvas> xBitmapCanvas (mxSharedCanvas, UNO_QUERY);
595     if (xBitmapCanvas.is())
596     {
597         rendering::ViewState aSourceViewState (rSourceViewState);
598         if (rxSourceCanvas == Reference<rendering::XCanvas>(this))
599             aSourceViewState = MergeViewState(aSourceViewState);
600         xBitmapCanvas->copyRect(
601             rxSourceCanvas, rSourceRect, aSourceViewState, rSourceRenderState,
602             rDestRect, MergeViewState(rDestViewState), rDestRenderState);
603     }
604 }
605 
606 
607 
608 
609 //----- XSpriteCanvas ---------------------------------------------------------
610 
611 Reference<rendering::XAnimatedSprite> SAL_CALL
612     PresenterCanvas::createSpriteFromAnimation (
613         const css::uno::Reference<css::rendering::XAnimation>& rAnimation)
614     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
615 {
616     ThrowIfDisposed();
617 
618     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
619     if (xSpriteCanvas.is())
620         return xSpriteCanvas->createSpriteFromAnimation(rAnimation);
621     else
622         return NULL;
623 }
624 
625 
626 
627 
628 Reference<rendering::XAnimatedSprite> SAL_CALL
629     PresenterCanvas::createSpriteFromBitmaps (
630         const css::uno::Sequence<
631             css::uno::Reference< css::rendering::XBitmap > >& rAnimationBitmaps,
632     ::sal_Int8 nInterpolationMode)
633         throw (css::lang::IllegalArgumentException,
634             css::rendering::VolatileContentDestroyedException,
635             css::uno::RuntimeException)
636 {
637     ThrowIfDisposed();
638 
639     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
640     if (xSpriteCanvas.is())
641         return xSpriteCanvas->createSpriteFromBitmaps(rAnimationBitmaps, nInterpolationMode);
642     else
643         return NULL;
644 }
645 
646 
647 
648 
649 Reference<rendering::XCustomSprite> SAL_CALL
650     PresenterCanvas::createCustomSprite (
651         const css::geometry::RealSize2D& rSpriteSize)
652     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
653 {
654     ThrowIfDisposed();
655 
656     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
657     if (xSpriteCanvas.is())
658         return new PresenterCustomSprite(
659             this,
660             xSpriteCanvas->createCustomSprite(rSpriteSize),
661             mxSharedWindow,
662             rSpriteSize);
663     else if (mxUpdateCanvas.is())
664         return new PresenterCustomSprite(
665             this,
666             mxUpdateCanvas->createCustomSprite(rSpriteSize),
667             mxUpdateWindow,
668             rSpriteSize);
669     else
670         return NULL;
671 }
672 
673 
674 
675 
676 Reference<rendering::XSprite> SAL_CALL
677     PresenterCanvas::createClonedSprite (
678         const css::uno::Reference< css::rendering::XSprite >& rxOriginal)
679     throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
680 {
681     ThrowIfDisposed();
682 
683     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxSharedCanvas, UNO_QUERY);
684     if (xSpriteCanvas.is())
685         return xSpriteCanvas->createClonedSprite(rxOriginal);
686     if (mxUpdateCanvas.is())
687         return mxUpdateCanvas->createClonedSprite(rxOriginal);
688     return NULL;
689 }
690 
691 
692 
693 
694 ::sal_Bool SAL_CALL PresenterCanvas::updateScreen (::sal_Bool bUpdateAll)
695     throw (css::uno::RuntimeException)
696 {
697     ThrowIfDisposed();
698 
699     mbOffsetUpdatePending = true;
700     if (mpUpdateRequester.get() != NULL)
701     {
702         mpUpdateRequester->RequestUpdate(bUpdateAll);
703         return sal_True;
704     }
705     else
706     {
707         return sal_False;
708     }
709 }
710 
711 
712 
713 
714 //----- XEventListener --------------------------------------------------------
715 
716 void SAL_CALL PresenterCanvas::disposing (const css::lang::EventObject& rEvent)
717     throw (css::uno::RuntimeException)
718 {
719     ThrowIfDisposed();
720     if (rEvent.Source == mxWindow)
721         mxWindow = NULL;
722 }
723 
724 
725 
726 
727 //----- XWindowListener -------------------------------------------------------
728 
729 void SAL_CALL PresenterCanvas::windowResized (const css::awt::WindowEvent& rEvent)
730         throw (css::uno::RuntimeException)
731 {
732     (void)rEvent;
733     ThrowIfDisposed();
734     mbOffsetUpdatePending = true;
735 }
736 
737 
738 
739 
740 void SAL_CALL PresenterCanvas::windowMoved (const css::awt::WindowEvent& rEvent)
741     throw (css::uno::RuntimeException)
742 {
743     (void)rEvent;
744     ThrowIfDisposed();
745     mbOffsetUpdatePending = true;
746 }
747 
748 
749 
750 
751 void SAL_CALL PresenterCanvas::windowShown (const css::lang::EventObject& rEvent)
752     throw (css::uno::RuntimeException)
753 {
754     (void)rEvent;
755     ThrowIfDisposed();
756     mbOffsetUpdatePending = true;
757 }
758 
759 
760 
761 
762 void SAL_CALL PresenterCanvas::windowHidden (const css::lang::EventObject& rEvent)
763     throw (css::uno::RuntimeException)
764 {
765     (void)rEvent;
766     ThrowIfDisposed();
767 }
768 
769 
770 
771 
772 //----- XBitmap ---------------------------------------------------------------
773 
774 geometry::IntegerSize2D SAL_CALL PresenterCanvas::getSize (void)
775     throw (RuntimeException)
776 {
777     ThrowIfDisposed();
778 
779     if (mxWindow.is())
780     {
781         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
782         return geometry::IntegerSize2D(aWindowBox.Width, aWindowBox.Height);
783     }
784     else
785         return geometry::IntegerSize2D(0,0);
786 }
787 
788 
789 
790 
791 sal_Bool SAL_CALL PresenterCanvas::hasAlpha (void)
792     throw (RuntimeException)
793 {
794     Reference<rendering::XBitmap> xBitmap (mxSharedCanvas, UNO_QUERY);
795     if (xBitmap.is())
796         return xBitmap->hasAlpha();
797     else
798         return sal_False;
799 }
800 
801 
802 
803 
804 Reference<rendering::XBitmapCanvas> SAL_CALL PresenterCanvas::queryBitmapCanvas (void)
805     throw (RuntimeException)
806 {
807     ThrowIfDisposed();
808 
809     return this;
810 }
811 
812 
813 
814 
815 Reference<rendering::XBitmap> SAL_CALL PresenterCanvas::getScaledBitmap(
816     const css::geometry::RealSize2D& rNewSize,
817     sal_Bool bFast)
818     throw (css::uno::RuntimeException,
819         css::lang::IllegalArgumentException,
820         css::rendering::VolatileContentDestroyedException)
821 {
822     (void)rNewSize;
823     (void)bFast;
824 
825     ThrowIfDisposed();
826 
827     // Not implemented.
828 
829     return NULL;
830 }
831 
832 
833 
834 
835 //-----------------------------------------------------------------------------
836 
837 rendering::ViewState PresenterCanvas::MergeViewState (
838     const rendering::ViewState& rViewState)
839 {
840     // Make sure the offset is up-to-date.
841     if (mbOffsetUpdatePending)
842         maOffset = GetOffset(mxSharedWindow);
843     return MergeViewState(rViewState, maOffset);
844 }
845 
846 
847 
848 
849 css::rendering::ViewState PresenterCanvas::MergeViewState (
850     const css::rendering::ViewState& rViewState,
851     const css::awt::Point& rOffset)
852 {
853     // Early rejects.
854     if ( ! mxSharedCanvas.is())
855         return rViewState;
856 
857     Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice());
858     if ( ! xDevice.is())
859         return rViewState;
860 
861     // Create a modifiable copy of the given view state.
862     rendering::ViewState aViewState (rViewState);
863 
864     // Prepare the local clip rectangle.
865     ::basegfx::B2DRectangle aWindowRange (GetClipRectangle(aViewState.AffineTransform, rOffset));
866 
867     // Adapt the offset of the view state.
868     aViewState.AffineTransform.m02 += rOffset.X;
869     aViewState.AffineTransform.m12 += rOffset.Y;
870 
871     // Adapt the clip polygon.
872     if ( ! aViewState.Clip.is())
873     {
874         // Cancel out the later multiplication with the view state
875         // transformation.
876         aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
877             xDevice,
878             ::basegfx::B2DPolyPolygon(::basegfx::tools::createPolygonFromRect(aWindowRange)));
879     }
880     else
881     {
882         // Have to compute the intersection of the given clipping polygon in
883         // the view state and the local clip rectangle.
884 
885         // Clip the view state clipping polygon against the local clip rectangle.
886         const ::basegfx::B2DPolyPolygon aClipPolygon (
887             ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
888                 aViewState.Clip));
889         const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
890             ::basegfx::tools::clipPolyPolygonOnRange(
891                 aClipPolygon,
892                 aWindowRange,
893                 true, /* bInside */
894                 false /* bStroke */));
895 
896         aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
897             xDevice,
898             aClippedClipPolygon);
899     }
900 
901     return aViewState;
902 }
903 
904 
905 
906 
907 awt::Point PresenterCanvas::GetOffset (const Reference<awt::XWindow>& rxBaseWindow)
908 {
909     mbOffsetUpdatePending = false;
910     if (mxWindow.is() && rxBaseWindow.is())
911     {
912         ::Window* pWindow = VCLUnoHelper::GetWindow(mxWindow);
913         ::Window* pSharedWindow = VCLUnoHelper::GetWindow(rxBaseWindow);
914         if (pWindow!=NULL && pSharedWindow!=NULL)
915         {
916             Rectangle aBox = pWindow->GetWindowExtentsRelative(pSharedWindow);
917 
918             // Calculate offset of this canvas with respect to the shared
919             // canvas.
920             return awt::Point(aBox.Left(), aBox.Top());
921         }
922     }
923 
924     return awt::Point(0, 0);
925 }
926 
927 
928 
929 
930 ::basegfx::B2DRectangle PresenterCanvas::GetClipRectangle (
931     const css::geometry::AffineMatrix2D& rViewTransform,
932     const awt::Point& rOffset)
933 {
934     ::basegfx::B2DRectangle aClipRectangle;
935 
936     ::Window* pWindow = VCLUnoHelper::GetWindow(mxWindow);
937     if (pWindow == NULL)
938         return ::basegfx::B2DRectangle();
939 
940     ::Window* pSharedWindow = VCLUnoHelper::GetWindow(mxSharedWindow);
941     if (pSharedWindow == NULL)
942         return ::basegfx::B2DRectangle();
943 
944     // Get the bounding box of the window and create a range in the
945     // coordinate system of the child window.
946     Rectangle aLocalClip;
947     if (maClipRectangle.Width <= 0 || maClipRectangle.Height <= 0)
948     {
949         // No clip rectangle has been set via SetClip by the pane.
950         // Use the window extents instead.
951         aLocalClip = pWindow->GetWindowExtentsRelative(pSharedWindow);
952     }
953     else
954     {
955         // Use a previously given clip rectangle.
956         aLocalClip = Rectangle(
957             maClipRectangle.X + rOffset.X,
958             maClipRectangle.Y + rOffset.Y,
959             maClipRectangle.X + maClipRectangle.Width + rOffset.X,
960             maClipRectangle.Y + maClipRectangle.Height + rOffset.Y);
961     }
962 
963     // The local clip rectangle is used to clip the view state clipping
964     // polygon.
965     ::basegfx::B2DRectangle aWindowRectangle (
966         aLocalClip.Left() - rOffset.X,
967         aLocalClip.Top() - rOffset.Y,
968         aLocalClip.Right() - rOffset.X + 1,
969         aLocalClip.Bottom() - rOffset.Y + 1);
970 
971     // Calculate the inverted view state transformation to cancel out a
972     // later transformation of the local clip polygon with the view state
973     // transformation.
974     ::basegfx::B2DHomMatrix aInvertedViewStateTransformation;
975     ::basegfx::unotools::homMatrixFromAffineMatrix(
976         aInvertedViewStateTransformation,
977         rViewTransform);
978     if (aInvertedViewStateTransformation.invert())
979     {
980         // Cancel out the later multiplication with the view state
981         // transformation.
982         aWindowRectangle.transform(aInvertedViewStateTransformation);
983     }
984 
985     return aWindowRectangle;
986 }
987 
988 
989 
990 Reference<rendering::XPolyPolygon2D> PresenterCanvas::UpdateSpriteClip (
991     const Reference<rendering::XPolyPolygon2D>& rxOriginalClip,
992     const geometry::RealPoint2D& rLocation,
993     const geometry::RealSize2D& rSize)
994 {
995     (void)rSize;
996 
997     // Check used resources and just return the original clip when not
998     // every one of them is available.
999     if ( ! mxWindow.is())
1000         return rxOriginalClip;
1001 
1002     Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice());
1003     if ( ! xDevice.is())
1004         return rxOriginalClip;
1005 
1006     // Determine the bounds of the clip rectangle (the window border) in the
1007     // coordinate system of the sprite.
1008     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
1009     const double nMinX (-rLocation.X);
1010     const double nMinY (-rLocation.Y);
1011     const double nMaxX (aWindowBox.Width-rLocation.X);
1012     const double nMaxY (aWindowBox.Height-rLocation.Y);
1013 
1014     // Create a clip polygon.
1015     Reference<rendering::XPolyPolygon2D> xPolygon;
1016     if (rxOriginalClip.is())
1017     {
1018         // Combine the original clip with the window clip.
1019         const ::basegfx::B2DPolyPolygon aOriginalClip (
1020             ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rxOriginalClip));
1021         ::basegfx::B2DRectangle aWindowRange (nMinX, nMinY, nMaxX, nMaxY);
1022         const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
1023             ::basegfx::tools::clipPolyPolygonOnRange(
1024                 aOriginalClip,
1025                 aWindowRange,
1026                 true, /* bInside */
1027                 false /* bStroke */));
1028         xPolygon = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1029             xDevice,
1030             aClippedClipPolygon);
1031     }
1032     else
1033     {
1034         // Create a new clip polygon from the window clip rectangle.
1035         Sequence<Sequence<geometry::RealPoint2D> > aPoints (1);
1036         aPoints[0] = Sequence<geometry::RealPoint2D>(4);
1037         aPoints[0][0] = geometry::RealPoint2D(nMinX,nMinY);
1038         aPoints[0][1] = geometry::RealPoint2D(nMaxX,nMinY);
1039         aPoints[0][2] = geometry::RealPoint2D(nMaxX,nMaxY);
1040         aPoints[0][3] = geometry::RealPoint2D(nMinX,nMaxY);
1041         Reference<rendering::XLinePolyPolygon2D> xLinePolygon(
1042             xDevice->createCompatibleLinePolyPolygon(aPoints));
1043         if (xLinePolygon.is())
1044             xLinePolygon->setClosed(0, sal_True);
1045         xPolygon = Reference<rendering::XPolyPolygon2D>(xLinePolygon, UNO_QUERY);
1046     }
1047 
1048     return xPolygon;
1049 }
1050 
1051 
1052 
1053 
1054 void PresenterCanvas::ThrowIfDisposed (void)
1055     throw (css::lang::DisposedException)
1056 {
1057 	if (rBHelper.bDisposed || rBHelper.bInDispose || ! mxSharedCanvas.is())
1058 	{
1059         throw lang::DisposedException (
1060             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1061                 "PresenterCanvas object has already been disposed")),
1062             static_cast<uno::XWeak*>(this));
1063     }
1064 }
1065 
1066 
1067 
1068 
1069 //===== PresenterCustomSprite =================================================
1070 
1071 
1072 PresenterCustomSprite::PresenterCustomSprite (
1073     const rtl::Reference<PresenterCanvas>& rpCanvas,
1074     const Reference<rendering::XCustomSprite>& rxSprite,
1075     const Reference<awt::XWindow>& rxBaseWindow,
1076     const css::geometry::RealSize2D& rSpriteSize)
1077     : PresenterCustomSpriteInterfaceBase(m_aMutex),
1078       mpCanvas(rpCanvas),
1079       mxSprite(rxSprite),
1080       mxBaseWindow(rxBaseWindow),
1081       maPosition(0,0),
1082       maSpriteSize(rSpriteSize)
1083 {
1084 }
1085 
1086 
1087 
1088 
1089 PresenterCustomSprite::~PresenterCustomSprite (void)
1090 {
1091 }
1092 
1093 
1094 
1095 
1096 void SAL_CALL PresenterCustomSprite::disposing (void)
1097     throw (RuntimeException)
1098 {
1099     Reference<XComponent> xComponent (mxSprite, UNO_QUERY);
1100     mxSprite = NULL;
1101     if (xComponent.is())
1102         xComponent->dispose();
1103     mpCanvas = rtl::Reference<PresenterCanvas>();
1104 }
1105 
1106 
1107 
1108 
1109 //----- XSprite ---------------------------------------------------------------
1110 
1111 void SAL_CALL PresenterCustomSprite::setAlpha (const double nAlpha)
1112     throw (lang::IllegalArgumentException,RuntimeException)
1113 {
1114     ThrowIfDisposed();
1115     mxSprite->setAlpha(nAlpha);
1116 }
1117 
1118 
1119 
1120 
1121 void SAL_CALL PresenterCustomSprite::move (
1122     const geometry::RealPoint2D& rNewPos,
1123     const rendering::ViewState& rViewState,
1124     const rendering::RenderState& rRenderState)
1125     throw (lang::IllegalArgumentException,RuntimeException)
1126 {
1127     ThrowIfDisposed();
1128     maPosition = rNewPos;
1129     mxSprite->move(
1130         rNewPos,
1131         mpCanvas->MergeViewState(rViewState, mpCanvas->GetOffset(mxBaseWindow)),
1132         rRenderState);
1133     // Clip sprite against window bounds.  This call is necessary because
1134     // sprite clipping is done in the corrdinate system of the sprite.
1135     // Therefore, after each change of the sprites location the window
1136     // bounds have to be transformed into the sprites coordinate system.
1137     clip(NULL);
1138 }
1139 
1140 
1141 
1142 
1143 void SAL_CALL PresenterCustomSprite::transform (const geometry::AffineMatrix2D& rTransformation)
1144     throw (lang::IllegalArgumentException,RuntimeException)
1145 {
1146     ThrowIfDisposed();
1147     mxSprite->transform(rTransformation);
1148 }
1149 
1150 
1151 
1152 
1153 void SAL_CALL PresenterCustomSprite::clip (const Reference<rendering::XPolyPolygon2D>& rxClip)
1154     throw (RuntimeException)
1155 {
1156     ThrowIfDisposed();
1157     // The clip region is expected in the coordinate system of the sprite.
1158     // UpdateSpriteClip() integrates the window bounds, transformed into the
1159     // sprites coordinate system, with the given clip.
1160     mxSprite->clip(mpCanvas->UpdateSpriteClip(rxClip, maPosition, maSpriteSize));
1161 }
1162 
1163 
1164 
1165 
1166 void SAL_CALL PresenterCustomSprite::setPriority (const double nPriority)
1167     throw (RuntimeException)
1168 {
1169     ThrowIfDisposed();
1170     mxSprite->setPriority(nPriority);
1171 }
1172 
1173 
1174 
1175 void SAL_CALL PresenterCustomSprite::show (void)
1176     throw (RuntimeException)
1177 {
1178     ThrowIfDisposed();
1179     mxSprite->show();
1180 }
1181 
1182 
1183 
1184 
1185 void SAL_CALL PresenterCustomSprite::hide (void)
1186     throw (RuntimeException)
1187 {
1188     ThrowIfDisposed();
1189     mxSprite->hide();
1190 }
1191 
1192 
1193 
1194 
1195 //----- XCustomSprite ---------------------------------------------------------
1196 
1197 Reference<rendering::XCanvas> PresenterCustomSprite::getContentCanvas (void)
1198     throw (RuntimeException)
1199 {
1200     ThrowIfDisposed();
1201     return mxSprite->getContentCanvas();
1202 }
1203 
1204 
1205 
1206 
1207 //-----------------------------------------------------------------------------
1208 
1209 void PresenterCustomSprite::ThrowIfDisposed (void)
1210     throw (css::lang::DisposedException)
1211 {
1212 	if (rBHelper.bDisposed || rBHelper.bInDispose || ! mxSprite.is())
1213 	{
1214         throw lang::DisposedException (
1215             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1216                 "PresenterCustomSprite object has already been disposed")),
1217             static_cast<uno::XWeak*>(this));
1218     }
1219 }
1220 
1221 
1222 
1223 
1224 } } // end of namespace ::sd::presenter
1225