tdf#150622 use high contrast selection fg/bg colors for text selection

with SettingsForSelection
SettingsText -> HighlightTextColor
SettingsFill -> HighlightColor
SettingsLine -> HighlightColor

Change-Id: Iaac5834ce0f8b3f1b89376711b564773cfd0bfe3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141287
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/svx/sdr/overlay/overlayobject.hxx b/include/svx/sdr/overlay/overlayobject.hxx
index 294ceb3..643007c 100644
--- a/include/svx/sdr/overlay/overlayobject.hxx
+++ b/include/svx/sdr/overlay/overlayobject.hxx
@@ -109,10 +109,11 @@ namespace sdr::overlay
            // it is switched to false
            bool                                            mbAllowsAntiAliase : 1;

            // Flag to control if this OverlayObject is allowed to ignore the
            // DrawMode settings which force use of colors to High Contrast fg/bg
            // In High Contrast mode all fg and bg and forced to the a pair of normal
            // high contrast colors. If this flag is set, then in High Contrast mode
            // the colors are instead forced to the high contrast selection fg/bg pair.
            // Default is false.
            bool                                            mbOverruleDrawModeSettings : 1;
            bool                                            mbHighContrastSelection : 1;

            // set changed flag. Call after change, since the old range is invalidated
            // and then the new one is calculated and invalidated, too. This will only
@@ -148,7 +149,7 @@ namespace sdr::overlay
            bool allowsAntiAliase() const { return mbAllowsAntiAliase; }

            // read access to DrawModeSettings flag
            bool overrulesDrawModeSettings() const { return mbOverruleDrawModeSettings; }
            bool isHighContrastSelection() const { return mbHighContrastSelection; }

            // read access to baseRange. This may trigger createBaseRange() if
            // object is changed.
