fdo#40594 Fix for chart missing issue in Writer (for docx)

1. Enabled parsing of chart in writer module.
2. While parsing chart is read as ole2shape. Then converted into TextEmbedded object for chart.
3. While exporting postponed chart writing after rpr tag.
4. Generated unique id for each chart.
5. Corrected content type of chart in export.

Change-Id: I6a1ca0c34e03e17cc3dd8a183580132ea7af5c48
Reviewed-on: https://gerrit.libreoffice.org/5976
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx
index 461a1fe..3e7efb0 100644
--- a/oox/source/shape/ShapeContextHandler.cxx
+++ b/oox/source/shape/ShapeContextHandler.cxx
@@ -90,6 +90,31 @@ uno::Reference<xml::sax::XFastContextHandler> ShapeContextHandler::getLockedCanv
    return mxLockedCanvasContext;
}

/*
 * This method creates new ChartGraphicDataContext Object.
 */
uno::Reference<xml::sax::XFastContextHandler> ShapeContextHandler::getChartShapeContext(sal_Int32 nElement)
{
    if (!mxChartShapeContext.is())
    {
        ContextHandler2Helper *rFragmentHandler
                    (new ShapeFragmentHandler(*mxFilterBase, msRelationFragmentPath));
        ShapePtr pMasterShape;

        switch (nElement & 0xffff)
        {
            case XML_chart:
                mpShape.reset(new Shape("com.sun.star.drawing.OLE2Shape" ));
                mxChartShapeContext.set(new ChartGraphicDataContext(*rFragmentHandler, mpShape, true));
                break;
            default:
                break;
        }
    }

    return mxChartShapeContext;
}

uno::Reference<xml::sax::XFastContextHandler>
ShapeContextHandler::getGraphicShapeContext(::sal_Int32 Element )
{
@@ -164,6 +189,9 @@ ShapeContextHandler::getContextHandler()
        case NMSP_dmlLockedCanvas:
            xResult.set(getLockedCanvasContext(mnStartToken));
            break;
        case NMSP_dmlChart:
            xResult.set(getChartShapeContext(mnStartToken));
            break;
        default:
            xResult.set(getGraphicShapeContext(mnStartToken));
            break;
@@ -188,18 +216,21 @@ void SAL_CALL ShapeContextHandler::startFastElement

    mpThemePtr.reset(new Theme());

    if (Element == DGM_TOKEN(relIds) || Element == LC_TOKEN(lockedCanvas))
    if (Element == DGM_TOKEN(relIds) || Element == LC_TOKEN(lockedCanvas) || Element == C_TOKEN(chart) )
    {
        // Parse the theme relation, if available; the diagram won't have colors without it.
        if (!msRelationFragmentPath.isEmpty())
        {
            FragmentHandlerRef rFragmentHandler(new ShapeFragmentHandler(*mxFilterBase, msRelationFragmentPath));
            OUString aThemeFragmentPath = rFragmentHandler->getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "theme" ) );
            uno::Reference<xml::sax::XFastSAXSerializable> xDoc(mxFilterBase->importFragment(aThemeFragmentPath), uno::UNO_QUERY_THROW);
            mxFilterBase->importFragment(new ThemeFragmentHandler(*mxFilterBase, aThemeFragmentPath, *mpThemePtr ), xDoc);
            ShapeFilterBase* pShapeFilterBase(dynamic_cast<ShapeFilterBase*>(mxFilterBase.get()));
            if (pShapeFilterBase)
                pShapeFilterBase->setCurrentTheme(mpThemePtr);
            if(!aThemeFragmentPath.isEmpty())
            {
                uno::Reference<xml::sax::XFastSAXSerializable> xDoc(mxFilterBase->importFragment(aThemeFragmentPath), uno::UNO_QUERY_THROW);
                mxFilterBase->importFragment(new ThemeFragmentHandler(*mxFilterBase, aThemeFragmentPath, *mpThemePtr ), xDoc);
                ShapeFilterBase* pShapeFilterBase(dynamic_cast<ShapeFilterBase*>(mxFilterBase.get()));
                if (pShapeFilterBase)
                    pShapeFilterBase->setCurrentTheme(mpThemePtr);
            }
        }

        createFastChildContext(Element, Attribs);
