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

Quelle  svdhdl.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 <algorithm>
#include <cassert>

#include <svx/svdhdl.hxx>
#include <svx/svdpagv.hxx>
#include <svx/svdmrkv.hxx>
#include <utility>
#include <vcl/settings.hxx>
#include <vcl/virdev.hxx>
#include <vcl/ptrstyle.hxx>

#include <svx/sxekitm.hxx>
#include <svx/strings.hrc>
#include <svx/svdmodel.hxx>
#include "gradtrns.hxx"
#include <svx/xflgrit.hxx>
#include <svx/svdundo.hxx>
#include <svx/dialmgr.hxx>
#include <svx/xflftrit.hxx>

#include <svx/svdopath.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
#include <svx/sdr/overlay/overlaybitmapex.hxx>
#include <sdr/overlay/overlayline.hxx>
#include <sdr/overlay/overlaytriangle.hxx>
#include <sdr/overlay/overlayhandle.hxx>
#include <sdr/overlay/overlayrectangle.hxx>
#include <svx/sdrpagewindow.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <vcl/svapp.hxx>
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
#include <tools/lazydelete.hxx>
#include <vcl/BitmapTools.hxx>
#include <svx/sdr/contact/objectcontact.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
#include <osl/diagnose.h>

#include <basegfx/polygon/b2dpolygontools.hxx>
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <svtools/optionsdrawinglayer.hxx>
#include <memory>
#include <bitmaps.hlst>

namespace {

// #i15222#
// Due to the resource problems in Win95/98 with bitmap resources I
// will change this handle bitmap providing class. Old version was splitting
// and preparing all small handle bitmaps in device bitmap format, now this will
// be done on the fly. Thus, there is only one big bitmap in memory. With
// three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
// The price for that needs to be evaluated. Maybe we will need another change here
// if this is too expensive.
class SdrHdlBitmapSet
{
    // the bitmap holding all information
    BitmapEx                    maMarkersBitmap;

    // the cropped Bitmaps for reusage
    ::std::vector< BitmapEx >   maRealMarkers;

    // helpers
    BitmapEx& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle&&nbsp;rRectangle);

public:
    explicit SdrHdlBitmapSet();

    const BitmapEx& GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd);
};

}

#define KIND_COUNT          (14)
#define INDEX_COUNT         (6)
#define INDIVIDUAL_COUNT    (5)

SdrHdlBitmapSet::SdrHdlBitmapSet()
    :   maMarkersBitmap(SIP_SA_MARKERS),
        // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
        maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT)
{
}

BitmapEx& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle)
{
    BitmapEx& rTargetBitmap = maRealMarkers[nIndex];

    if(rTargetBitmap.IsEmpty())
    {
        rTargetBitmap = maMarkersBitmap;
        rTargetBitmap.Crop(rRectangle);
    }

    return rTargetBitmap;
}

// change getting of bitmap to use the big resource bitmap
const BitmapEx& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd)
{
    // fill in size and source position in maMarkersBitmap
    const sal_uInt16 nYPos(nInd * 11);

    switch(eKindOfMarker)
    {
        default:
        {
            OSL_FAIL( "Unknown kind of marker." );
            [[fallthrough]]; // return Rect_9x9 as default
        }
        case BitmapMarkerKind::Rect_9x9:
        {
            return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, tools::Rectangle(Point(7, nYPos), Size(9, 9)));
        }

        case BitmapMarkerKind::Rect_7x7:
        {
            return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, tools::Rectangle(Point(0, nYPos), Size(7, 7)));
        }

        case BitmapMarkerKind::Rect_11x11:
        {
            return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, tools::Rectangle(Point(16, nYPos), Size(11, 11)));
        }

        case BitmapMarkerKind::Rect_13x13:
        {
            const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd);

            switch(nInd)
            {
                case 0:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 66), Size(13, 13)));
                }
                case 1:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 66), Size(13, 13)));
                }
                case 2:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 79), Size(13, 13)));
                }
                case 3:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 79), Size(13, 13)));
                }
                case 4:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 79), Size(13, 13)));
                }
                default// case 5:
                {
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 66), Size(13, 13)));
                }
            }
        }

        case BitmapMarkerKind::Circ_7x7:
        case BitmapMarkerKind::Customshape_7x7:
        {
            return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, tools::Rectangle(Point(27, nYPos), Size(7, 7)));
        }

        case BitmapMarkerKind::Circ_9x9:
        case BitmapMarkerKind::Customshape_9x9:
        {
            return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, tools::Rectangle(Point(34, nYPos), Size(9, 9)));
        }

        case BitmapMarkerKind::Circ_11x11:
        case BitmapMarkerKind::Customshape_11x11:
        {
            return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, tools::Rectangle(Point(43, nYPos), Size(11, 11)));
        }

        case BitmapMarkerKind::Elli_7x9:
        {
            return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, tools::Rectangle(Point(54, nYPos), Size(7, 9)));
        }

        case BitmapMarkerKind::Elli_9x11:
        {
            return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, tools::Rectangle(Point(61, nYPos), Size(9, 11)));
        }

        case BitmapMarkerKind::Elli_9x7:
        {
            return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, tools::Rectangle(Point(70, nYPos), Size(9, 7)));
        }

        case BitmapMarkerKind::Elli_11x9:
        {
            return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, tools::Rectangle(Point(79, nYPos), Size(11, 9)));
        }

        case BitmapMarkerKind::RectPlus_7x7:
        {
            return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, tools::Rectangle(Point(90, nYPos), Size(7, 7)));
        }

        case BitmapMarkerKind::RectPlus_9x9:
        {
            return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, tools::Rectangle(Point(97, nYPos), Size(9, 9)));
        }

        case BitmapMarkerKind::RectPlus_11x11:
        {
            return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, tools::Rectangle(Point(106, nYPos), Size(11, 11)));
        }

        case BitmapMarkerKind::Crosshair:
        {
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
        }

        case BitmapMarkerKind::Glue:
        {
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
        }

        case BitmapMarkerKind::Glue_Deselected:
        {
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
        }

        case BitmapMarkerKind::Anchor: // AnchorTR for SW
        case BitmapMarkerKind::AnchorTR:
        {
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
        }

        // add AnchorPressed to be able to animate anchor control
        case BitmapMarkerKind::AnchorPressed:
        case BitmapMarkerKind::AnchorPressedTR:
        {
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
        }
    }
}


