[Libreoffice-commits] core.git: 3 commits - include/oox oox/source sw/qa vcl/unx

Jacobo Aragunde Pérez jaragunde at igalia.com
Tue Feb 4 17:11:01 PST 2014


 include/oox/export/drawingml.hxx                              |    5 
 oox/source/drawingml/color.cxx                                |    9 
 oox/source/drawingml/shape.cxx                                |   41 ++
 oox/source/export/drawingml.cxx                               |  137 ++++++++--
 sw/qa/extras/ooxmlexport/data/gradient-fill-preservation.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx                      |   39 ++
 vcl/unx/gtk/a11y/atkwrapper.cxx                               |    5 
 7 files changed, 216 insertions(+), 20 deletions(-)

New commits:
commit b8a863a219ae3efaa050e5f213d5ae3a91459c06
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue Feb 4 18:55:21 2014 +0100

    drawingML: do not write empty schemeClr tags
    
    Change-Id: I8508f00f6af218605d1d43d3efcefbf545387ab8

diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 9fc0ec9..f011190 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -181,6 +181,10 @@ void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
 
 void DrawingML::WriteColor( OUString sColorSchemeName, Sequence< PropertyValue > aTransformations )
 {
+    // prevent writing a tag with empty val attribute
+    if( sColorSchemeName.isEmpty() )
+        return;
+
     if( aTransformations.hasElements() )
     {
         mpFS->startElementNS( XML_a, XML_schemeClr,
@@ -219,17 +223,14 @@ void DrawingML::WriteSolidFill( OUString sSchemeName, sal_Int32 nAlpha )
     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
     if( nAlpha < MAX_PERCENT )
     {
-        mpFS->startElementNS( XML_a, XML_schemeClr, XML_val,
-            OUStringToOString( sSchemeName, RTL_TEXTENCODING_ASCII_US ).getStr(),
-            FSEND );
-        mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
-        mpFS->endElementNS( XML_a, XML_schemeClr );
+        Sequence< PropertyValue > aTransformations(1);
+        aTransformations[0].Name = "alpha";
+        aTransformations[0].Value <<= nAlpha;
+        WriteColor( sSchemeName, aTransformations );
     }
     else
     {
-        mpFS->singleElementNS( XML_a, XML_schemeClr, XML_val,
-            OUStringToOString( sSchemeName, RTL_TEXTENCODING_ASCII_US ).getStr(),
-            FSEND );
+        WriteColor( sSchemeName );
     }
     mpFS->endElementNS( XML_a, XML_solidFill );
 }
commit 2fcf3a871c94feeca11619ef5c8c0466ce61eb74
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Fri Jan 31 14:02:12 2014 +0100

    ooxml: preserve gradient shape fill
    
    LibreOffice is unable to properly import the custom gradient fills
    defined in ooxml documents. To prevent data loss, we save the
    original gradient fill definition in the shape interopgrabbag and we
    write it back to the document on export.
    
    In case the user has changed the fill properties of a shape, the
    original fill will be discarded in favor of the new fill.
    
    We have added a new ooxmlexport unit test to test this feature.
    
    We have also added some missing transformations to the methods
    getColorTransformationName and getColorTransformationToken in Color
    class, and refactored some code in class DrawingML to the method
    WriteColor( OUString, Sequence ).
    
    Change-Id: Ie71f89eaa20313561aa9180ea33b76f3fb5e5df6

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index f2ec9e7..7a07f5e 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -24,6 +24,7 @@
 #include <sax/fshelper.hxx>
 #include <rtl/strbuf.hxx>
 #include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/Gradient.hpp>
 #include <com/sun/star/uno/XReference.hpp>
 #include <tools/poly.hxx>
 #include <filter/msfilter/escherex.hxx>
@@ -106,6 +107,8 @@ protected:
     const char* GetComponentDir();
     const char* GetRelationCompPrefix();
 
+    bool EqualGradients( ::com::sun::star::awt::Gradient aGradient1, ::com::sun::star::awt::Gradient aGradient2 );
+
 public:
     DrawingML( ::sax_fastparser::FSHelperPtr pFS, ::oox::core::XmlFilterBase* pFB = NULL, DocumentType eDocumentType = DOCUMENT_PPTX, DMLTextExport* pTextExport = 0 )
         : meDocumentType( eDocumentType ), mpTextExport(pTextExport), mpFS( pFS ), mpFB( pFB ) {}
@@ -117,6 +120,8 @@ public:
     OUString WriteImage( const Graphic &rGraphic );
 
     void WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha = MAX_PERCENT );
+    void WriteColor( OUString sColorSchemeName, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aTransformations );
+    void WriteColorTransformations( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aTransformations );
     void WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor );
     void WriteLineArrow( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, sal_Bool bLineStart );
     void WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID );
diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx
index 4a87827..84dbd35 100644
--- a/oox/source/drawingml/color.cxx
+++ b/oox/source/drawingml/color.cxx
@@ -358,6 +358,9 @@ OUString Color::getColorTransformationName( sal_Int32 nElement )
         case XML_blue:      return OUString( "blue" );
         case XML_blueMod:   return OUString( "blueMod" );
         case XML_blueOff:   return OUString( "blueOff" );
+        case XML_alpha:     return OUString( "alpha" );
+        case XML_alphaMod:  return OUString( "alphaMod" );
+        case XML_alphaOff:  return OUString( "alphaOff" );
         case XML_hue:       return OUString( "hue" );
         case XML_hueMod:    return OUString( "hueMod" );
         case XML_hueOff:    return OUString( "hueOff" );
@@ -399,6 +402,12 @@ sal_Int32 Color::getColorTransformationToken( OUString sName )
         return XML_blueMod;
     else if( sName == "blueOff" )
         return XML_blueOff;
+    else if( sName == "alpha" )
+        return XML_alpha;
+    else if( sName == "alphaMod" )
+        return XML_alphaMod;
+    else if( sName == "alphaOff" )
+        return XML_alphaOff;
     else if( sName == "hue" )
         return XML_hue;
     else if( sName == "hueMod" )
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 3259f72..99940ab 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -799,6 +799,47 @@ Reference< XShape > Shape::createAndInsert(
                 PUT_PROP( aProperties, nSize - 1, "SpPrLnSolidFillSchemeClr", sLnColorFillScheme );
             }
             putPropertiesToGrabBag( aProperties );
+
+            // Store original gradient fill of the shape to InteropGrabBag
+            // LibreOffice doesn't support all the kinds of gradient so we save its complete definition
+            if( aShapeProps.hasProperty( PROP_FillGradient ) )
+            {
+                Sequence< PropertyValue > aGradientStops( aFillProperties.maGradientProps.maGradientStops.size() );
+                ::std::map< double, Color >::iterator aIt = aFillProperties.maGradientProps.maGradientStops.begin();
+                for( sal_uInt32 i = 0; i < aFillProperties.maGradientProps.maGradientStops.size(); ++i )
+                { // for each stop in the gradient definition:
+
+                    // save position
+                    Sequence< PropertyValue > aGradientStop( 3 );
+                    PUT_PROP( aGradientStop, 0, "Pos", aIt->first );
+
+                    OUString sStopColorScheme = aIt->second.getSchemeName();
+                    if( sStopColorScheme.isEmpty() )
+                    {
+                        // save RGB color
+                        PUT_PROP( aGradientStop, 1, "RgbClr", aIt->second.getColor( rGraphicHelper, nFillPhClr ) );
+                        // in the case of a RGB color, transformations are already applied to
+                        // the color with the exception of alpha transformations. We only need
+                        // to keep the transparency value to calculate the alpha value later.
+                        if( aIt->second.hasTransparency() )
+                        {
+                            PUT_PROP( aGradientStop, 2, "Transparency", aIt->second.getTransparency() );
+                        }
+                    }
+                    else
+                    {
+                        // save color with scheme name
+                        PUT_PROP( aGradientStop, 1, "SchemeClr", sStopColorScheme );
+                        // save all color transformations
+                        PUT_PROP( aGradientStop, 2, "Transformations", aIt->second.getTransformations() );
+                    }
+
+                    PUT_PROP( aGradientStops, i, OUString::number( i ), aGradientStop );
+                    ++aIt;
+                }
+                putPropertyToGrabBag( "GradFillDefinition", Any( aGradientStops ) );
+                putPropertyToGrabBag( "OriginalGradFill", Any( aShapeProps[PROP_FillGradient] ) );
+            }
         }
 
         // These can have a custom geometry, so position should be set here,
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 3db4c04..9fc0ec9 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -179,6 +179,34 @@ void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
     }
 }
 