@@ -353,6 +384,17 @@ ShapeContextHandler::getShape() throw (uno::RuntimeException)
                mxLockedCanvasContext.clear();
            }
        }
        else if (mxChartShapeContext.is())
        {
            basegfx::B2DHomMatrix aMatrix;
            ChartGraphicDataContext* pChartGraphicDataContext = dynamic_cast<ChartGraphicDataContext*>(mxChartShapeContext.get());
            oox::drawingml::ShapePtr pShapePtr( pChartGraphicDataContext->getShape());
            // See SwXTextDocument::createInstance(), ODF import uses the same hack.
            pShapePtr->setServiceName("com.sun.star.drawing.temporaryForXMLImportOLE2Shape");
            pShapePtr->addShape( *mxFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShapePtr->getFillProperties() );
            xResult = pShapePtr->getXShape();
            mxChartShapeContext.clear();
        }
        else if (mpShape.get() != NULL)
        {
            basegfx::B2DHomMatrix aTransformation;
diff --git a/oox/source/shape/ShapeContextHandler.hxx b/oox/source/shape/ShapeContextHandler.hxx
index 2d500ef..a1e8e029 100644
--- a/oox/source/shape/ShapeContextHandler.hxx
+++ b/oox/source/shape/ShapeContextHandler.hxx
@@ -150,6 +150,7 @@ private:
    css::uno::Reference<XFastContextHandler> mxGraphicShapeContext;
    css::uno::Reference<XFastContextHandler> mxDiagramShapeContext;
    css::uno::Reference<XFastContextHandler> mxLockedCanvasContext;
    css::uno::Reference<XFastContextHandler> mxChartShapeContext;

    core::XmlFilterRef mxFilterBase;
    drawingml::ThemePtr mpThemePtr;
@@ -158,6 +159,7 @@ private:
    OUString msRelationFragmentPath;

    css::uno::Reference<XFastContextHandler> getGraphicShapeContext(::sal_Int32 Element);
    css::uno::Reference<XFastContextHandler> getChartShapeContext(::sal_Int32 Element);
    css::uno::Reference<XFastContextHandler> getDrawingShapeContext();
    css::uno::Reference<XFastContextHandler> getDiagramShapeContext();
    css::uno::Reference<XFastContextHandler> getLockedCanvasContext(sal_Int32 nElement);
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 7d060ea..2e01341 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1114,6 +1114,8 @@ void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
    WritePostponedGraphic();

    WritePostponedDiagram();
    //We need to write w:drawing tag after the w:rPr.
    WritePostponedChart();

    // merge the properties _before_ the run text (strictly speaking, just
    // after the start of the run)
@@ -2784,6 +2786,31 @@ bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& r

    if( xChartDoc.is() )
    {
        m_postponedChart = pSdrObj;
        m_postponedChartSize = rSize;
        return true;
    }
    return false;
}

/*
 * Write chart hierarchy in w:drawing after end element of w:rPr tag.
 */