SdrHdl::SdrHdl():
    m_pObj(nullptr),
    m_pPV(nullptr),
    m_pHdlList(nullptr),
    m_eKind(SdrHdlKind::Move),
    m_nRotationAngle(0),
    m_nObjHdlNum(0),
    m_nPolyNum(0),
    m_nPPntNum(0),
    m_nSourceHdlNum(0),
    m_bSelect(false),
    m_b1PixMore(false),
    m_bPlusHdl(false),
    mbMoveOutside(false),
    mbMouseOver(false)
{
}

SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind):
    m_pObj(nullptr),
    m_pPV(nullptr),
    m_pHdlList(nullptr),
    m_aPos(rPnt),
    m_eKind(eNewKind),
    m_nRotationAngle(0),
    m_nObjHdlNum(0),
    m_nPolyNum(0),
    m_nPPntNum(0),
    m_nSourceHdlNum(0),
    m_bSelect(false),
    m_b1PixMore(false),
    m_bPlusHdl(false),
    mbMoveOutside(false),
    mbMouseOver(false)
{
}

SdrHdl::~SdrHdl()
{
    GetRidOfIAObject();
}

void SdrHdl::Set1PixMore(bool bJa)
{
    if(m_b1PixMore != bJa)
    {
        m_b1PixMore = bJa;

        // create new display
        Touch();
    }
}

void SdrHdl::SetMoveOutside( bool bMoveOutside )
{
    if(mbMoveOutside != bMoveOutside)
    {
        mbMoveOutside = bMoveOutside;

        // create new display
        Touch();
    }
}

void SdrHdl::SetRotationAngle(Degree100 n)
{
    if(m_nRotationAngle != n)
    {
        m_nRotationAngle = n;

        // create new display
        Touch();
    }
}

void SdrHdl::SetPos(const Point& rPnt)
{
    if(m_aPos != rPnt)
    {
        // remember new position
        m_aPos = rPnt;

        // create new display
        Touch();
    }
}

void SdrHdl::SetSelected(bool bJa)
{
    if(m_bSelect != bJa)
    {
        // remember new value
        m_bSelect = bJa;

        // create new display
        Touch();
    }
}

void SdrHdl::SetHdlList(SdrHdlList* pList)
{
    if(m_pHdlList != pList)
    {
        // remember list
        m_pHdlList = pList;

        // now it's possible to create graphic representation
        Touch();
    }
}

void SdrHdl::SetObj(SdrObject* pNewObj)
{
    if(m_pObj != pNewObj)
    {
        // remember new object
        m_pObj = pNewObj;

        // graphic representation may have changed
        Touch();
    }
}

void SdrHdl::Touch()
{
    // force update of graphic representation
    CreateB2dIAObject();
}

void SdrHdl::GetRidOfIAObject()
{

    // OVERLAYMANAGER
    maOverlayGroup.clear();
}

