[Libreoffice-commits] .: oox/inc oox/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Sep 19 07:04:40 PDT 2012


 oox/inc/oox/vml/vmlshape.hxx        |   19 ++++++++
 oox/inc/oox/vml/vmlshapecontext.hxx |    6 ++
 oox/source/token/properties.txt     |    1 
 oox/source/vml/vmlshape.cxx         |   84 ++++++++++++++++++++++++++++++++++++
 oox/source/vml/vmlshapecontext.cxx  |   30 ++++++++++++
 5 files changed, 138 insertions(+), 2 deletions(-)

New commits:
commit 0423a6741fc08a35b123556f9b10219d090ee42a
Author: Eilidh McAdam <eilidh at lanedo.com>
Date:   Wed Sep 19 10:01:57 2012 +0100

    Import bezier curves from .docx.
    
    A shape element with a path attribute is interpreted as a bezier. We can
    support both curve and line commands by using the correct co-ordinate
    flags when using the UNO interface (omit control points for lines).
    Alternatively, curves may be specified using the to, from, control1 and
    control2 attributes of a curve element.
    
    Note that when setting the PolyPolygonBezier property of the xshape, the
    shape size and position are set too large somehow. The workaround for
    now is manually forcing the pre-calculated shape size and position.
    
    Change-Id: If3563474df357d161a2ed2e7a20856d5aed80a94
    Reviewed-on: https://gerrit.libreoffice.org/649
    Reviewed-by: Miklos Vajna <vmiklos at suse.cz>
    Tested-by: Miklos Vajna <vmiklos at suse.cz>

diff --git a/oox/inc/oox/vml/vmlshape.hxx b/oox/inc/oox/vml/vmlshape.hxx
index 8fab5f7..5bdc2b5 100644
--- a/oox/inc/oox/vml/vmlshape.hxx
+++ b/oox/inc/oox/vml/vmlshape.hxx
@@ -185,6 +185,9 @@ struct ShapeModel
     ::rtl::OUString     maLegacyDiagramPath;///< Legacy Diagram Fragment Path
     ::rtl::OUString     maFrom;             ///< Start point for line shape.
     ::rtl::OUString     maTo;               ///< End point for line shape.
+    ::rtl::OUString     maControl1;         ///< Bezier control point 1
+    ::rtl::OUString     maControl2;         ///< Bezier control point 2
+    ::rtl::OUString     maVmlPath;          ///< VML path for this shape
 
     explicit            ShapeModel();
                         ~ShapeModel();
@@ -334,6 +337,22 @@ protected:
                             const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes,
                             const ::com::sun::star::awt::Rectangle& rShapeRect ) const;
 };
+
+/** Bezier shape object that supports to, from, control1 and control2
+    attribute or path attribute specification */
+class BezierShape : public SimpleShape
+{
+public:
+    explicit             BezierShape( Drawing& rDrawing );
+
+protected:
+    /** Creates the corresponding XShape and inserts it into the passed container. */
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
+                        implConvertAndInsert(
+                            const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes,
+                            const ::com::sun::star::awt::Rectangle& rShapeRect ) const;
+};
+
 // ============================================================================
 
 /** A shape object with custom geometry. */
diff --git a/oox/inc/oox/vml/vmlshapecontext.hxx b/oox/inc/oox/vml/vmlshapecontext.hxx
index 358f8fe..e3d5d89 100644
--- a/oox/inc/oox/vml/vmlshapecontext.hxx
+++ b/oox/inc/oox/vml/vmlshapecontext.hxx
@@ -134,6 +134,12 @@ private:
     void                setFrom( const ::rtl::OUString& rPoints );
     /** Processes the 'to' attribute. */
     void                setTo( const ::rtl::OUString& rPoints );
+    /** Processes the 'control1' attribute. */
+    void                setControl1( const ::rtl::OUString& rPoints );
+    /** Processes the 'control2' attribute. */
+    void                setControl2( const ::rtl::OUString& rPoints );
+    /** Processes the 'path' attribute. */
+    void                setVmlPath( const ::rtl::OUString& rPath );
 
 protected:
     ShapeBase&          mrShape;
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index 5c917e9..8d5ab7d 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -334,6 +334,7 @@ PercentageNumberFormat
 PersistName
 Perspective
 PolyPolygon
+PolyPolygonBezier
 PolygonKind
 Position
 PositionBottom
diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx
index 156730f..0bd3399 100644
--- a/oox/source/vml/vmlshape.cxx
+++ b/oox/source/vml/vmlshape.cxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/awt/XControlModel.hpp>
 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
 #include <com/sun/star/drawing/XShapes.hpp>
 #include <com/sun/star/drawing/XControlShape.hpp>
