diff options
-rw-r--r-- | oox/inc/oox/vml/vmlshape.hxx | 19 | ||||
-rw-r--r-- | oox/inc/oox/vml/vmlshapecontext.hxx | 6 | ||||
-rw-r--r-- | oox/source/token/properties.txt | 1 | ||||
-rw-r--r-- | oox/source/vml/vmlshape.cxx | 84 | ||||
-rw-r--r-- | oox/source/vml/vmlshapecontext.cxx | 30 |
5 files changed, 138 insertions, 2 deletions
diff --git a/oox/inc/oox/vml/vmlshape.hxx b/oox/inc/oox/vml/vmlshape.hxx index 8fab5f7ec92d..5bdc2b51e486 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 358f8fedd706..e3d5d8963eb2 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 5c917e9d7f29..8d5ab7d5991b 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 156730f67d01..0bd3399f3c6f 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 b140f5a363f3..88998d1b06a4 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 ) : |