void SdrHdl::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList || !m_pHdlList->GetView() || m_pHdlList->GetView()->areMarkHandlesHidden())
        return;

    BitmapColorIndex eColIndex = BitmapColorIndex::LightGreen;
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;

    bool bRot = m_pHdlList->IsRotateShear();
    if(m_pObj)
        eColIndex = m_bSelect ? BitmapColorIndex::Cyan : BitmapColorIndex::LightCyan;
    if(bRot)
    {
        // red rotation handles
        if(m_pObj && m_bSelect)
            eColIndex = BitmapColorIndex::Red;
        else
            eColIndex = BitmapColorIndex::LightRed;
    }

    switch(m_eKind)
    {
        case SdrHdlKind::Move:
        {
            eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
            break;
        }
        case SdrHdlKind::UpperLeft:
        case SdrHdlKind::UpperRight:
        case SdrHdlKind::LowerLeft:
        case SdrHdlKind::LowerRight:
        {
            // corner handles
            if(bRot)
            {
                eKindOfMarker = BitmapMarkerKind::Circ_7x7;
            }
            else
            {
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
            }
            break;
        }
        case SdrHdlKind::Upper:
        case SdrHdlKind::Lower:
        {
            // Upper/Lower handles
            if(bRot)
            {
                eKindOfMarker = BitmapMarkerKind::Elli_9x7;
            }
            else
            {
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
            }
            break;
        }
        case SdrHdlKind::Left:
        case SdrHdlKind::Right:
        {
            // Left/Right handles
            if(bRot)
            {
                eKindOfMarker = BitmapMarkerKind::Elli_7x9;
            }
            else
            {
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
            }
            break;
        }
        case SdrHdlKind::Poly:
        {
            if(bRot)
            {
                eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Circ_9x9 : BitmapMarkerKind::Circ_7x7;
            }
            else
            {
                eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
            }
            break;
        }
        case SdrHdlKind::BezierWeight: // weight at poly
        {
            eKindOfMarker = BitmapMarkerKind::Circ_7x7;
            break;
        }
        case SdrHdlKind::Circle:
        {
            eKindOfMarker = BitmapMarkerKind::Rect_11x11;
            break;
        }
        case SdrHdlKind::Ref1:
        case SdrHdlKind::Ref2:
        {
            eKindOfMarker = BitmapMarkerKind::Crosshair;
            break;
        }
        case SdrHdlKind::Glue:
        {
            eKindOfMarker = BitmapMarkerKind::Glue;
            break;
        }
        case SdrHdlKind::Anchor:
        {
            eKindOfMarker = BitmapMarkerKind::Anchor;
            break;
        }
        case SdrHdlKind::User:
        {
            break;
        }
        // top right anchor for SW
        case SdrHdlKind::Anchor_TR:
        {
            eKindOfMarker = BitmapMarkerKind::AnchorTR;
            break;
        }

        // for SJ and the CustomShapeHandles:
        case SdrHdlKind::CustomShape1:
        {
            eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Customshape_9x9 : BitmapMarkerKind::Customshape_7x7;
            eColIndex = BitmapColorIndex::Yellow;
            break;
        }
        default:
            break;
    }

    SdrMarkView* pView = m_pHdlList->GetView();
    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            Point aMoveOutsideOffset(0, 0);
            OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice();

            // add offset if necessary
            if(m_pHdlList->IsMoveOutside() || mbMoveOutside)
            {
                Size aOffset = rOutDev.PixelToLogic(Size(4, 4));

                if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Upper || m_eKind == SdrHdlKind::UpperRight)
                    aMoveOutsideOffset.AdjustY( -(aOffset.Width()) );
                if(m_eKind == SdrHdlKind::LowerLeft || m_eKind == SdrHdlKind::Lower || m_eKind == SdrHdlKind::LowerRight)
                    aMoveOutsideOffset.AdjustY(aOffset.Height() );
                if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Left  || m_eKind == SdrHdlKind::LowerLeft)
                    aMoveOutsideOffset.AdjustX( -(aOffset.Width()) );
                if(m_eKind == SdrHdlKind::UpperRight || m_eKind == SdrHdlKind::Right || m_eKind == SdrHdlKind::LowerRight)
                    aMoveOutsideOffset.AdjustX(aOffset.Height() );
            }

            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject;
                if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker == BitmapMarkerKind::Rect_7x7 || eKindOfMarker == BitmapMarkerKind::Rect_9x9 || eKindOfMarker == BitmapMarkerKind::Rect_11x11))
                {
                    double fSize = 7.0;
                    switch (eKindOfMarker)
                    {
                        case BitmapMarkerKind::Rect_9x9:
                            fSize = 9.0;
                            break;
                        case BitmapMarkerKind::Rect_11x11:
                            fSize = 11.0;
                            break;
                        default:
                            break;
                    }
                    float fScalingFactor = rOutDev.GetDPIScaleFactor();
                    basegfx::B2DSize aB2DSize(fSize * fScalingFactor, fSize * fScalingFactor);

                    Color aHandleFillColor(COL_LIGHTGREEN);
                    switch (eColIndex)
                    {
                        case BitmapColorIndex::Cyan:
                            aHandleFillColor = COL_CYAN;
                            break;
                        case BitmapColorIndex::LightCyan:
                            aHandleFillColor = COL_LIGHTCYAN;
                            break;
                        case BitmapColorIndex::Red:
                            aHandleFillColor = COL_RED;
                            break;
                        case BitmapColorIndex::LightRed:
                            aHandleFillColor = COL_LIGHTRED;
                            break;
                        case BitmapColorIndex::Yellow:
                            aHandleFillColor = COL_YELLOW;
                            break;
                        default:
                            break;
                    }
                    pNewOverlayObject.reset(new sdr::overlay::OverlayHandle(aPosition, aB2DSize, /*HandleStrokeColor*/COL_BLACK, aHandleFillColor));
                }
                else
                {
                    pNewOverlayObject = CreateOverlayObject(
                                            aPosition, eColIndex, eKindOfMarker,
                                            aMoveOutsideOffset);
                }

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd)
{
    BitmapMarkerKind eRetval(eKnd);

    switch(eKnd)
    {
        case BitmapMarkerKind::Rect_7x7:          eRetval = BitmapMarkerKind::Rect_9x9;         break;
        case BitmapMarkerKind::Rect_9x9:          eRetval = BitmapMarkerKind::Rect_11x11;       break;
        case BitmapMarkerKind::Rect_11x11:        eRetval = BitmapMarkerKind::Rect_13x13;       break;

        case BitmapMarkerKind::Circ_7x7:          eRetval = BitmapMarkerKind::Circ_9x9;         break;
        case BitmapMarkerKind::Circ_9x9:          eRetval = BitmapMarkerKind::Circ_11x11;       break;

        case BitmapMarkerKind::Customshape_7x7:       eRetval = BitmapMarkerKind::Customshape_9x9;      break;
        case BitmapMarkerKind::Customshape_9x9:       eRetval = BitmapMarkerKind::Customshape_11x11;    break;
        //case BitmapMarkerKind::Customshape_11x11:   eRetval = ; break;

        case BitmapMarkerKind::Elli_7x9:          eRetval = BitmapMarkerKind::Elli_9x11;        break;

        case BitmapMarkerKind::Elli_9x7:          eRetval = BitmapMarkerKind::Elli_11x9;        break;

        case BitmapMarkerKind::RectPlus_7x7:      eRetval = BitmapMarkerKind::RectPlus_9x9;     break;
        case BitmapMarkerKind::RectPlus_9x9:      eRetval = BitmapMarkerKind::RectPlus_11x11;   break;

        // let anchor blink with its pressed state
        case BitmapMarkerKind::Anchor:            eRetval = BitmapMarkerKind::AnchorPressed;    break;

        // same for AnchorTR
        case BitmapMarkerKind::AnchorTR:          eRetval = BitmapMarkerKind::AnchorPressedTR;  break;
        default:
            break;
    }

    return eRetval;
}