+void DrawingML::WriteColor( OUString sColorSchemeName, Sequence< PropertyValue > aTransformations )
+{
+    if( aTransformations.hasElements() )
+    {
+        mpFS->startElementNS( XML_a, XML_schemeClr,
+                              XML_val, USS( sColorSchemeName ),
+                              FSEND );
+        WriteColorTransformations( aTransformations );
+        mpFS->endElementNS( XML_a, XML_schemeClr );
+    }
+    else
+        mpFS->singleElementNS( XML_a, XML_schemeClr,
+                              XML_val, USS( sColorSchemeName ),
+                              FSEND );
+}
+
+void DrawingML::WriteColorTransformations( Sequence< PropertyValue > aTransformations )
+{
+    for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
+    {
+        sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
+        sal_Int32 nValue; aTransformations[i].Value >>= nValue;
+
+        if( nToken != XML_TOKEN_INVALID )
+            mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
+    }
+}
+
 void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
 {
     mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
@@ -283,14 +311,93 @@ sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensi
         | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
 }
 
+bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
+{
+    return aGradient1.Style == aGradient2.Style &&
+            aGradient1.StartColor == aGradient2.StartColor &&
+            aGradient1.EndColor == aGradient2.EndColor &&
+            aGradient1.Angle == aGradient2.Angle &&
+            aGradient1.Border == aGradient2.Border &&
+            aGradient1.XOffset == aGradient2.XOffset &&
+            aGradient1.YOffset == aGradient2.YOffset &&
+            aGradient1.StartIntensity == aGradient2.StartIntensity &&
+            aGradient1.EndIntensity == aGradient2.EndIntensity &&
+            aGradient1.StepCount == aGradient2.StepCount;
+}
+
 void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
 {
     awt::Gradient aGradient;
     if( GETA( FillGradient ) ) {
         aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
 
+        // get InteropGrabBag and search the relevant attributes
+        awt::Gradient aOriginalGradient;
+        Sequence< PropertyValue > aGradientStops;
+        if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
+        {
+            Sequence< PropertyValue > aGrabBag;
+            mAny >>= aGrabBag;
+            for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
+                if( aGrabBag[i].Name == "GradFillDefinition" )
+                    aGrabBag[i].Value >>= aGradientStops;
+                else if( aGrabBag[i].Name == "OriginalGradFill" )
+                    aGrabBag[i].Value >>= aOriginalGradient;
+        }
+
         mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
 
+        // check if an ooxml gradient had been imported and if the user has modified it
+        if( aGradientStops.hasElements() && EqualGradients( aOriginalGradient, aGradient ) )
+        {
+            // write back the original gradient
+            mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
+
+            // get original stops and write them
+            for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
+            {
+                Sequence< PropertyValue > aGradientStop;
+                aGradientStops[i].Value >>= aGradientStop;
+
+                // get values
+                OUString sSchemeClr;
+                double nPos = 0;
+                sal_Int16 nTransparency = 0;
+                sal_Int32 nRgbClr = 0;
+                Sequence< PropertyValue > aTransformations;
+                for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
+                    if( aGradientStop[j].Name == "SchemeClr" )
+                        aGradientStop[j].Value >>= sSchemeClr;
+                    else if( aGradientStop[j].Name == "RgbClr" )
+                        aGradientStop[j].Value >>= nRgbClr;
+                    else if( aGradientStop[j].Name == "Pos" )
+                        aGradientStop[j].Value >>= nPos;
+                    else if( aGradientStop[j].Name == "Transparency" )
+                        aGradientStop[j].Value >>= nTransparency;
+                    else if( aGradientStop[j].Name == "Transformations" )
+                        aGradientStop[j].Value >>= aTransformations;
+
+                // write stop
+                mpFS->startElementNS( XML_a, XML_gs,
+                                      XML_pos, OString::number( nPos * 100000.0 ).getStr(),
+                                      FSEND );
+                if( sSchemeClr.isEmpty() )
+                {
+                    // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
+                    sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
+                    WriteColor( nRgbClr, nAlpha );
+                }
+                else
+                    WriteColor( sSchemeClr, aTransformations );
+                mpFS->endElementNS( XML_a, XML_gs );
+            }
+            mpFS->endElementNS( XML_a, XML_gsLst );
+
+            mpFS->singleElementNS( XML_a, XML_lin,
+                                   XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
+                                   FSEND );
+        }
+        else
         switch( aGradient.Style ) {
             default:
             case GradientStyle_LINEAR:
@@ -1798,18 +1905,7 @@ void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, Sequence< PropertyValu
             else if( aProperties[i].Name == "Transformations" )
                 aProperties[i].Value >>= aTransformations;
         mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
-        mpFS->startElementNS( XML_a, XML_schemeClr,
-                              XML_val, USS( sSchemeClr ),
-                              FSEND );
-        for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
-        {
-            sal_Int32 nValue;
-            aTransformations[i].Value >>= nValue;
-            mpFS->singleElementNS( XML_a, Color::getColorTransformationToken( aTransformations[i].Name ),
-                                   XML_val, I32S( nValue ),
-                                   FSEND );
-        }
-        mpFS->endElementNS( XML_a, XML_schemeClr );
+        WriteColor( sSchemeClr, aTransformations );
         mpFS->endElementNS( XML_a, nTokenId );
     }
     else
diff --git a/sw/qa/extras/ooxmlexport/data/gradient-fill-preservation.docx b/sw/qa/extras/ooxmlexport/data/gradient-fill-preservation.docx
new file mode 100644
index 0000000..c9abc10
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/gradient-fill-preservation.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index 239bb02..1c82044 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -2781,6 +2781,45 @@ DECLARE_OOXMLEXPORT_TEST(testDMLCustomGeometry, "dml-customgeometry-cubicbezier.
         CPPUNIT_ASSERT_EQUAL(aCoordinates[i].second, aPairs[i].Second.Value.get<sal_Int32>());
     }
 }
+
+DECLARE_OOXMLEXPORT_TEST(testGradientFillPreservation, "gradient-fill-preservation.docx")
+{
+    xmlDocPtr pXmlDocument = parseExport("word/document.xml");
+    if (!pXmlDocument)
+        return;
+
+    // check rgb colors for every step in the gradient of the first shape
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr",
+            "val", "ffff00");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[2]/a:srgbClr",
+            "val", "ffff33");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[3]/a:srgbClr",
+            "val", "ff0000");
+
+    // check theme colors for every step in the gradient of the second shape
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='0']/a:schemeClr",
+            "val", "accent5");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='50000']/a:schemeClr",
+            "val", "accent1");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='100000']/a:schemeClr",
+            "val", "accent1");
+
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[1]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='50000']/a:srgbClr/a:alpha",
+            "val", "20000");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='50000']/a:schemeClr/a:tint",
+            "val", "44500");
+    assertXPath(pXmlDocument,
+            "/w:document/w:body/w:p/w:r/mc:AlternateContent[2]/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:gradFill/a:gsLst/a:gs[@pos='50000']/a:schemeClr/a:satMod",
+            "val", "160000");
+}
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit c482da1cf440beb1464b9ae1b992e3d0e7a4ab8d
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue Feb 4 19:30:53 2014 +0100

    fdo#39944: fallback for DOCUMENT_* roles in ATK < 2.1.0
    
    Set fallback to DOCUMENT_FRAME role.
    
    Change-Id: Ib83cd2f9881bcdec7b69a7660cf4166a612aaf60

diff --git a/vcl/unx/gtk/a11y/atkwrapper.cxx b/vcl/unx/gtk/a11y/atkwrapper.cxx
index 8b7ea4a..6e48230 100644
--- a/vcl/unx/gtk/a11y/atkwrapper.cxx
+++ b/vcl/unx/gtk/a11y/atkwrapper.cxx
@@ -276,6 +276,11 @@ static AtkRole mapToAtkRole( sal_Int16 nRole )
         , ATK_ROLE_DOCUMENT_PRESENTATION
         , ATK_ROLE_DOCUMENT_SPREADSHEET
         , ATK_ROLE_DOCUMENT_TEXT
+#else
+        //older version should fallback to DOCUMENT_FRAME role
+        , ATK_ROLE_DOCUMENT_FRAME
+        , ATK_ROLE_DOCUMENT_FRAME
+        , ATK_ROLE_DOCUMENT_FRAME
 #endif
     };
 


More information about the Libreoffice-commits mailing list