diff --git a/include/vcl/rendercontext/DrawModeFlags.hxx b/include/vcl/rendercontext/DrawModeFlags.hxx
index edfa276..b51b179 100644
--- a/include/vcl/rendercontext/DrawModeFlags.hxx
+++ b/include/vcl/rendercontext/DrawModeFlags.hxx
@@ -45,11 +45,12 @@ enum class DrawModeFlags : sal_uInt32
    SettingsFill = 0x00020000,
    SettingsText = 0x00040000,
    SettingsGradient = 0x00080000,
    NoTransparency = 0x00100000,
    SettingsForSelection = 0x00100000,
    NoTransparency = 0x00200000,
};
namespace o3tl
{
template <> struct typed_flags<DrawModeFlags> : is_typed_flags<DrawModeFlags, 0x1fffff>
template <> struct typed_flags<DrawModeFlags> : is_typed_flags<DrawModeFlags, 0x3fffff>
{
};
}
diff --git a/svx/source/sdr/overlay/overlaymanager.cxx b/svx/source/sdr/overlay/overlaymanager.cxx
index 3d501b81..c29138d 100644
--- a/svx/source/sdr/overlay/overlaymanager.cxx
+++ b/svx/source/sdr/overlay/overlaymanager.cxx
@@ -51,8 +51,6 @@ namespace sdr::overlay
            // but it seems reasonable to allow overlays to use the selection color
            // taken from the system High Contrast settings
            const DrawModeFlags nOriginalDrawMode(rDestinationDevice.GetDrawMode());
            const DrawModeFlags nForceSettings = DrawModeFlags::SettingsLine | DrawModeFlags::SettingsFill |
                                                 DrawModeFlags::SettingsText | DrawModeFlags::SettingsGradient;

            // create processor
            std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor(drawinglayer::processor2d::createProcessor2DFromOutputDevice(
@@ -81,16 +79,16 @@ namespace sdr::overlay
                                rDestinationDevice.SetAntialiasing(nOriginalAA & ~AntialiasingFlags::Enable);
                            }

                            const bool bOverrulesDrawModeSettings = rCandidate.overrulesDrawModeSettings();
                            if (bOverrulesDrawModeSettings)
                            const bool bIsHighContrastSelection = rCandidate.isHighContrastSelection();
                            if (bIsHighContrastSelection)
                            {
                                // overrule DrawMode settings
                                rDestinationDevice.SetDrawMode(nOriginalDrawMode & ~nForceSettings);
                                rDestinationDevice.SetDrawMode(nOriginalDrawMode | DrawModeFlags::SettingsForSelection);
                            }

                            pProcessor->process(rSequence);

                            if (bOverrulesDrawModeSettings)
                            if (bIsHighContrastSelection)
                            {
                                // restore DrawMode settings
                                rDestinationDevice.SetDrawMode(nOriginalDrawMode);
diff --git a/svx/source/sdr/overlay/overlayobject.cxx b/svx/source/sdr/overlay/overlayobject.cxx
index 6aab4f8..5c1de46 100644
--- a/svx/source/sdr/overlay/overlayobject.cxx
+++ b/svx/source/sdr/overlay/overlayobject.cxx
@@ -91,7 +91,7 @@ namespace sdr::overlay
            mbIsHittable(true),
            mbAllowsAnimation(false),
            mbAllowsAntiAliase(true),
            mbOverruleDrawModeSettings(false)
            mbHighContrastSelection(false)
        {
        }

diff --git a/svx/source/sdr/overlay/overlayrectangle.cxx b/svx/source/sdr/overlay/overlayrectangle.cxx
index ce9c11b..3bf04f4 100644
--- a/svx/source/sdr/overlay/overlayrectangle.cxx
+++ b/svx/source/sdr/overlay/overlayrectangle.cxx
@@ -81,8 +81,8 @@ namespace sdr::overlay

            // set AllowsAnimation flag to mark this object as animation capable
            mbAllowsAnimation = bAnimate;
            // allow use of selection color even in HighContrast mode
            mbOverruleDrawModeSettings = true;
            // use selection colors in HighContrast mode
            mbHighContrastSelection = true;
        }

        void OverlayRectangle::Trigger(sal_uInt32 nTime)
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 9f3552f..76c629a 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -45,8 +45,11 @@
#include <vcl/weld.hxx>
#include <vcl/window.hxx>
#include <comphelper/lok.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <editeng/outliner.hxx>
#include <sal/log.hxx>
#include <sdr/overlay/overlaytools.hxx>
@@ -389,6 +392,7 @@ void SdrObjEditView::ModelHasChanged()
namespace
{
class TextEditFrameOverlayObject;
class TextEditHighContrastOverlaySelection;

/**
        Helper class to visualize the content of an active EditView as an
@@ -407,7 +411,8 @@ class TextEditOverlayObject : public sdr::overlay::OverlayObject
{
protected:
    /// local access to associated sdr::overlay::OverlaySelection
    std::unique_ptr<sdr::overlay::OverlaySelection> mxOverlaySelection;
    std::unique_ptr<sdr::overlay::OverlaySelection> mxOverlayTransparentSelection;
    std::unique_ptr<TextEditHighContrastOverlaySelection> mxOverlayHighContrastSelection;
    std::unique_ptr<TextEditFrameOverlayObject> mxOverlayFrame;

    /// local definition depends on active OutlinerView
@@ -429,15 +434,11 @@ public:
    TextEditOverlayObject(const Color& rColor, OutlinerView& rOutlinerView);
    virtual ~TextEditOverlayObject() override;

    // data read access
    const sdr::overlay::OverlaySelection* getOverlaySelection() const
    {
        return mxOverlaySelection.get();
    }
    const OutlinerView& getOutlinerView() const { return mrOutlinerView; }

    sdr::overlay::OverlayObject* getOverlaySelection();
    sdr::overlay::OverlayObject* getOverlayFrame();

    const OutlinerView& getOutlinerView() const { return mrOutlinerView; }

    /// override to check conditions for last createOverlayObjectPrimitive2DSequence
    virtual drawinglayer::primitive2d::Primitive2DContainer
    getOverlayObjectPrimitive2DSequence() const override;
@@ -448,6 +449,10 @@ public:
    void checkSelectionChange();

    const basegfx::B2DRange& getRange() const { return maRange; }
    const drawinglayer::primitive2d::Primitive2DContainer& getTextPrimitives() const
    {
        return maTextPrimitives;
    }
};

class TextEditFrameOverlayObject : public sdr::overlay::OverlayObject
@@ -465,6 +470,88 @@ public:
    virtual ~TextEditFrameOverlayObject() override;
};

class TextEditHighContrastOverlaySelection : public sdr::overlay::OverlayObject
{
private:
    const TextEditOverlayObject& mrTextEditOverlayObject;
    std::vector<basegfx::B2DRange> maRanges;

    // geometry creation for OverlayObject, can use local *Last* values
    virtual drawinglayer::primitive2d::Primitive2DContainer
    createOverlayObjectPrimitive2DSequence() override;

public:
    TextEditHighContrastOverlaySelection(const TextEditOverlayObject& rTextEditOverlayObject);
    void setRanges(std::vector<basegfx::B2DRange>&& rNew);
    virtual ~TextEditHighContrastOverlaySelection() override;
};

TextEditHighContrastOverlaySelection::TextEditHighContrastOverlaySelection(
    const TextEditOverlayObject& rTextEditOverlayObject)
    : OverlayObject(rTextEditOverlayObject.getBaseColor())
    , mrTextEditOverlayObject(rTextEditOverlayObject)
{
    allowAntiAliase(rTextEditOverlayObject.allowsAntiAliase());
    // use selection colors in HighContrast mode
    mbHighContrastSelection = true;
}

void TextEditHighContrastOverlaySelection::setRanges(std::vector<basegfx::B2DRange>&& rNew)
{
    if (rNew != maRanges)
    {
        maRanges = std::move(rNew);
        objectChange();
    }
}

drawinglayer::primitive2d::Primitive2DContainer
TextEditHighContrastOverlaySelection::createOverlayObjectPrimitive2DSequence()
{
    drawinglayer::primitive2d::Primitive2DContainer aRetval;

    size_t nCount = maRanges.size();

    if (nCount)
    {
        basegfx::B2DPolyPolygon aClipPolyPolygon;

        basegfx::BColor aRGBColor(getBaseColor().getBColor());

        for (size_t a = 0; a < nCount; ++a)
            aClipPolyPolygon.append(basegfx::utils::createPolygonFromRect(maRanges[a]));

        // This is used in high contrast mode, we will render the selection
        // with the bg forced to the selection Highlight color and the fg color
        // forced to the HighlightText color
        aRetval.append(drawinglayer::primitive2d::Primitive2DReference(
            new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
                basegfx::B2DPolyPolygon(
                    basegfx::utils::createPolygonFromRect(aClipPolyPolygon.getB2DRange())),
                aRGBColor)));
        aRetval.append(mrTextEditOverlayObject.getTextPrimitives());
        aRetval.append(drawinglayer::primitive2d::Primitive2DReference(
            new drawinglayer::primitive2d::MaskPrimitive2D(aClipPolyPolygon, std::move(aRetval))));
    }

    return aRetval;
}

TextEditHighContrastOverlaySelection::~TextEditHighContrastOverlaySelection()
{
    if (getOverlayManager())
    {
        getOverlayManager()->remove(*this);
    }
}

sdr::overlay::OverlayObject* TextEditOverlayObject::getOverlaySelection()
{
    if (mxOverlayTransparentSelection)
        return mxOverlayTransparentSelection.get();
    return mxOverlayHighContrastSelection.get();
}

sdr::overlay::OverlayObject* TextEditOverlayObject::getOverlayFrame()
{
    if (!mxOverlayFrame)
@@ -510,14 +597,22 @@ TextEditOverlayObject::TextEditOverlayObject(const Color& rColor, OutlinerView& 

    // create local OverlaySelection - this is an integral part of EditText
    // visualization
    std::vector<basegfx::B2DRange> aEmptySelection{};
    mxOverlaySelection.reset(new sdr::overlay::OverlaySelection(
        sdr::overlay::OverlayType::Transparent, rColor, std::move(aEmptySelection), true));
    if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
    {
        mxOverlayHighContrastSelection.reset(new TextEditHighContrastOverlaySelection(*this));
    }
    else
    {
        std::vector<basegfx::B2DRange> aEmptySelection{};
        mxOverlayTransparentSelection.reset(new sdr::overlay::OverlaySelection(
            sdr::overlay::OverlayType::Transparent, rColor, std::move(aEmptySelection), true));
    }
}

TextEditOverlayObject::~TextEditOverlayObject()
{
    mxOverlaySelection.reset();
    mxOverlayTransparentSelection.reset();
    mxOverlayHighContrastSelection.reset();

    if (getOverlayManager())
    {
@@ -531,8 +626,8 @@ TextEditFrameOverlayObject::TextEditFrameOverlayObject(
    , mrTextEditOverlayObject(rTextEditOverlayObject)
{
    allowAntiAliase(rTextEditOverlayObject.allowsAntiAliase());
    // allow use of selection color even in HighContrast mode
    mbOverruleDrawModeSettings = true;
    // use selection colors in HighContrast mode
    mbHighContrastSelection = true;
}

TextEditFrameOverlayObject::~TextEditFrameOverlayObject()
@@ -658,7 +753,10 @@ void TextEditOverlayObject::checkSelectionChange()
            aRect.Right() + aLogicPixel.Width(), aRect.Bottom() + aLogicPixel.Height());
    }

    mxOverlaySelection->setRanges(std::move(aLogicRanges));
    if (mxOverlayTransparentSelection)
        mxOverlayTransparentSelection->setRanges(std::move(aLogicRanges));
    else
        mxOverlayHighContrastSelection->setRanges(std::move(aLogicRanges));
}
} // end of anonymous namespace

@@ -1309,8 +1407,7 @@ bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, vcl::W
                                xManager->add(*pNewTextEditOverlayObject);
                                if (bVisualizeSurroundingFrame)
                                    xManager->add(*pNewTextEditOverlayObject->getOverlayFrame());
                                xManager->add(const_cast<sdr::overlay::OverlaySelection&>(
                                    *pNewTextEditOverlayObject->getOverlaySelection()));
                                xManager->add(*pNewTextEditOverlayObject->getOverlaySelection());

                                maTEOverlayGroup.append(std::move(pNewTextEditOverlayObject));
                            }
diff --git a/vcl/source/outdev/gradient.cxx b/vcl/source/outdev/gradient.cxx
index bd19cd5..707ca47 100644
--- a/vcl/source/outdev/gradient.cxx
+++ b/vcl/source/outdev/gradient.cxx
@@ -617,7 +617,12 @@ Color OutputDevice::GetSingleColorGradientFill()
    else if ( mnDrawMode & DrawModeFlags::WhiteGradient )
        aColor = COL_WHITE;
    else if ( mnDrawMode & DrawModeFlags::SettingsGradient )
        aColor = GetSettings().GetStyleSettings().GetWindowColor();
    {
        if (mnDrawMode & DrawModeFlags::SettingsForSelection)
            aColor = GetSettings().GetStyleSettings().GetHighlightColor();
        else
            aColor = GetSettings().GetStyleSettings().GetWindowColor();
    }

    return aColor;
}
diff --git a/vcl/source/rendercontext/drawmode.cxx b/vcl/source/rendercontext/drawmode.cxx
index fe0a1660..9819be3 100644
--- a/vcl/source/rendercontext/drawmode.cxx
+++ b/vcl/source/rendercontext/drawmode.cxx
@@ -53,7 +53,10 @@ Color GetLineColor(Color const& rColor, DrawModeFlags nDrawMode,
            }
            else if (nDrawMode & DrawModeFlags::SettingsLine)
            {
                aColor = rStyleSettings.GetWindowTextColor();
                if (nDrawMode & DrawModeFlags::SettingsForSelection)
                    aColor = rStyleSettings.GetHighlightColor();
                else
                    aColor = rStyleSettings.GetWindowTextColor();
            }
        }
    }
@@ -91,7 +94,10 @@ Color GetFillColor(Color const& rColor, DrawModeFlags nDrawMode,
            }
            else if (nDrawMode & DrawModeFlags::SettingsFill)
            {
                aColor = rStyleSettings.GetWindowColor();
                if (nDrawMode & DrawModeFlags::SettingsForSelection)
                    aColor = rStyleSettings.GetHighlightColor();
                else
                    aColor = rStyleSettings.GetWindowColor();
            }
        }
    }
@@ -119,7 +125,10 @@ Color GetHatchColor(Color const& rColor, DrawModeFlags nDrawMode,
    }
    else if (nDrawMode & DrawModeFlags::SettingsLine)
    {
        aColor = rStyleSettings.GetWindowTextColor();
        if (nDrawMode & DrawModeFlags::SettingsForSelection)
            aColor = rStyleSettings.GetHighlightColor();
        else
            aColor = rStyleSettings.GetWindowTextColor();
    }

    return aColor;
@@ -149,7 +158,10 @@ Color GetTextColor(Color const& rColor, DrawModeFlags nDrawMode,
        }
        else if (nDrawMode & DrawModeFlags::SettingsText)
        {
            aColor = rStyleSettings.GetWindowTextColor();
            if (nDrawMode & DrawModeFlags::SettingsForSelection)
                aColor = rStyleSettings.GetHighlightTextColor();
            else
                aColor = rStyleSettings.GetWindowTextColor();
        }
    }

@@ -183,7 +195,10 @@ vcl::Font GetFont(vcl::Font const& rFont, DrawModeFlags nDrawMode,
        }
        else if (nDrawMode & DrawModeFlags::SettingsText)
        {
            aTextColor = rStyleSettings.GetWindowTextColor();
            if (nDrawMode & DrawModeFlags::SettingsForSelection)
                aTextColor = rStyleSettings.GetHighlightTextColor();
            else
                aTextColor = rStyleSettings.GetWindowTextColor();
        }

        aFont.SetColor(aTextColor);
@@ -207,7 +222,10 @@ vcl::Font GetFont(vcl::Font const& rFont, DrawModeFlags nDrawMode,
            }
            else if (nDrawMode & DrawModeFlags::SettingsFill)
            {
                aTextFillColor = rStyleSettings.GetWindowColor();
                if (nDrawMode & DrawModeFlags::SettingsForSelection)
                    aTextFillColor = rStyleSettings.GetHighlightColor();
                else
                    aTextFillColor = rStyleSettings.GetWindowColor();
            }
            else if (nDrawMode & DrawModeFlags::NoFill)
            {