@@ -553,6 +554,89 @@ Reference<XShape> LineShape::implConvertAndInsert(const Reference<XShapes>& rxSh
 
 // ============================================================================
 
+BezierShape::BezierShape(Drawing& rDrawing)
+    : SimpleShape(rDrawing, "com.sun.star.drawing.OpenBezierShape")
+{
+}
+
+Reference< XShape > BezierShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+    Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
+    Rectangle aCoordSys = getCoordSystem();
+
+    if( (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
+    {
+        const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
+
+        // Bezier paths may consist of one or more sub-paths
+        typedef ::std::vector< ::std::vector< Point > > SubPathList;
+        typedef ::std::vector< ::std::vector< PolygonFlags > > FlagsList;
+        SubPathList aCoordLists;
+        FlagsList aFlagLists;
+        sal_Int32 nIndex = 0;
+
+        // Curve defined by to, from, control1 and control2 attributes
+        if ( maShapeModel.maVmlPath.isEmpty() )
+        {
+            aCoordLists.push_back( ::std::vector< Point >() );
+            aFlagLists.push_back( ::std::vector< PolygonFlags >() );
+
+            // Start point
+            aCoordLists[ 0 ].push_back(
+                Point(ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, true, true ),
+                  ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, false, true ) ) );
+            // Control point 1
+            aCoordLists[ 0 ].push_back(
+                Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, true, true ),
+                      ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, false, true ) ) );
+            // Control point 2
+            aCoordLists[ 0 ].push_back(
+                Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, true, true ),
+                      ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, false, true ) ) );
+            // End point
+            aCoordLists[ 0 ].push_back(
+                Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, true, true ),
+                      ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, false, true ) ) );
+
+            // First and last points are normals, points 2 and 4 are controls
+            aFlagLists[ 0 ].resize( aCoordLists[ 0 ].size(), PolygonFlags_CONTROL );
+            aFlagLists[ 0 ][ 0 ] = PolygonFlags_NORMAL;
+            aFlagLists[ 0 ].back() = PolygonFlags_NORMAL;
+        }
+        // Curve defined by path attribute
+        else
+        {
+            // Parse VML path string and convert to absolute coordinates
+            ConversionHelper::decodeVmlPath( aCoordLists, aFlagLists, maShapeModel.maVmlPath );
+
+            for ( SubPathList::iterator aListIt = aCoordLists.begin(); aListIt != aCoordLists.end(); aListIt++ )
+                for ( ::std::vector< Point >::iterator aPointIt = (*aListIt).begin(); aPointIt != (*aListIt).end(); aPointIt++)
+                {
+                    (*aPointIt) = lclGetAbsPoint( (*aPointIt), rShapeRect, aCoordSys );
+                }
+        }
+
+        PolyPolygonBezierCoords aBezierCoords;
+        aBezierCoords.Coordinates.realloc( aCoordLists.size() );
+        for ( unsigned int i = 0; i < aCoordLists.size(); i++ )
+            aBezierCoords.Coordinates[i] = ContainerHelper::vectorToSequence( aCoordLists[i] );
+
+        aBezierCoords.Flags.realloc( aFlagLists.size() );
+        for ( unsigned int i = 0; i < aFlagLists.size(); i++ )
+            aBezierCoords.Flags[i] = ContainerHelper::vectorToSequence( aFlagLists[i] );
+
+        PropertySet aPropSet( xShape );
+        aPropSet.setProperty( PROP_PolyPolygonBezier, aBezierCoords );
+    }
+
+    // Hacky way of ensuring the shape is correctly sized/positioned
+    xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
+    xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
+    return xShape;
+}
+
+// ============================================================================
+
 CustomShape::CustomShape( Drawing& rDrawing ) :
     SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) )
 {
diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx
index b140f5a..88998d1 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -216,7 +216,10 @@ ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
         case VML_TOKEN( group ):
             return new GroupShapeContext( rParent, rShapes.createShape< GroupShape >(), rAttribs );
         case VML_TOKEN( shape ):
-            return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
+            if (rAttribs.hasAttribute(XML_path))
+                return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
+            else
+                return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
         case VML_TOKEN( rect ):
             return new RectangleShapeContext( rParent, rAttribs, rShapes.createShape< RectangleShape >() );
         case VML_TOKEN( roundrect ):
@@ -227,10 +230,11 @@ ShapeContextBase::ShapeContextBase( ContextHandler2Helper& rParent ) :
             return new ShapeContext( rParent, rShapes.createShape< PolyLineShape >(), rAttribs );
         case VML_TOKEN( line ):
             return new ShapeContext( rParent, rShapes.createShape< LineShape >(), rAttribs );
+        case VML_TOKEN( curve ):
+            return new ShapeContext( rParent, rShapes.createShape< BezierShape >(), rAttribs );
 
         // TODO:
         case VML_TOKEN( arc ):
-        case VML_TOKEN( curve ):
         case VML_TOKEN( diagram ):
         case VML_TOKEN( image ):
             return new ShapeContext( rParent, rShapes.createShape< ComplexShape >(), rAttribs );
@@ -379,6 +383,9 @@ ShapeContext::ShapeContext( ContextHandler2Helper& rParent, ShapeBase& rShape, c
     // line start and end positions
     setFrom(rAttribs.getString(XML_from, OUString()));
     setTo(rAttribs.getString(XML_to, OUString()));
+    setControl1(rAttribs.getString(XML_control1, OUString()));
+    setControl2(rAttribs.getString(XML_control2, OUString()));
+    setVmlPath(rAttribs.getString(XML_path, OUString()));
 }
 
 ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
@@ -409,6 +416,7 @@ void ShapeContext::setPoints( const OUString& rPoints )
 {
     mrShapeModel.maPoints.clear();
     sal_Int32 nIndex = 0;
+
     while( nIndex >= 0 )
     {
         sal_Int32 nX = rPoints.getToken( 0, ',', nIndex ).toInt32();
@@ -429,6 +437,24 @@ void ShapeContext::setTo( const OUString& rPoints )
         mrShapeModel.maTo = rPoints;
 }
 
+void ShapeContext::setControl1( const OUString& rPoints )
+{
+    if (!rPoints.isEmpty())
+        mrShapeModel.maControl1 = rPoints;
+}
+
+void ShapeContext::setControl2( const OUString& rPoints )
+{
+    if (!rPoints.isEmpty())
+        mrShapeModel.maControl2 = rPoints;
+}
+void ShapeContext::setVmlPath( const OUString& rPath )
+{
+    if (!rPath.isEmpty())
+        mrShapeModel.maVmlPath = rPath;
+}
+
+
 // ============================================================================
 
 GroupShapeContext::GroupShapeContext( ContextHandler2Helper& rParent, GroupShape& rShape, const AttributeList& rAttribs ) :


More information about the Libreoffice-commits mailing list