summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
Diffstat (limited to 'oox')
-rw-r--r--oox/inc/oox/vml/vmlshape.hxx19
-rw-r--r--oox/inc/oox/vml/vmlshapecontext.hxx6
-rw-r--r--oox/source/token/properties.txt1
-rw-r--r--oox/source/vml/vmlshape.cxx84
-rw-r--r--oox/source/vml/vmlshapecontext.cxx30
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 ) :