namespace
{

OUString appendMarkerName(BitmapMarkerKind eKindOfMarker)
{
    switch(eKindOfMarker)
    {
        case BitmapMarkerKind::Rect_7x7:
            return u"rect7"_ustr;
        case BitmapMarkerKind::Rect_9x9:
            return u"rect9"_ustr;
        case BitmapMarkerKind::Rect_11x11:
            return u"rect11"_ustr;
        case BitmapMarkerKind::Rect_13x13:
            return u"rect13"_ustr;
        case BitmapMarkerKind::Circ_7x7:
        case BitmapMarkerKind::Customshape_7x7:
            return u"circ7"_ustr;
        case BitmapMarkerKind::Circ_9x9:
        case BitmapMarkerKind::Customshape_9x9:
            return u"circ9"_ustr;
        case BitmapMarkerKind::Circ_11x11:
        case BitmapMarkerKind::Customshape_11x11:
            return u"circ11"_ustr;
        case BitmapMarkerKind::Elli_7x9:
            return u"elli7x9"_ustr;
        case BitmapMarkerKind::Elli_9x11:
            return u"elli9x11"_ustr;
        case BitmapMarkerKind::Elli_9x7:
            return u"elli9x7"_ustr;
        case BitmapMarkerKind::Elli_11x9:
            return u"elli11x9"_ustr;
        case BitmapMarkerKind::RectPlus_7x7:
            return u"rectplus7"_ustr;
        case BitmapMarkerKind::RectPlus_9x9:
            return u"rectplus9"_ustr;
        case BitmapMarkerKind::RectPlus_11x11:
            return u"rectplus11"_ustr;
        case BitmapMarkerKind::Crosshair:
            return u"cross"_ustr;
        case BitmapMarkerKind::Anchor:
        case BitmapMarkerKind::AnchorTR:
            return u"anchor"_ustr;
        case BitmapMarkerKind::AnchorPressed:
        case BitmapMarkerKind::AnchorPressedTR:
            return u"anchor-pressed"_ustr;
        case BitmapMarkerKind::Glue:
            return u"glue-selected"_ustr;
        case BitmapMarkerKind::Glue_Deselected:
            return u"glue-unselected"_ustr;
        default:
            break;
    }
    return OUString();
}

OUString appendMarkerColor(BitmapColorIndex eIndex)
{
    switch(eIndex)
    {
        case BitmapColorIndex::LightGreen:
            return u"1"_ustr;
        case BitmapColorIndex::Cyan:
            return u"2"_ustr;
        case BitmapColorIndex::LightCyan:
            return u"3"_ustr;
        case BitmapColorIndex::Red:
            return u"4"_ustr;
        case BitmapColorIndex::LightRed:
            return u"5"_ustr;
        case BitmapColorIndex::Yellow:
            return u"6"_ustr;
        default:
            break;
    }
    return OUString();
}

BitmapEx ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker, BitmapColorIndex eIndex)
{
    // use this code path only when we use HiDPI (for now)
    if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
    {
        OUString sMarkerName = appendMarkerName(eKindOfMarker);
        if (!sMarkerName.isEmpty())
        {
            OUString sMarkerPrefix(u"svx/res/marker-"_ustr);
            BitmapEx aBitmapEx;

            if (eKindOfMarker == BitmapMarkerKind::Crosshair
             || eKindOfMarker == BitmapMarkerKind::Anchor
             || eKindOfMarker == BitmapMarkerKind::AnchorTR
             || eKindOfMarker == BitmapMarkerKind::AnchorPressed
             || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR
             || eKindOfMarker == BitmapMarkerKind::Glue
             || eKindOfMarker == BitmapMarkerKind::Glue_Deselected)
            {
                aBitmapEx = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + ".png");
            }
            else
            {
                aBitmapEx = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + "-" + appendMarkerColor(eIndex) + ".png");
            }

            if (!aBitmapEx.IsEmpty())
                return aBitmapEx;
        }
    }

    // if we can't load the marker...

    static tools::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet {};
    return aModernSet.get()->GetBitmapEx(eKindOfMarker, sal_uInt16(eIndex));
}

// end anonymous namespace

std::unique_ptr<sdr::overlay::OverlayObject> SdrHdl::CreateOverlayObject(
    const basegfx::B2DPoint& rPos,
    BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset)
{
    std::unique_ptr<sdr::overlay::OverlayObject> pRetval;

    // support bigger sizes
    bool bForceBiggerSize(false);

    if (m_pHdlList && m_pHdlList->GetHdlSize() > 3)
    {
        switch(eKindOfMarker)
        {
            case BitmapMarkerKind::Anchor:
            case BitmapMarkerKind::AnchorPressed:
            case BitmapMarkerKind::AnchorTR:
            case BitmapMarkerKind::AnchorPressedTR:
            {
                // #i121463# For anchor, do not simply make bigger because of HdlSize,
                // do it dependent of IsSelected() which Writer can set in drag mode
                if(IsSelected())
                {
                    bForceBiggerSize = true;
                }
                break;
            }
            default:
            {
                bForceBiggerSize = true;
                break;
            }
        }
    }

    if(bForceBiggerSize)
    {
        eKindOfMarker = GetNextBigger(eKindOfMarker);
    }

    // This handle has the focus, visualize it
    if(IsFocusHdl() && m_pHdlList && m_pHdlList->GetFocusHdl() == this)
    {
        // create animated handle
        BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker);

        if(eNextBigger == eKindOfMarker)
        {
            // this may happen for the not supported getting-bigger types.
            // Choose an alternative here
            switch(eKindOfMarker)
            {
                case BitmapMarkerKind::Rect_13x13:        eNextBigger = BitmapMarkerKind::Rect_11x11;   break;
                case BitmapMarkerKind::Circ_11x11:        eNextBigger = BitmapMarkerKind::Elli_11x9;    break;
                case BitmapMarkerKind::Elli_9x11:         eNextBigger = BitmapMarkerKind::Elli_11x9;    break;
                case BitmapMarkerKind::Elli_11x9:         eNextBigger = BitmapMarkerKind::Elli_9x11;    break;
                case BitmapMarkerKind::RectPlus_11x11:    eNextBigger = BitmapMarkerKind::Rect_13x13;   break;
                case BitmapMarkerKind::Glue:
                    eNextBigger = BitmapMarkerKind::Crosshair;
                    break;
                case BitmapMarkerKind::Crosshair:
                case BitmapMarkerKind::Glue_Deselected:
                    eNextBigger = BitmapMarkerKind::Glue;
                    break;
                default:
                    break;
            }
        }

        // create animated handle
        BitmapEx aBmpEx1 = ImpGetBitmapEx(eKindOfMarker, eColIndex);
        BitmapEx aBmpEx2 = ImpGetBitmapEx(eNextBigger,   eColIndex);

        // #i53216# Use system cursor blink time. Use the unsigned value.
        const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
        const sal_uInt64 nBlinkTime(rStyleSettings.GetCursorBlinkTime());

        if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
        {
            // when anchor is used take upper left as reference point inside the handle
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime));
        }
        else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
        {
            // AnchorTR for SW, take top right as (0,0)
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
                static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1), 0,
                static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Width() - 1), 0));
        }
        else
        {
            // create centered handle as default
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
                static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
                static_cast<sal_uInt16>(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
                static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
                static_cast<sal_uInt16>(aBmpEx2.GetSizePixel().Height() - 1) >> 1));
        }
    }
    else
    {
        // create normal handle: use ImpGetBitmapEx(...) now
        BitmapEx aBmpEx = ImpGetBitmapEx(eKindOfMarker, eColIndex);

        // When the image with handles is not found, the bitmap returned is
        // empty. This is a problem when we use LibreOffice as a library
        // (through LOKit - for example on Android) even when we don't show
        // the handles, because the hit test would always return false.
        //
        // This HACK replaces the empty bitmap with a black 13x13 bitmap handle
        // so that the hit test works for this case.
        if (aBmpEx.IsEmpty())
        {
            aBmpEx = BitmapEx(Size(13, 13), vcl::PixelFormat::N24_BPP);
            aBmpEx.Erase(COL_BLACK);
        }

        if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
        {
            // upper left as reference point inside the handle for AnchorPressed, too
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx));
        }
        else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
        {
            // AnchorTR for SW, take top right as (0,0)
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx,
                static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1), 0));
        }
        else
        {
            sal_uInt16 nCenX(static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1) >> 1);
            sal_uInt16 nCenY(static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Height() - 1) >> 1);

            if(aMoveOutsideOffset.X() > 0)
            {
                nCenX = 0;
            }
            else if(aMoveOutsideOffset.X() < 0)
            {
                nCenX = static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Width() - 1);
            }

            if(aMoveOutsideOffset.Y() > 0)
            {
                nCenY = 0;
            }
            else if(aMoveOutsideOffset.Y() < 0)
            {
                nCenY = static_cast<sal_uInt16>(aBmpEx.GetSizePixel().Height() - 1);
            }

            // create centered handle as default
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, nCenX, nCenY));
        }
    }

    return pRetval;
}