void DocxAttributeOutput::WritePostponedChart()
{
       if(m_postponedChart == NULL)
                return;
       uno::Reference< chart2::XChartDocument > xChartDoc;
       uno::Reference< drawing::XShape > xShape( ((SdrObject*)m_postponedChart)->getUnoShape(), uno::UNO_QUERY );
       if( xShape.is() )
       {
            uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
            if( xPropSet.is() )
                xChartDoc.set( xPropSet->getPropertyValue( "Model" ), uno::UNO_QUERY );
       }

       if( xChartDoc.is() )
       {
        OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
        m_pSerializer->startElementNS( XML_w, XML_drawing,
            FSEND );
@@ -2791,8 +2818,8 @@ bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& r
            XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
            FSEND );

        OString aWidth( OString::number( TwipsToEMU( rSize.Width() ) ) );
        OString aHeight( OString::number( TwipsToEMU( rSize.Height() ) ) );
        OString aWidth( OString::number( TwipsToEMU( m_postponedChartSize.Width() ) ) );
        OString aHeight( OString::number( TwipsToEMU( m_postponedChartSize.Height() ) ) );
        m_pSerializer->singleElementNS( XML_wp, XML_extent,
            XML_cx, aWidth.getStr(),
            XML_cy, aHeight.getStr(),
@@ -2802,15 +2829,13 @@ bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& r
            XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
            FSEND );

        // should get the unique id
        sal_Int32 nID = 1;
        OUString sName("Object 1");
        uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
        if( xNamed.is() )
            sName = xNamed->getName();

        m_pSerializer->singleElementNS( XML_wp, XML_docPr,
            XML_id, I32S( nID ),
            XML_id, I32S( ++m_docPrID ),
            XML_name, USS( sName ),
            FSEND );

@@ -2842,9 +2867,9 @@ bool DocxAttributeOutput::WriteOLEChart( const SdrObject* pSdrObj, const Size& r
        m_pSerializer->endElementNS( XML_wp, XML_inline );
        m_pSerializer->endElementNS( XML_w, XML_drawing );

        return true;
    }
    return false;
        m_postponedChart = NULL;
    return;
}

bool DocxAttributeOutput::WriteOLEMath( const SdrObject*, const SwOLENode& rOLENode, const Size& )
@@ -5639,6 +5664,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
      m_pFootnotesList( new ::docx::FootnotesList() ),
      m_pEndnotesList( new ::docx::FootnotesList() ),
      m_footnoteEndnoteRefTag( 0 ),
      m_docPrID(0),
      m_pSectionInfo( NULL ),
      m_pRedlineData( NULL ),
      m_nRedlineId( 0 ),
@@ -5660,6 +5686,7 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri
      m_postponedGraphic( NULL ),
      m_postponedDiagram( NULL ),
      m_postponedMath( NULL ),
      m_postponedChart( NULL ),
      pendingPlaceholder( NULL ),
      m_postitFieldsMaxId( 0 ),
      m_anchorId( 0 ),
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index f5e17da..01ea79a 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -603,6 +603,7 @@ private:
    void WritePostponedGraphic();
    void WritePostponedMath();
    void WritePostponedDiagram();
    void WritePostponedChart();
    void WriteCommentRanges();

    void StartField_Impl( FieldInfos& rInfos, bool bWriteRun = sal_False );
@@ -626,7 +627,7 @@ private:
    ::docx::FootnotesList *m_pFootnotesList;
    ::docx::FootnotesList *m_pEndnotesList;
    int m_footnoteEndnoteRefTag;

    int m_docPrID;
    boost::scoped_ptr< const WW8_SepInfo > m_pSectionInfo;

    /// Redline data to remember in the text run.
