basegfx/source/tools/gradienttools.cxx             |   32 ++++++
 include/basegfx/utils/gradienttools.hxx            |    9 +
 include/oox/helper/modelobjecthelper.hxx           |    3 
 oox/source/drawingml/fillproperties.cxx            |  110 ++++++++++++++++++++-
 oox/source/drawingml/shapepropertymap.cxx          |   16 ++-
 oox/source/helper/modelobjecthelper.cxx            |   12 ++
 svx/source/sdr/primitive2d/sdrattributecreator.cxx |   21 +---
 7 files changed, 184 insertions(+), 19 deletions(-)

New commits:
commit ce86e5b4a8d54eb55fdde7756ad6fde6e6967d55
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Wed Mar 29 11:04:27 2023 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Sun Apr 2 13:19:27 2023 +0200

    MCGR: 1st additions to OOXML MCGR import
    
    This change provides 1st changes to get Gradients with
    muti color stops imported from MSO in the oox import
    filter. It supports currently multiple ColorStops and
    transparency. Also 'border'(s) should work, but
    -remember- this is work in progress.
    
    Since it is work in progress it is currently and
    temporaily secured by ENV VAR "MCGR_TEST=0", so when
    not using this the master version will not be touched
    at all.
    
    The number defines various ColorStop tests, 0 for none,
    but some changes are active, e.g. MSO import. You may
    try 1 or 16 to see all your Gradients hard replaced by
    something using that feature.
    I will take care fo cleaning this up again when the
    feature progresses/gets complete.
    
    Change-Id: I92e10d8cd5150733741a6def20a542abf97bd903
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149682
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/basegfx/source/tools/gradienttools.cxx 
b/basegfx/source/tools/gradienttools.cxx
index a98eeddf641c..49cf831da262 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -264,6 +264,38 @@ namespace basegfx
 
     namespace utils
     {
+        /* Tooling method to check if a ColorStop vector is defined
+           by a single color. It returns true if this is the case.
+           If true is returned, rSingleColor contains that single
+           color for convenience.
+           NOTE: If no ColorStop is defined, a fallback to BColor-default
+                 (which is black) and true will be returned
+        */
+        bool isSingleColor(const ColorStops& rColorStops, BColor& rSingleColor)
+        {
+            if (rColorStops.empty())
+            {
+                rSingleColor = BColor();
+                return true;
+            }
+
+            if (1 == rColorStops.size())
+            {
+                rSingleColor = rColorStops.front().getStopColor();
+                return true;
+            }
+
+            rSingleColor = rColorStops.front().getStopColor();
+
+            for (auto const& rCandidate : rColorStops)
+            {
+                if (rCandidate.getStopColor() != rSingleColor)
+                    return false;
+            }
+
+            return true;
+        }
+
         /* Tooling method to reverse ColorStops, including offsets.
            When also mirroring offsets a valid sort keeps valid.
         */
diff --git a/include/basegfx/utils/gradienttools.hxx 
b/include/basegfx/utils/gradienttools.hxx
index 33f87717528b..c7123bc81db3 100644
--- a/include/basegfx/utils/gradienttools.hxx
+++ b/include/basegfx/utils/gradienttools.hxx
@@ -196,6 +196,15 @@ namespace basegfx
 
     namespace utils
     {
+        /* Tooling method to check if a ColorStop vector is defined
+           by a single color. It returns true if this is the case.
+           If true is returned, rSingleColor contains that single
+           color for convenience.
+           NOTE: If no ColorStop is defined, a fallback to BColor-default
+                 (which is black) and true will be returned
+        */
+        BASEGFX_DLLPUBLIC bool isSingleColor(const ColorStops& rColorStops, 
BColor& rSingleColor);
+
         /* Tooling method to reverse ColorStops, including offsets.
            When also mirroring offsets a valid sort keeps valid.
         */
diff --git a/include/oox/helper/modelobjecthelper.hxx 
b/include/oox/helper/modelobjecthelper.hxx
index 9aba2538fdc4..6d4b1fea1925 100644
--- a/include/oox/helper/modelobjecthelper.hxx
+++ b/include/oox/helper/modelobjecthelper.hxx
@@ -28,6 +28,7 @@
 
 namespace com::sun::star {
     namespace awt { struct Gradient;
+                    struct Gradient2;
                     class XBitmap; }
     namespace graphic { class XGraphic; }
     namespace container { class XNameContainer; }
@@ -102,8 +103,10 @@ public:
 
     /** Inserts a new named fill gradient, returns the gradient name, based on
         an internal constant name with a new unused index appended. */
+    OUString     insertFillGradient( const css::awt::Gradient2& rGradient );
     OUString     insertFillGradient( const css::awt::Gradient& rGradient );
 
+    OUString     insertTransGrandient( const css::awt::Gradient2& rGradient );
     OUString     insertTransGrandient( const css::awt::Gradient& rGradient );
 
     OUString     insertFillHatch( const css::drawing::Hatch& rHatch );
diff --git a/oox/source/drawingml/fillproperties.cxx 
b/oox/source/drawingml/fillproperties.cxx
index 98a048d7f8ac..fd3ba99b2c3f 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -27,9 +27,10 @@
 #include <vcl/BitmapFilter.hxx>
 #include <vcl/BitmapMonochromeFilter.hxx>
 #include <docmodel/uno/UnoThemeColor.hxx>
+#include <basegfx/utils/gradienttools.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
 #include <com/sun/star/text/GraphicCrop.hpp>
 #include <com/sun/star/awt/Size.hpp>
 #include <com/sun/star/drawing/BitmapMode.hpp>
@@ -479,7 +480,112 @@ void FillProperties::pushToPropMap(ShapePropertyMap& 
rPropMap, const GraphicHelp
 
         case XML_gradFill:
             // do not create gradient struct if property is not supported...
-            if( rPropMap.supportsProperty( ShapeProperty::FillGradient ) )
+            static bool bMCGR(nullptr != std::getenv("MCGR_TEST"));
+
+            if( bMCGR && rPropMap.supportsProperty( 
ShapeProperty::FillGradient ) )
+            {
+                // use awt::Gradient2, prepare ColorStops
+                awt::Gradient2 aGradient;
+                basegfx::ColorStops aColorStops;
+                basegfx::ColorStops aTransparencyStops;
+                bool bContainsTransparency(false);
+
+                // set defaults
+                aGradient.Angle = 900;
+                aGradient.StartIntensity = 100;
+                aGradient.EndIntensity = 100;
+                aGradient.Style = awt::GradientStyle_LINEAR;
+
+                // convert to ColorStops, check for contained transparency
+                for (const auto& rCandidate : maGradientProps.maGradientStops)
+                {
+                    const ::Color 
aColor(rCandidate.second.getColor(rGraphicHelper, nPhClr));
+                    aColorStops.emplace_back(rCandidate.first, 
aColor.getBColor());
+                    bContainsTransparency = bContainsTransparency || 
rCandidate.second.hasTransparency();
+                }
+
+                // if we have transparency, convert to ColorStops
+                if (bContainsTransparency)
+                {
+                    for (const auto& rCandidate : 
maGradientProps.maGradientStops)
+                    {
+                        const double 
fTrans(rCandidate.second.getTransparency() * (1.0/100.0));
+                        aTransparencyStops.emplace_back(rCandidate.first, 
basegfx::BColor(fTrans, fTrans, fTrans));
+                    }
+                }
+
+                // "rotate with shape" set to false -> do not rotate
+                if (!maGradientProps.moRotateWithShape.value_or(true))
+                {
+                    nShapeRotation = 0;
+                }
+
+                if (maGradientProps.moGradientPath.has_value())
+                {
+                    IntegerRectangle2D aFillToRect = 
maGradientProps.moFillToRect.value_or( IntegerRectangle2D( 0, 0, MAX_PERCENT, 
MAX_PERCENT ) );
+                    sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - 
aFillToRect.X2) / 2;
+                    aGradient.XOffset = getLimitedValue<sal_Int16, sal_Int32>(
+                        nCenterX / PER_PERCENT, 0, 100);
+                    sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - 
aFillToRect.Y2) / 2;
+                    aGradient.YOffset = getLimitedValue<sal_Int16, sal_Int32>(
+                        nCenterY / PER_PERCENT, 0, 100);
+
+                    if( maGradientProps.moGradientPath.value() == XML_circle )
+                    {
+                        // Style should be radial at least when the horizontal 
center is at 50%.
+                        // Otherwise import as a linear gradient, because it 
is the most similar to the MSO radial style.
+                        // aGradient.Style = awt::GradientStyle_LINEAR;
+                        if( aGradient.XOffset == 100 && aGradient.YOffset == 
100 )
+                            aGradient.Angle = 450;
+                        else if( aGradient.XOffset == 0 && aGradient.YOffset 
== 100 )
+                            aGradient.Angle = 3150;
+                        else if( aGradient.XOffset == 100 && aGradient.YOffset 
== 0 )
+                            aGradient.Angle = 1350;
+                        else if( aGradient.XOffset == 0 && aGradient.YOffset 
== 0 )
+                            aGradient.Angle = 2250;
+                        else
+                            aGradient.Style = awt::GradientStyle_RADIAL;
+                    }
+                    else
+                    {
+                        aGradient.Style = awt::GradientStyle_RECT;
+                    }
+
+                    basegfx::utils::reverseColorStops(aColorStops);
+                    basegfx::utils::reverseColorStops(aTransparencyStops);
+                }
+                else if (!maGradientProps.maGradientStops.empty())
+                {
+                    // aGradient.Style = awt::GradientStyle_LINEAR;
+                    sal_Int32 nShadeAngle = 
maGradientProps.moShadeAngle.value_or( 0 );
+                    // Adjust for flips
+                    if ( bFlipH )
+                        nShadeAngle = 180*60000 - nShadeAngle;
+                    if ( bFlipV )
+                        nShadeAngle = -nShadeAngle;
+                    const sal_Int32 nDmlAngle = nShadeAngle + nShapeRotation;
+                    // convert DrawingML angle (in 1/60000 degrees) to API 
angle (in 1/10 degrees)
+                    aGradient.Angle = static_cast< sal_Int16 >( (8100 - 
(nDmlAngle / (PER_DEGREE / 10))) % 3600 );
+                }
+
+                // set ColorStops using UNO API
+                
basegfx::utils::fillColorStopSequenceFromColorStops(aGradient.ColorStops, 
aColorStops);
+
+                // push gradient or named gradient to property map
+                if (rPropMap.setProperty(ShapeProperty::FillGradient, 
aGradient))
+                {
+                    eFillStyle = FillStyle_GRADIENT;
+                }
+
+                // push gradient transparency to property map if it exists
+                if (!aTransparencyStops.empty())
+                {
+                    
basegfx::utils::fillColorStopSequenceFromColorStops(aGradient.ColorStops, 
aTransparencyStops);
+                    rPropMap.setProperty(ShapeProperty::GradientTransparency, 
aGradient);
+                }
+            }
+
+            if( !bMCGR && rPropMap.supportsProperty( 
ShapeProperty::FillGradient ) )
             {
                 sal_Int32 nEndTrans     = 0;
                 sal_Int32 nStartTrans   = 0;
diff --git a/oox/source/drawingml/shapepropertymap.cxx 
b/oox/source/drawingml/shapepropertymap.cxx
index 57014b4780a6..253b9259f7aa 100644
--- a/oox/source/drawingml/shapepropertymap.cxx
+++ b/oox/source/drawingml/shapepropertymap.cxx
@@ -19,7 +19,7 @@
 
 #include <oox/drawingml/shapepropertymap.hxx>
 
-#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
 #include <com/sun/star/beans/NamedValue.hpp>
 #include <com/sun/star/drawing/LineDash.hpp>
 #include <com/sun/star/drawing/Hatch.hpp>
@@ -166,7 +166,12 @@ bool ShapePropertyMap::setFillGradient( sal_Int32 nPropId, 
const Any& rValue )
         return setAnyProperty( nPropId, rValue );
 
     // create named gradient and push its name
-    if( rValue.has< awt::Gradient >() )
+    if( rValue.has< awt::Gradient2 >() )
+    {
+        OUString aGradientName = mrModelObjHelper.insertFillGradient( 
rValue.get< awt::Gradient2 >() );
+        return !aGradientName.isEmpty() && setProperty( nPropId, aGradientName 
);
+    }
+    else if( rValue.has< awt::Gradient >() )
     {
         OUString aGradientName = mrModelObjHelper.insertFillGradient( 
rValue.get< awt::Gradient >() );
         return !aGradientName.isEmpty() && setProperty( nPropId, aGradientName 
);
@@ -194,7 +199,12 @@ bool ShapePropertyMap::setFillHatch( sal_Int32 nPropId, 
const Any& rValue )
 bool ShapePropertyMap::setGradientTrans( sal_Int32 nPropId, const Any& rValue )
 {
     // create named gradient and push its name
-    if( rValue.has< awt::Gradient >() )
+    if( rValue.has< awt::Gradient2 >() )
+    {
+        OUString aGradientName = mrModelObjHelper.insertTransGrandient( 
rValue.get< awt::Gradient2 >() );
+        return !aGradientName.isEmpty()  && setProperty( nPropId, 
aGradientName );
+    }
+    else if( rValue.has< awt::Gradient >() )
     {
         OUString aGradientName = mrModelObjHelper.insertTransGrandient( 
rValue.get< awt::Gradient >() );
         return !aGradientName.isEmpty()  && setProperty( nPropId, 
aGradientName );
diff --git a/oox/source/helper/modelobjecthelper.cxx 
b/oox/source/helper/modelobjecthelper.cxx
index b68af8084fe0..e721d2ef3413 100644
--- a/oox/source/helper/modelobjecthelper.cxx
+++ b/oox/source/helper/modelobjecthelper.cxx
@@ -19,7 +19,7 @@
 
 #include <oox/helper/modelobjecthelper.hxx>
 
-#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/awt/Gradient2.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
 #include <com/sun/star/drawing/LineDash.hpp>
 #include <com/sun/star/drawing/Hatch.hpp>
@@ -123,11 +123,21 @@ OUString ModelObjectHelper::insertLineDash( const 
LineDash& rDash )
     return maDashContainer.insertObject( gaDashNameBase, Any( rDash ), true );
 }
 
+OUString ModelObjectHelper::insertFillGradient( const awt::Gradient2& 
rGradient )
+{
+    return maGradientContainer.insertObject( gaGradientNameBase, Any( 
rGradient ), true );
+}
+
 OUString ModelObjectHelper::insertFillGradient( const awt::Gradient& rGradient 
)
 {
     return maGradientContainer.insertObject( gaGradientNameBase, Any( 
rGradient ), true );
 }
 
+OUString ModelObjectHelper::insertTransGrandient( const awt::Gradient2& 
rGradient )
+{
+    return maTransGradContainer.insertObject( gaTransGradNameBase, Any( 
rGradient ), true );
+}
+
 OUString ModelObjectHelper::insertTransGrandient( const awt::Gradient& 
rGradient )
 {
     return maTransGradContainer.insertObject( gaTransGradNameBase, Any( 
rGradient ), true );
diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx 
b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
index a7670606adff..813c9884bc9b 100644
--- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx
+++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
@@ -444,9 +444,9 @@ namespace drawinglayer::primitive2d
                         && pGradientItem->IsEnabled())
                     {
                         const XGradient& rGradient = 
pGradientItem->GetGradientValue();
-                        const sal_uInt8 
nStartLuminance(Color(rGradient.GetColorStops().front().getStopColor()).GetLuminance());
-                        const sal_uInt8 
nEndLuminance(Color(rGradient.GetColorStops().back().getStopColor()).GetLuminance());
-                        const bool bCompletelyTransparent(0xff == 
nStartLuminance && 0xff == nEndLuminance);
+                        basegfx::BColor aSingleColor;
+                        const bool 
bSingleColor(basegfx::utils::isSingleColor(rGradient.GetColorStops(), 
aSingleColor));
+                        const bool bCompletelyTransparent(bSingleColor && 
basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
 
                         if(bCompletelyTransparent)
                         {
@@ -921,10 +921,10 @@ namespace drawinglayer::primitive2d
             {
                 // test if float transparence is completely transparent
                 const XGradient& rGradient = pGradientItem->GetGradientValue();
-                const sal_uInt8 
nStartLuminance(Color(rGradient.GetColorStops().front().getStopColor()).GetLuminance());
-                const sal_uInt8 
nEndLuminance(Color(rGradient.GetColorStops().back().getStopColor()).GetLuminance());
-                const bool bCompletelyTransparent(0xff == nStartLuminance && 
0xff == nEndLuminance);
-                const bool bNotTransparent(0x00 == nStartLuminance && 0x00 == 
nEndLuminance);
+                basegfx::BColor aSingleColor;
+                const bool 
bSingleColor(basegfx::utils::isSingleColor(rGradient.GetColorStops(), 
aSingleColor));
+                const bool bCompletelyTransparent(bSingleColor && 
basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
+                const bool bNotTransparent(bSingleColor && 
basegfx::fTools::equalZero(aSingleColor.luminance()));
 
                 // create nothing when completely transparent: This case is 
already checked for the
                 // normal fill attributes, XFILL_NONE will be used.
@@ -932,18 +932,13 @@ namespace drawinglayer::primitive2d
                 // Both cases are optimizations, always creating 
FillGradientAttribute will work, too
                 if(!bNotTransparent && !bCompletelyTransparent)
                 {
-                    const double fStartLum(nStartLuminance / 255.0);
-                    const double fEndLum(nEndLuminance / 255.0);
-
                     return attribute::FillGradientAttribute(
                         
XGradientStyleToGradientStyle(rGradient.GetGradientStyle()),
                         static_cast<double>(rGradient.GetBorder()) * 0.01,
                         static_cast<double>(rGradient.GetXOffset()) * 0.01,
                         static_cast<double>(rGradient.GetYOffset()) * 0.01,
                         toRadians(rGradient.GetAngle()),
-                        basegfx::utils::createColorStopsFromStartEndColor(
-                            basegfx::BColor(fStartLum, fStartLum, fStartLum),
-                            basegfx::BColor(fEndLum, fEndLum, fEndLum)));
+                        rGradient.GetColorStops());
                 }
             }
 
  • [Libreoffice-commits] core.git:... Armin Le Grand (allotropia) (via logerrit)

Reply via email to