bool SdrHdl::IsHdlHit(const Point& rPnt) const
{
    // OVERLAYMANAGER
    basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y());
    return maOverlayGroup.isHitLogic(aPosition);
}

PointerStyle SdrHdl::GetPointer() const
{
    PointerStyle ePtr=PointerStyle::Move;
    const bool bSize=m_eKind>=SdrHdlKind::UpperLeft && m_eKind<=SdrHdlKind::LowerRight;
    const bool bRot=m_pHdlList!=nullptr && m_pHdlList->IsRotateShear();
    const bool bDis=m_pHdlList!=nullptr && m_pHdlList->IsDistortShear();
    if (bSize && m_pHdlList!=nullptr && (bRot || bDis)) {
        switch (m_eKind) {
            case SdrHdlKind::UpperLeft: case SdrHdlKind::UpperRight:
            case SdrHdlKind::LowerLeft: case SdrHdlKind::LowerRight: ePtr=bRot ? PointerStyle::Rotate : PointerStyle::RefHand; break;
            case SdrHdlKind::Left : case SdrHdlKind::Right: ePtr=PointerStyle::VShear; break;
            case SdrHdlKind::Upper: case SdrHdlKind::Lower: ePtr=PointerStyle::HShear; break;
            default:
                break;
        }
    } else {
        // When resizing rotated rectangles, rotate the mouse cursor slightly, too
        if (bSize && m_nRotationAngle!=0_deg100) {
            Degree100 nHdlAngle(0);
            switch (m_eKind) {
                case SdrHdlKind::LowerRight: nHdlAngle=31500_deg100; break;
                case SdrHdlKind::Lower: nHdlAngle=27000_deg100; break;
                case SdrHdlKind::LowerLeft: nHdlAngle=22500_deg100; break;
                case SdrHdlKind::Left : nHdlAngle=18000_deg100; break;
                case SdrHdlKind::UpperLeft: nHdlAngle=13500_deg100; break;
                case SdrHdlKind::Upper: nHdlAngle=9000_deg100;  break;
                case SdrHdlKind::UpperRight: nHdlAngle=4500_deg100;  break;
                case SdrHdlKind::Right: nHdlAngle=0_deg100;     break;
                default:
                    break;
            }
            // a little bit more (for rounding)
            nHdlAngle = NormAngle36000(nHdlAngle + m_nRotationAngle + 2249_deg100);
            nHdlAngle/=4500_deg100;
            switch (static_cast<sal_uInt8>(nHdlAngle.get())) {
                case 0: ePtr=PointerStyle::ESize;  break;
                case 1: ePtr=PointerStyle::NESize; break;
                case 2: ePtr=PointerStyle::NSize;  break;
                case 3: ePtr=PointerStyle::NWSize; break;
                case 4: ePtr=PointerStyle::WSize;  break;
                case 5: ePtr=PointerStyle::SWSize; break;
                case 6: ePtr=PointerStyle::SSize;  break;
                case 7: ePtr=PointerStyle::SESize; break;
            } // switch
        } else {
            switch (m_eKind) {
                case SdrHdlKind::UpperLeft: ePtr=PointerStyle::NWSize;  break;
                case SdrHdlKind::Upper: ePtr=PointerStyle::NSize;     break;
                case SdrHdlKind::UpperRight: ePtr=PointerStyle::NESize;  break;
                case SdrHdlKind::Left : ePtr=PointerStyle::WSize;     break;
                case SdrHdlKind::Right: ePtr=PointerStyle::ESize;     break;
                case SdrHdlKind::LowerLeft: ePtr=PointerStyle::SWSize;  break;
                case SdrHdlKind::Lower: ePtr=PointerStyle::SSize;     break;
                case SdrHdlKind::LowerRight: ePtr=PointerStyle::SESize;  break;
                case SdrHdlKind::Poly : ePtr=PointerStyle::MovePoint; break;
                case SdrHdlKind::Circle : ePtr=PointerStyle::Hand;      break;
                case SdrHdlKind::Ref1 : ePtr=PointerStyle::RefHand;   break;
                case SdrHdlKind::Ref2 : ePtr=PointerStyle::RefHand;   break;
                case SdrHdlKind::BezierWeight : ePtr=PointerStyle::MoveBezierWeight; break;
                case SdrHdlKind::Glue : ePtr=PointerStyle::MovePoint; break;
                case SdrHdlKind::CustomShape1 : ePtr=PointerStyle::RefHand; break;
                default:
                    break;
            }
        }
    }
    return ePtr;
}

bool SdrHdl::IsFocusHdl() const
{
    switch(m_eKind)
    {
        case SdrHdlKind::UpperLeft:
        case SdrHdlKind::Upper:
        case SdrHdlKind::UpperRight:
        case SdrHdlKind::Left:
        case SdrHdlKind::Right:
        case SdrHdlKind::LowerLeft:
        case SdrHdlKind::Lower:
        case SdrHdlKind::LowerRight:
        {
            // if it's an activated TextEdit, it's moved to extended points
            return !m_pHdlList || !m_pHdlList->IsMoveOutside();
        }

        case SdrHdlKind::Move:      // handle to move object
        case SdrHdlKind::Poly:      // selected point of polygon or curve
        case SdrHdlKind::BezierWeight:      // weight at a curve
        case SdrHdlKind::Circle:      // angle of circle segments, corner radius of rectangles
        case SdrHdlKind::Ref1:      // reference point 1, e. g. center of rotation
        case SdrHdlKind::Ref2:      // reference point 2, e. g. endpoint of reflection axis
        case SdrHdlKind::Glue:      // gluepoint

        // for SJ and the CustomShapeHandles:
        case SdrHdlKind::CustomShape1:

        case SdrHdlKind::User:
        {
            return true;
        }

        default:
        {
            return false;
        }
    }
}