@@ -703,6 +704,8 @@ private:
    };
    std::list< PostponedDiagram >* m_postponedDiagram;
    const SwOLENode* m_postponedMath;
    const SdrObject* m_postponedChart;
    Size m_postponedChartSize;
    const SwField* pendingPlaceholder;
    std::vector< const SwPostItField* > m_postitFields;
    unsigned int m_postitFieldsMaxId;
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 6af8c6b..ff45180 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -316,7 +316,7 @@ OString DocxExport::OutputChart( uno::Reference< frame::XModel >& xModel, sal_In
    aFileName = "word/charts/chart" + OUString::number(nCount) + ".xml";
    ::sax_fastparser::FSHelperPtr pChartFS =
        m_pFilter->openFragmentStreamWithSerializer( aFileName,
            "application/vnd.openxmlformats-officedocument.drawingml.chart" );
            "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" );

    oox::drawingml::ChartExport aChartExport( XML_w, pChartFS, xModel, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
    aChartExport.ExportContent();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index c89fdf2..308a7b2 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1723,6 +1723,25 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape 
            uno::Reference<text::XTextContent> xTxtContent(xShape, uno::UNO_QUERY);
            m_aAnchoredStack.push(xTxtContent);
        }
        else if (xSInfo->supportsService("com.sun.star.drawing.OLE2Shape"))
        {
            // OLE2Shape from oox should be converted to a TextEmbeddedObject for sw.
            m_aTextAppendStack.push(TextAppendContext(uno::Reference<text::XTextAppend>(xShape, uno::UNO_QUERY), uno::Reference<text::XTextCursor>()));
            uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY);
            m_aAnchoredStack.push(xTextContent);
            uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, uno::UNO_QUERY);

            PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();

            m_xEmbedded.set(m_xTextFactory->createInstance("com.sun.star.text.TextEmbeddedObject"), uno::UNO_QUERY_THROW);
            uno::Reference<beans::XPropertySet> xEmbeddedProperties(m_xEmbedded, uno::UNO_QUERY_THROW);
            xEmbeddedProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_EMBEDDED_OBJECT), xShapePropertySet->getPropertyValue(rPropNameSupplier.GetName(PROP_EMBEDDED_OBJECT)));
            xEmbeddedProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_ANCHOR_TYPE), uno::makeAny(text::TextContentAnchorType_AS_CHARACTER));
            // So that the original bitmap-only shape will be replaced by the embedded object.
            m_aAnchoredStack.top().bToRemove = true;
            m_aTextAppendStack.pop();
               appendTextContent(m_xEmbedded, uno::Sequence<beans::PropertyValue>());
        }
        else
        {
            uno::Reference< text::XTextRange > xShapeText( xShape, uno::UNO_QUERY_THROW);
@@ -1783,7 +1802,17 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape 
        SAL_WARN("writerfilter", "Exception when adding shape: " << e.Message);
    }
}

/*
 * Updating chart height and width after reading the actual values from wp:extent
*/
void DomainMapper_Impl::UpdateEmbeddedShapeProps(const uno::Reference< drawing::XShape > xShape)
{
        PropertyNameSupplier& rPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
        uno::Reference<beans::XPropertySet> xEmbeddedProperties(m_xEmbedded, uno::UNO_QUERY_THROW);
        awt::Size aSize = xShape->getSize( );
        xEmbeddedProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_WIDTH), uno::makeAny(sal_Int32(aSize.Width)));
        xEmbeddedProperties->setPropertyValue(rPropNameSupplier.GetName(PROP_HEIGHT), uno::makeAny(sal_Int32(aSize.Height)));
}


void DomainMapper_Impl::PopShapeContext()
@@ -3668,6 +3697,10 @@ void  DomainMapper_Impl::ImportGraphic(writerfilter::Reference< Properties >::Po
    uno::Reference<text::XTextContent> xTextContent
        (m_pGraphicImport->GetGraphicObject());

    // Update the shape properties if it is embedded object.
    if(m_xEmbedded.is()){
        UpdateEmbeddedShapeProps(m_pGraphicImport->GetXShapeObject());
    }
    //insert it into the document at the current cursor position
    OSL_ENSURE( xTextContent.is(), "DomainMapper_Impl::ImportGraphic");
    if( xTextContent.is())
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 0da21a0..f61c9ad 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -299,6 +299,7 @@ private:
    ::com::sun::star::uno::Reference < com::sun::star::uno::XComponentContext >     m_xComponentContext;
    ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > m_xPageStyles;
    ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >               m_xBodyText;
    ::com::sun::star::uno::Reference<text::XTextContent>                            m_xEmbedded;

    TextAppendStack                                                                 m_aTextAppendStack;

@@ -523,6 +524,7 @@ public:

    void PushShapeContext( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape );
    void PopShapeContext();
    void UpdateEmbeddedShapeProps( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape );
    /// Add a pending shape: it's currently inserted into the document, but it should be removed before the import finishes.
    void PushPendingShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape );
    /// Get the first pending shape, if there are any.
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index af55e26..c4b9b43 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -1028,6 +1028,9 @@ uno::Reference<text::XTextContent> GraphicImport::GetGraphicObject()
    return xResult;
}

uno::Reference< ::com::sun::star::drawing::XShape> GraphicImport::GetXShapeObject(){
    return m_xShape;
}


