Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/slideshow/source/engine/slide/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 18 kB image not shown  

Quelle  userpaintoverlay.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */



#include <com/sun/star/awt/MouseButton.hpp>
#include <com/sun/star/awt/MouseEvent.hpp>

#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <cppcanvas/basegfxfactory.hxx>
#include <comphelper/diagnose_ex.hxx>

#include <slideshowcontext.hxx>
#include "userpaintoverlay.hxx"
#include <mouseeventhandler.hxx>
#include <eventmultiplexer.hxx>
#include <screenupdater.hxx>
#include <vieweventhandler.hxx>

#include <slide.hxx>
#include <cursormanager.hxx>

using namespace ::com::sun::star;

namespace slideshow::internal
{
        class PaintOverlayHandler : public MouseEventHandler,
                                    public ViewEventHandler,
                    public UserPaintEventHandler
        {
        public:
            PaintOverlayHandler( const RGBColor&          rStrokeColor,
                                 double                   nStrokeWidth,
                                 ScreenUpdater&           rScreenUpdater,
                                 const UnoViewContainer&  rViews,
                                 Slide&                   rSlide,
                                 PolyPolygonVector&&      rPolygons,
                                 bool                     bActive ) :
                mrScreenUpdater( rScreenUpdater ),
                maViews(),
                maPolygons( std::move(rPolygons) ),
                maStrokeColor( rStrokeColor ),
                mnStrokeWidth( nStrokeWidth ),
                maLastPoint(),
                maLastMouseDownPos(),
                mbIsLastPointValid( false ),
                mbIsLastMouseDownPosValid( false ),
                //handle the "remove all ink from slide" mode of erasing
                mbIsEraseAllModeActivated( false ),
                //handle the "remove stroke by stroke" mode of erasing
                mbIsEraseModeActivated( false ),
                mrSlide(rSlide),
                mnSize(100),
                mbActive( bActive )
            {
                forconst auto& rView : rViews )
                    viewAdded( rView );

                drawPolygons();
            }

            void dispose()
            {
                maViews.clear();
            }

            // ViewEventHandler methods
            virtual void viewAdded( const UnoViewSharedPtr& rView ) override
            {
                maViews.push_back( rView );
            }

            virtual void viewRemoved( const UnoViewSharedPtr& rView ) override
            {
                std::erase(maViews, rView);
            }

            virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ ) override
            {
                // TODO(F2): for persistent drawings, need to store
                // polygon and repaint here.
            }

            virtual void viewsChanged() override
            {
                // TODO(F2): for persistent drawings, need to store
                // polygon and repaint here.
            }

            bool colorChanged( RGBColor const& rUserColor ) override
            {
                mbIsLastPointValid = false;
                mbActive = true;
                maStrokeColor = rUserColor;
                mbIsEraseModeActivated = false;
                return true;
            }

            bool widthChanged( double nUserStrokeWidth ) override
            {
                mnStrokeWidth = nUserStrokeWidth;
                mbIsEraseModeActivated = false;
                return true;
            }

            void repaintWithoutPolygons()
            {
                    // must get access to the instance to erase all polygon
                    forconst auto& rxView : maViews )
                    {
                        // fully clear view content to background color
                        //rxView->getCanvas()->clear();

                        //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
                        SlideBitmapSharedPtr         pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
                        ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );

                        const ::basegfx::B2DHomMatrix   aViewTransform( rxView->getTransformation() );
                        const ::basegfx::B2DPoint       aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );

                        // setup a canvas with device coordinate space, the slide
                        // bitmap already has the correct dimension.
                        ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );

                        pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );

                        // render at given output position
                        pBitmap->move( aOutPosPixel );

                        // clear clip (might have been changed, e.g. from comb
                        // transition)
                        pBitmap->clip( ::basegfx::B2DPolyPolygon() );
                        pBitmap->draw( pDevicePixelCanvas );

                        mrScreenUpdater.notifyUpdate(rxView,true);
                    }
            }

            bool eraseAllInkChanged( bool bEraseAllInk ) override
            {
                mbIsEraseAllModeActivated = bEraseAllInk;
                // if the erase all mode is activated it will remove all ink from slide,
                // therefore destroy all the polygons stored
                if(mbIsEraseAllModeActivated)
                {
                    // The Erase Mode should be deactivated
                    mbIsEraseModeActivated = false;
                    repaintWithoutPolygons();
                    maPolygons.clear();
                }
                mbIsEraseAllModeActivated=false;
                return true;
            }

            bool eraseInkWidthChanged( sal_Int32 rEraseInkSize ) override
            {
                // Change the size
                mnSize=rEraseInkSize;
                // Changed to mode Erase
                mbIsEraseModeActivated = true;
                return true;
            }

            bool switchPenMode() override
            {
                mbIsLastPointValid = false;
                mbActive = true;
                mbIsEraseModeActivated = false;
                return true;
            }

            bool switchEraserMode() override
            {
                mbIsLastPointValid = false;
                mbActive = true;
                mbIsEraseModeActivated = true;
                return true;
            }

            bool disable() override
            {
                mbIsLastPointValid = false;
                mbIsLastMouseDownPosValid = false;
                mbActive = false;
                return true;
            }

            //Draw all registered polygons.
            void drawPolygons()
            {
                forconst auto& rxPolygon : maPolygons )
                {
                    rxPolygon->draw();
                }
                // screen update necessary to show painting
                mrScreenUpdater.notifyUpdate();
            }

            //Retrieve all registered polygons.
            const PolyPolygonVector& getPolygons() const
            {
                return maPolygons;
            }

            // MouseEventHandler methods
            virtual bool handleMousePressed( const awt::MouseEvent& e ) override
            {
                if( !mbActive )
                    return false;

                if (e.Buttons == awt::MouseButton::RIGHT)
                {
                    mbIsLastPointValid = false;
                    return false;
                }

                if (e.Buttons != awt::MouseButton::LEFT)
                    return false;

                maLastMouseDownPos.setX( e.X );
                maLastMouseDownPos.setY( e.Y );
                mbIsLastMouseDownPosValid = true;

                // eat mouse click (though we don't process it
                // _directly_, it enables the drag mode
                return true;
            }

            virtual bool handleMouseReleased( const awt::MouseEvent& e ) override
            {
                if( !mbActive )
                    return false;

                if (e.Buttons == awt::MouseButton::RIGHT)
                {
                    mbIsLastPointValid = false;
                    return false;
                }

                if (e.Buttons != awt::MouseButton::LEFT)
                    return false;

                // check, whether up- and down press are on exactly
                // the same pixel. If that's the case, ignore the
                // click, and pass on the event to low-prio
                // handlers. This effectively permits effect
                // advancements via clicks also when user paint is
                // enabled.
                if( mbIsLastMouseDownPosValid &&
                    ::basegfx::B2DPoint( e.X,
                                         e.Y ) == maLastMouseDownPos )
                {
                    mbIsLastMouseDownPosValid = false;
                    return false;
                }

                // invalidate, next downpress will have to start a new
                // polygon.
                mbIsLastPointValid = false;

                // eat mouse click (though we don't process it
                // _directly_, it enables the drag mode
                return true;
            }

            virtual bool handleMouseDragged( const awt::MouseEvent& e ) override
            {
                if( !mbActive )
                    return false;

                if (e.Buttons == awt::MouseButton::RIGHT)
                {
                    mbIsLastPointValid = false;
                    return false;
                }

                if(mbIsEraseModeActivated)
                {
                    //define the last point as an object
                    //we suppose that there's no way this point could be valid
                    ::basegfx::B2DPolygon aPoly;

                    maLastPoint.setX( e.X-mnSize );
                    maLastPoint.setY( e.Y-mnSize );

                    aPoly.append( maLastPoint );

                    maLastPoint.setX( e.X-mnSize );
                    maLastPoint.setY( e.Y+mnSize );

                    aPoly.append( maLastPoint );
                    maLastPoint.setX( e.X+mnSize );
                    maLastPoint.setY( e.Y+mnSize );

                    aPoly.append( maLastPoint );
                    maLastPoint.setX( e.X+mnSize );
                    maLastPoint.setY( e.Y-mnSize );

                    aPoly.append( maLastPoint );
                    maLastPoint.setX( e.X-mnSize );
                    maLastPoint.setY( e.Y-mnSize );

                    aPoly.append( maLastPoint );

                    //now we have defined a Polygon that is closed

                    //The point is to redraw the LastPoint the way it was originally on the bitmap,
                    //of the slide
                    for (const auto& rxView : maViews)
                    {

                        //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
                        SlideBitmapSharedPtr         pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
                        ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );

                        ::basegfx::B2DHomMatrix     aViewTransform( rxView->getTransformation() );
                        const ::basegfx::B2DPoint       aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );

                        // setup a canvas with device coordinate space, the slide
                        // bitmap already has the correct dimension.
                        ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );

                        pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );

                        // render at given output position
                        pBitmap->move( aOutPosPixel );

                        ::basegfx::B2DPolyPolygon aPolyPoly(aPoly);
                        aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
                        aPolyPoly.transform(aViewTransform);
                        // set clip so that we just redraw a part of the canvas
                        pBitmap->clip(aPolyPoly);
                        pBitmap->draw( pDevicePixelCanvas );

                        mrScreenUpdater.notifyUpdate(rxView,true);
                    }

                }
                else
                {
                    if( !mbIsLastPointValid )
                    {
                        mbIsLastPointValid = true;
                        maLastPoint.setX( e.X );
                        maLastPoint.setY( e.Y );
                    }
                    else
                    {
                        ::basegfx::B2DPolygon aPoly;
                        aPoly.append( maLastPoint );

                        maLastPoint.setX( e.X );
                        maLastPoint.setY( e.Y );

                        aPoly.append( maLastPoint );

                        // paint to all views
                        for (const auto& rxView : maViews)
                        {
                            ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
                                ::cppcanvas::BaseGfxFactory::createPolyPolygon( rxView->getCanvas(),
                                                                                aPoly ) );

                            if( pPolyPoly )
                            {
                                pPolyPoly->setStrokeWidth(mnStrokeWidth);
                                pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
                                pPolyPoly->draw();
                                maPolygons.push_back(pPolyPoly);
                            }
                        }

                        // screen update necessary to show painting
                        mrScreenUpdater.notifyUpdate();
                    }
                }
                // mouse events captured
                return true;
            }

            virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ ) override
            {
                // not used here
                return false// did not handle the event
            }

        private:
            ScreenUpdater&          mrScreenUpdater;
            UnoViewVector           maViews;
            PolyPolygonVector       maPolygons;
            RGBColor                maStrokeColor;
            double                  mnStrokeWidth;
            basegfx::B2DPoint       maLastPoint;
            basegfx::B2DPoint       maLastMouseDownPos;
            bool                    mbIsLastPointValid;
            bool                    mbIsLastMouseDownPosValid;
            // added bool for erasing purpose :
            bool                    mbIsEraseAllModeActivated;
            bool                    mbIsEraseModeActivated;
            Slide&                  mrSlide;
            sal_Int32               mnSize;
            bool                    mbActive;
        };

        UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor&          rStrokeColor,
                                                            double                   nStrokeWidth,
                                                            const SlideShowContext&  rContext,
                                                            PolyPolygonVector&&      rPolygons,
                                                            bool                     bActive )
        {
            UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
                                                                  nStrokeWidth,
                                                                  rContext,
                                                                  std::move(rPolygons),
                                                                  bActive));

            return pRet;
        }

        UserPaintOverlay::UserPaintOverlay( const RGBColor&          rStrokeColor,
                                            double                   nStrokeWidth,
                                            const SlideShowContext&  rContext,
                                            PolyPolygonVector&&      rPolygons,
                                            bool                     bActive ) :
            mpHandler( std::make_shared<PaintOverlayHandler>( rStrokeColor,
                                                nStrokeWidth,
                                                rContext.mrScreenUpdater,
                                                rContext.mrViewContainer,
                                                //adding a link to Slide
                                                dynamic_cast<Slide&>(rContext.mrCursorManager),
                                                std::move(rPolygons), bActive )),
            mrMultiplexer( rContext.mrEventMultiplexer )
        {
            mrMultiplexer.addClickHandler( mpHandler, 3.0 );
            mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
            mrMultiplexer.addViewHandler( mpHandler );
            mrMultiplexer.addUserPaintHandler(mpHandler);
        }

        PolyPolygonVector const & UserPaintOverlay::getPolygons() const
        {
            return mpHandler->getPolygons();
        }

        void UserPaintOverlay::drawPolygons()
        {
            mpHandler->drawPolygons();
        }

        UserPaintOverlay::~UserPaintOverlay()
        {
            try
            {
                mrMultiplexer.removeMouseMoveHandler( mpHandler );
                mrMultiplexer.removeClickHandler( mpHandler );
                mrMultiplexer.removeViewHandler( mpHandler );
                mpHandler->dispose();
            }
            catch (const uno::Exception&)
            {
                TOOLS_WARN_EXCEPTION("slideshow""");
            }
        }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.