void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/)
{
}

void SdrHdl::onHelpRequest()
{
}

void SdrHdl::onMouseLeave()
{
}

BitmapEx SdrHdl::createGluePointBitmap()
{
    return ImpGetBitmapEx(BitmapMarkerKind::Glue_Deselected, BitmapColorIndex::LightGreen);
}

void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl(
    std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject,
    const sdr::contact::ObjectContact& rObjectContact,
    sdr::overlay::OverlayManager& rOverlayManager)
{
    // check if we have an OverlayObject
    if(!pOverlayObject)
    {
        return;
    }

    // Add GridOffset for non-linear ViewToDevice transformation (calc)
    if(nullptr != GetObj() && rObjectContact.supportsGridOffsets())
    {
        basegfx::B2DVector aOffset(0.0, 0.0);
        const sdr::contact::ViewObjectContact& rVOC(GetObj()->GetViewContact().GetViewObjectContact(
            const_cast<sdr::contact::ObjectContact&>(rObjectContact)));

        rObjectContact.calculateGridOffsetForViewObjectContact(aOffset, rVOC);

        if(!aOffset.equalZero())
        {
            pOverlayObject->setOffset(aOffset);
        }
    }

    // add to OverlayManager
    rOverlayManager.add(*pOverlayObject);

    // add to local OverlayObjectList - ownership change (!)
    maOverlayGroup.append(std::move(pOverlayObject));
}

SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, bool bLum)
:   SdrHdl(rRef, SdrHdlKind::Color),
    m_aMarkerSize(rSize),
    m_bUseLuminance(bLum)
{
    if(IsUseLuminance())
        aCol = GetLuminance(aCol);

    // remember color
    m_aMarkerColor = aCol;
}

SdrHdlColor::~SdrHdlColor()
{
}

void SdrHdlColor::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                BitmapEx aBmpCol(CreateColorDropper(m_aMarkerColor));
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
                    sdr::overlay::OverlayBitmapEx(
                        aPosition,
                        aBmpCol,
                        static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Width() - 1) >> 1,
                        static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Height() - 1) >> 1
                    ));

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

BitmapEx SdrHdlColor::CreateColorDropper(Color aCol)
{
    // get the Bitmap
    VclPtr<VirtualDevice> pWrite(VclPtr<VirtualDevice>::Create());
    pWrite->SetOutputSizePixel(m_aMarkerSize);
    pWrite->SetBackground(aCol);
    pWrite->Erase();

    // draw outer border
    sal_Int32 nWidth = m_aMarkerSize.Width();
    sal_Int32 nHeight = m_aMarkerSize.Height();

    pWrite->SetLineColor(COL_LIGHTGRAY);
    pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1));
    pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0));
    pWrite->SetLineColor(COL_GRAY);
    pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1));
    pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2));

    // draw lighter UpperLeft
    const Color aLightColor(
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff))));
    pWrite->SetLineColor(aLightColor);
    pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2));
    pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1));

    // draw darker LowerRight
    const Color aDarkColor(
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000))));
    pWrite->SetLineColor(aDarkColor);
    pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2));
    pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3));

    return pWrite->GetBitmapEx(Point(0,0), m_aMarkerSize);
}

Color SdrHdlColor::GetLuminance(const Color& rCol)
{
    sal_uInt8 aLum = rCol.GetLuminance();
    Color aRetval(aLum, aLum, aLum);
    return aRetval;
}

void SdrHdlColor::SetColor(Color aNew, bool bCallLink)
{
    if(IsUseLuminance())
        aNew = GetLuminance(aNew);

    if(m_aMarkerColor != aNew)
    {
        // remember new color
        m_aMarkerColor = aNew;

        // create new display
        Touch();

        // tell about change
        if(bCallLink)
            m_aColorChangeHdl.Call(this);
    }
}

void SdrHdlColor::SetSize(const Size& rNew)
{
    if(rNew != m_aMarkerSize)
    {
        // remember new size
        m_aMarkerSize = rNew;

        // create new display
        Touch();
    }
}

SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, bool bGrad)
    : SdrHdl(rRef1, bGrad ? SdrHdlKind::Gradient : SdrHdlKind::Transparence)
    , m_pColHdl1(nullptr)
    , m_pColHdl2(nullptr)
    , m_a2ndPos(rRef2)
    , m_bGradient(bGrad)
    , m_bMoveSingleHandle(false)
    , m_bMoveFirstHandle(false)
{
}

SdrHdlGradient::~SdrHdlGradient()
{
}

void SdrHdlGradient::Set2ndPos(const Point& rPnt)
{
    if(m_a2ndPos != rPnt)
    {
        // remember new position
        m_a2ndPos = rPnt;

        // create new display
        Touch();
    }
}

void SdrHdlGradient::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                // striped line in between
                basegfx::B2DVector aVec(m_a2ndPos.X() - m_aPos.X(), m_a2ndPos.Y() - m_aPos.Y());
                double fVecLen = aVec.getLength();
                double fLongPercentArrow = (1.0 - 0.05) * fVecLen;
                double fHalfArrowWidth = (0.05 * 0.5) * fVecLen;
                aVec.normalize();
                basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX());
                sal_Int32 nMidX = static_cast<sal_Int32>(m_aPos.X() + aVec.getX() * fLongPercentArrow);
                sal_Int32 nMidY = static_cast<sal_Int32>(m_aPos.Y() + aVec.getY() * fLongPercentArrow);
                Point aMidPoint(nMidX, nMidY);

                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
                basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y());

                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
                    sdr::overlay::OverlayLineStriped(
                        aPosition, aMidPos
                    ));

                pNewOverlayObject->setBaseColor(IsGradient() ? COL_BLACK : COL_BLUE);

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);

                // arrowhead
                Point aLeft(aMidPoint.X() + static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
                            aMidPoint.Y() + static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));
                Point aRight(aMidPoint.X() - static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
                            aMidPoint.Y() - static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));

                basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y());
                basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y());
                basegfx::B2DPoint aPosition2(m_a2ndPos.X(), m_a2ndPos.Y());

                pNewOverlayObject.reset(new
                    sdr::overlay::OverlayTriangle(
                        aPositionLeft,
                        aPosition2,
                        aPositionRight,
                        IsGradient() ? COL_BLACK : COL_BLUE
                    ));

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