void GraphicImport::ProcessShapeOptions(Value& val)
@@ -1206,6 +1209,7 @@ void GraphicImport::lcl_sprm(Sprm & rSprm)
        case NS_ooxml::LN_pic_pic:
        case NS_ooxml::LN_dgm_relIds:
        case NS_ooxml::LN_lc_lockedCanvas:
        case NS_ooxml::LN_c_chart:
        {
            writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
            if( pProperties.get())
diff --git a/writerfilter/source/dmapper/GraphicImport.hxx b/writerfilter/source/dmapper/GraphicImport.hxx
index 6dba57c..a979512 100644
--- a/writerfilter/source/dmapper/GraphicImport.hxx
+++ b/writerfilter/source/dmapper/GraphicImport.hxx
@@ -84,6 +84,7 @@ public:
    virtual void data(const sal_uInt8* buf, size_t len, writerfilter::Reference<Properties>::Pointer_t ref);

    ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextContent > GetGraphicObject();
    ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape> GetXShapeObject();
    bool    IsGraphic() const;

 private:
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 3f0ed5a..f6a155c 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -27,6 +27,7 @@
  <namespace-alias name="http://schemas.openxmlformats.org/drawingml/2006/picture" alias="picture" id="dmlPicture"/>
  <namespace-alias name="http://schemas.openxmlformats.org/drawingml/2006/diagram" alias="diagram" id="dmlDiagram"/>
  <namespace-alias name="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" alias="lockedCanvas" id="dmlLockedCanvas"/>
  <namespace-alias name="http://schemas.openxmlformats.org/drawingml/2006/chart" alias="chart" id="dmlChart"/>
  <namespace-alias name="urn:schemas-microsoft-com:office:word" alias="vml_wordprocessingDrawing" id="vmlWord"/>
  <namespace-alias name="http://schemas.openxmlformats.org/wordprocessingml/2006/main" alias="wordprocessingml" id="doc"/>
  <namespace-alias name="http://schemas.openxmlformats.org/officeDocument/2006/math" alias="math" id="officeMath"/>
@@ -5169,6 +5170,7 @@
          <ref name="pic"/>
          <ref name="relIds"/>
          <ref name="lockedCanvas"/>
          <ref name="chart"/>
          <element>
            <anyName/>
            <ref name="BUILT_IN_ANY_TYPE"/>
@@ -5196,6 +5198,7 @@
      <element name="pic" tokenid="ooxml:CT_GraphicalObjectData_pic"/>
      <element name="relIds" tokenid="ooxml:CT_GraphicalObjectData_relIds"/>
      <element name="lockedCanvas" tokenid="ooxml:CT_GraphicalObjectData_lockedCanvas"/>
      <element name="chart" tokenid="ooxml:CT_GraphicalObjectData_chart"/>
      <attribute name="uri" tokenid="ooxml:CT_GraphicalObjectData_uri"/>
    </resource>
    <resource name="CT_GraphicalObject" resource="Properties" tag="shape">
@@ -8472,6 +8475,16 @@
          <ref name="CT_GvmlGroupShape"/>
        </element>
      </define>
      <define xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" name="CT_Chart">
        <attribute name="r:id">
          <text/>
        </attribute>
        </define>
      <define name="chart">
        <element xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" name="c:chart">
            <ref name="CT_Chart"/>
        </element>
      </define>
    </grammar>
    <resource name="CT_PictureNonVisual" resource="Properties" tag="shape">
      <element name="cNvPr" tokenid="ooxml:CT_PictureNonVisual_cNvPr"/>
@@ -8501,6 +8514,13 @@
    <resource name="lockedCanvas" resource="Shape" tag="shape">
      <element xmlns:lc="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas" name="lc:lockedCanvas" tokenid="ooxml:lc_lockedCanvas"/>
    </resource>
    <resource xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" name="CT_Chart" resource="Shape" tag="shape">
      <attribute name="r:id" tokenid="ooxml:CT_RelId_chart"/>
    </resource>
    <resource name="chart" resource="Shape" tag="shape">
        <element xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" name="c:chart" tokenid="ooxml:c_chart"/>
    </resource>

  </namespace>
  <namespace name="vml-main" file="vml-main.rng" todo="ignore">
    <start name="shape"/>