IMPL_LINK_NOARG(SdrHdlGradient, ColorChangeHdl, SdrHdlColor*, void)
{
    if(GetObj())
        FromIAOToItem(GetObj(), truetrue);
}

void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, bool bSetItemOnObject, bool bUndo)
{
    // from IAO positions and colors to gradient
    const SfxItemSet& rSet = _pObj->GetMergedItemSet();

    GradTransGradient aOldGradTransGradient;
    GradTransGradient aGradTransGradient;
    GradTransVector aGradTransVector;

    aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y());
    aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
    if(m_pColHdl1)
        aGradTransVector.aCol1 = m_pColHdl1->GetColor();
    if(m_pColHdl2)
        aGradTransVector.aCol2 = m_pColHdl2->GetColor();

    if(IsGradient())
        aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLGRADIENT).GetGradientValue();
    else
        aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLFLOATTRANSPARENCE).GetGradientValue();

    // transform vector data to gradient
    GradTransformer::VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, m_bMoveSingleHandle, m_bMoveFirstHandle);

    if(bSetItemOnObject)
    {
        SdrModel& rModel(_pObj->getSdrModelFromSdrObject());
        SfxItemSet aNewSet(rModel.GetItemPool());
        const OUString aString;

        if(IsGradient())
        {
            XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient);
            aNewSet.Put(aNewGradItem);
        }
        else
        {
            XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient);
            aNewSet.Put(aNewTransItem);
        }

        if(bUndo && rModel.IsUndoEnabled())
        {
            rModel.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE));
            rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj));
            rModel.EndUndo();
        }

        m_pObj->SetMergedItemSetAndBroadcast(aNewSet);
    }

    // back transformation, set values on pIAOHandle
    GradTransformer::GradToVec(aGradTransGradient, aGradTransVector, _pObj);

    SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()),
             basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) });
    Set2ndPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()),
                basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) });
    if(m_pColHdl1)
    {
        m_pColHdl1->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()),
                             basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) });
        m_pColHdl1->SetColor(aGradTransVector.aCol1);
    }
    if(m_pColHdl2)
    {
        m_pColHdl2->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()),
                             basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) });
        m_pColHdl2->SetColor(aGradTransVector.aCol2);
    }
}


SdrHdlLine::~SdrHdlLine() {}

void SdrHdlLine::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!(pView && !pView->areMarkHandlesHidden() && m_pHdl1 && m_pHdl2))
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
                basegfx::B2DPoint aPosition2(m_pHdl2->GetPos().X(), m_pHdl2->GetPos().Y());

                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
                    sdr::overlay::OverlayLineStriped(
                        aPosition1,
                        aPosition2
                    ));

                // color(?)
                pNewOverlayObject->setBaseColor(COL_LIGHTRED);

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

PointerStyle SdrHdlLine::GetPointer() const
{
    return PointerStyle::RefHand;
}


SdrHdlBezWgt::~SdrHdlBezWgt() {}

void SdrHdlBezWgt::CreateB2dIAObject()
{
    // call parent
    SdrHdl::CreateB2dIAObject();

    // create lines
    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
                basegfx::B2DPoint aPosition2(m_aPos.X(), m_aPos.Y());

                if(!aPosition1.equal(aPosition2))
                {
                    std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
                        sdr::overlay::OverlayLineStriped(
                            aPosition1,
                            aPosition2
                        ));

                    // line part is not hittable
                    pNewOverlayObject->setHittable(false);

                    // color(?)
                    pNewOverlayObject->setBaseColor(COL_LIGHTBLUE);

                    // OVERLAYMANAGER
                    insertNewlyCreatedOverlayObjectForSdrHdl(
                        std::move(pNewOverlayObject),
                        rPageWindow.GetObjectContact(),
                        *xManager);
                }
            }
        }
    }
}


E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly)
{
    m_aWireframePoly = rWireframePoly;
}

void E3dVolumeMarker::CreateB2dIAObject()
{
    // create lines
    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is() && m_aWireframePoly.count())
            {
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
                    sdr::overlay::OverlayPolyPolygonStripedAndFilled(
                        m_aWireframePoly));

                pNewOverlayObject->setBaseColor(COL_BLACK);

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}


ImpEdgeHdl::~ImpEdgeHdl()
{
}

void ImpEdgeHdl::CreateB2dIAObject()
{
    if(m_nObjHdlNum > 1 || !m_pObj)
    {
        // call parent
        SdrHdl::CreateB2dIAObject();
        return;
    }

    // first throw away old one
    GetRidOfIAObject();

    BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    // tdf#159666 Crash when table and line object are selected at the same time
    auto pEdge = dynamic_cast<SdrEdgeObj*>(m_pObj);
    if (!pEdge)
        return;

    if(pEdge->GetConnectedNode(m_nObjHdlNum == 0) != nullptr)
        eColIndex = BitmapColorIndex::LightRed;

    if(m_nPPntNum < 2)
    {
        // Handle with plus sign inside
        eKindOfMarker = BitmapMarkerKind::Circ_7x7;
    }

    SdrPageView* pPageView = pView->GetSdrPageView();
    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
                    aPosition,
                    eColIndex,
                    eKindOfMarker));

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode)
{
    if(m_eLineCode != eCode)
    {
        // remember new value
        m_eLineCode = eCode;

        // create new display
        Touch();
    }
}

PointerStyle ImpEdgeHdl::GetPointer() const
{
    SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
    if (pEdge==nullptr)
        return SdrHdl::GetPointer();
    if (m_nObjHdlNum<=1)
        return PointerStyle::MovePoint;
    if (IsHorzDrag())
        return PointerStyle::ESize;
    else
        return PointerStyle::SSize;
}

bool ImpEdgeHdl::IsHorzDrag() const
{
    SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
    if (pEdge==nullptr)
        return false;
    if (m_nObjHdlNum<=1)
        return false;

    SdrEdgeKind eEdgeKind = pEdge->GetObjectItem(SDRATTR_EDGEKIND).GetValue();

    const SdrEdgeInfoRec& rInfo=pEdge->m_aEdgeInfo;
    if (eEdgeKind==SdrEdgeKind::OrthoLines || eEdgeKind==SdrEdgeKind::Bezier)
    {
        return !rInfo.ImpIsHorzLine(m_eLineCode,*pEdge->m_pEdgeTrack);
    }
    else if (eEdgeKind==SdrEdgeKind::ThreeLines)
    {
        tools::Long nAngle=m_nObjHdlNum==2 ? rInfo.m_nAngle1 : rInfo.m_nAngle2;
        return nAngle==0 || nAngle==18000;
    }
    return false;
}


ImpMeasureHdl::~ImpMeasureHdl()
{
}

void ImpMeasureHdl::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_9x9;

    if(m_nObjHdlNum > 1)
    {
        eKindOfMarker = BitmapMarkerKind::Rect_7x7;
    }

    if(m_bSelect)
    {
        eColIndex = BitmapColorIndex::Cyan;
    }

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
                    aPosition,
                    eColIndex,
                    eKindOfMarker));

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}

PointerStyle ImpMeasureHdl::GetPointer() const
{
    switch (m_nObjHdlNum)
    {
        case 0: case 1: return PointerStyle::Hand;
        case 2: case 3: return PointerStyle::MovePoint;
        case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
    } // switch
    return PointerStyle::NotAllowed;
}


ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle& rRect) :
    SdrHdl(rRect.TopLeft(),SdrHdlKind::Move),
    maRect(rRect)
{
}

void ImpTextframeHdl::CreateB2dIAObject()
{
    // first throw away old one
    GetRidOfIAObject();

    if(!m_pHdlList)
        return;

    SdrMarkView* pView = m_pHdlList->GetView();

    if(!pView || pView->areMarkHandlesHidden())
        return;

    SdrPageView* pPageView = pView->GetSdrPageView();

    if(!pPageView)
        return;

    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
    {
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);

        if(rPageWindow.GetPaintWindow().OutputToWindow())
        {
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
            if (xManager.is())
            {
                const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top());
                const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom());
                const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
                const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);

                std::unique_ptr<sdr::overlay::OverlayRectangle> pNewOverlayObject(new sdr::overlay::OverlayRectangle(
                    aTopLeft,
                    aBottomRight,
                    aHilightColor,
                    fTransparence,
                    3.0,
                    3.0,
                    -toRadians(m_nRotationAngle),
                    true)); // allow animation; the Handle is not shown at text edit time

                pNewOverlayObject->setHittable(false);

                // OVERLAYMANAGER
                insertNewlyCreatedOverlayObjectForSdrHdl(
                    std::move(pNewOverlayObject),
                    rPageWindow.GetObjectContact(),
                    *xManager);
            }
        }
    }
}


static bool ImpSdrHdlListSorter(std::unique_ptr<SdrHdl> const& lhs, std::unique_ptr<SdrHdl> const& rhs)
{
    SdrHdlKind eKind1=lhs->GetKind();
    SdrHdlKind eKind2=rhs->GetKind();
    // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
    unsigned n1=1;
    unsigned n2=1;
    if (eKind1!=eKind2)
    {
        if (eKind1==SdrHdlKind::Ref1 || eKind1==SdrHdlKind::Ref2 || eKind1==SdrHdlKind::MirrorAxis) n1=5;
        else if (eKind1==SdrHdlKind::Glue) n1=2;
        else if (eKind1==SdrHdlKind::User) n1=3;
        else if (eKind1==SdrHdlKind::SmartTag) n1=0;
        if (eKind2==SdrHdlKind::Ref1 || eKind2==SdrHdlKind::Ref2 || eKind2==SdrHdlKind::MirrorAxis) n2=5;
        else if (eKind2==SdrHdlKind::Glue) n2=2;
        else if (eKind2==SdrHdlKind::User) n2=3;
        else if (eKind2==SdrHdlKind::SmartTag) n2=0;
    }
    if (lhs->IsPlusHdl()) n1=4;
    if (rhs->IsPlusHdl()) n2=4;
    if (n1==n2)
    {
        // Level 2: PageView (Pointer)
        SdrPageView* pPV1=lhs->GetPageView();
        SdrPageView* pPV2=rhs->GetPageView();
        if (pPV1==pPV2)
        {
            // Level 3: Position (x+y)
            SdrObject* pObj1=lhs->GetObj();
            SdrObject* pObj2=rhs->GetObj();
            if (pObj1==pObj2)
            {
                sal_uInt32 nNum1=lhs->GetObjHdlNum();
                sal_uInt32 nNum2=rhs->GetObjHdlNum();
                if (nNum1==nNum2)
                {
                    if (eKind1==eKind2)
                        return lhs<rhs; // Hack, to always get to the same sorting
                    return static_cast<sal_uInt16>(eKind1)<static_cast<sal_uInt16>(eKind2);
                }
                else
                    return nNum1<nNum2;
            }
            else
            {
                return pObj1<pObj2;
            }
        }
        else
        {
            return pPV1<pPV2;
        }
    }
    else
    {
        return n1<n2;
    }
}

namespace {

// Helper struct for re-sorting handles
struct ImplHdlAndIndex
{
    SdrHdl*                     mpHdl;
    sal_uInt32                  mnIndex;
};

}

extern "C" {

// Helper method for sorting handles taking care of OrdNums, keeping order in
// single objects and re-sorting polygon handles intuitively
static int ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 )
{
    const ImplHdlAndIndex* p1 = static_cast<ImplHdlAndIndex const *>(pVoid1);
    const ImplHdlAndIndex* p2 = static_cast<ImplHdlAndIndex const *>(pVoid2);

    if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj())
    {
        if(p1->mpHdl->GetObj() && dynamic_cast<const SdrPathObj*>(p1->mpHdl->GetObj()) != nullptr)
        {
            // same object and a path object
            if((p1->mpHdl->GetKind() == SdrHdlKind::Poly || p1->mpHdl->GetKind() == SdrHdlKind::BezierWeight)
                && (p2->mpHdl->GetKind() == SdrHdlKind::Poly || p2->mpHdl->GetKind() == SdrHdlKind::BezierWeight))
            {
                // both handles are point or control handles
                if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum())
                {
                    if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum())
                    {
                        return -1;
                    }
                    else
                    {
                        return 1;
                    }
                }
                else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum())
                {
                    return -1;
                }
                else
                {
                    return 1;
                }
            }
        }
    }
    else
    {
        if(!p1->mpHdl->GetObj())
        {
            return -1;
        }
        else if(!p2->mpHdl->GetObj())
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=95 G=94

¤ Dauer der Verarbeitung: 0.32 Sekunden  ¤

*© 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.