summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXisco Fauli <anistenis@gmail.com>2015-12-09 01:24:19 +0100
committerArmin Le Grand <Armin.Le.Grand@cib.de>2015-12-22 13:13:04 +0000
commit307421ba933361eaa34c12d23b0f261393ab51d8 (patch)
treebd5588be6f2332fd7f24487d56a7497548b6ecd3
parent3b02908486c52a815b65efe93f41cbc53d5452c3 (diff)
tdf#96181 SVG: Add support for <use> element
Change-Id: Ia95c7e35158f8a4c6a597662524c74e1909983bb Reviewed-on: https://gerrit.libreoffice.org/20483 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
-rw-r--r--filter/source/svg/svgreader.cxx116
-rw-r--r--include/xmloff/xmltoken.hxx1
-rw-r--r--xmloff/source/core/xmltoken.cxx1
3 files changed, 105 insertions, 13 deletions
diff --git a/filter/source/svg/svgreader.cxx b/filter/source/svg/svgreader.cxx
index 4cd7080b8a9a..5ae3281ae329 100644
--- a/filter/source/svg/svgreader.cxx
+++ b/filter/source/svg/svgreader.cxx
@@ -159,7 +159,8 @@ struct AnnotatingVisitor
AnnotatingVisitor(StatePool& rStatePool,
StateMap& rStateMap,
const State& rInitialState,
- const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler,
+ std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector) :
mnCurrStateId(0),
maCurrState(),
maParentStates(),
@@ -167,7 +168,9 @@ struct AnnotatingVisitor
mrStateMap(rStateMap),
mxDocumentHandler(xDocumentHandler),
maGradientVector(),
- maGradientStopVector()
+ maGradientStopVector(),
+ maElementVector(),
+ mrUseElementVector(rUseElementVector)
{
maParentStates.push_back(rInitialState);
}
@@ -265,6 +268,70 @@ struct AnnotatingVisitor
}
break;
}
+ case XML_USE:
+ {
+ uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem("href"));
+ if(xNode.is())
+ {
+ const OUString sValue(xNode->getNodeValue());
+ ElementRefMapType::iterator aFound=maElementIdMap.end();
+ if ( sValue.copy(0,1) == "#" )
+ aFound = maElementIdMap.find(sValue.copy(1));
+ else
+ aFound = maElementIdMap.find(sValue);
+ if( aFound != maElementIdMap.end() )
+ {
+ uno::Reference<xml::dom::XElement> xRefElem(
+ maElementVector[aFound->second]->cloneNode(true), uno::UNO_QUERY);
+
+ xRefElem->removeAttribute("id");
+ uno::Reference<xml::dom::XNode> xAttrNode;
+
+ const sal_Int32 nNumAttrs( xAttributes->getLength() );
+ OUString sAttributeValue;
+ double x=0.0, y=0.0;
+ for( sal_Int32 i=0; i<nNumAttrs; ++i )
+ {
+ sAttributeValue = xAttributes->item(i)->getNodeValue();
+ const sal_Int32 nAttribId(
+ getTokenId(xAttributes->item(i)->getNodeName()));
+
+ switch(nAttribId)
+ {
+ case XML_ID:
+ maElementVector.push_back(xElem);
+ maElementIdMap.insert(std::make_pair(sAttributeValue,
+ maElementVector.size() - 1));
+ break;
+ case XML_X:
+ x = convLength(sAttributeValue,maCurrState,'h');
+ break;
+ case XML_Y:
+ y = convLength(sAttributeValue,maCurrState,'v');
+ break;
+ case XML_TRANSFORM:
+ break;
+ default:
+ OUString sAttributeName = xAttributes->item(i)->getNodeName();
+ xRefElem->setAttribute(sAttributeName, sAttributeValue);
+ break;
+ }
+ }
+ std::stringstream ssAttrValue;
+ ssAttrValue << xRefElem->getAttribute("transform");
+ ssAttrValue << xElem->getAttribute("transform");
+ ssAttrValue << " translate(" << x << "," << y << ")";
+
+ OUString attrValue(OUString::createFromAscii (ssAttrValue.str().c_str()));
+ xRefElem->setAttribute("transform", attrValue);
+
+ mrUseElementVector.push_back(xRefElem);
+
+ visitElements((*this), xRefElem, STYLE_ANNOTATOR);
+ }
+ }
+ break;
+ }
case XML_STOP:
{
const sal_Int32 nNumAttrs( xAttributes->getLength() );
@@ -289,6 +356,7 @@ struct AnnotatingVisitor
// scan for style info
const sal_Int32 nNumAttrs( xAttributes->getLength() );
OUString sAttributeValue;
+
for( sal_Int32 i=0; i<nNumAttrs; ++i )
{
sAttributeValue = xAttributes->item(i)->getNodeValue();
@@ -297,8 +365,17 @@ struct AnnotatingVisitor
if( XML_STYLE == nTokenId )
parseStyle(sAttributeValue);
else
- parseAttribute(nTokenId,
- sAttributeValue);
+ {
+ if( XML_ID == nTokenId )
+ {
+ maElementVector.push_back(xElem);
+ maElementIdMap.insert(std::make_pair(sAttributeValue,
+ maElementVector.size() - 1));
+ }
+ else
+ parseAttribute(nTokenId,
+ sAttributeValue);
+ }
}
// all attributes parsed, can calc total CTM now
@@ -1218,18 +1295,23 @@ struct AnnotatingVisitor
uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
std::vector< Gradient > maGradientVector;
std::vector< GradientStop > maGradientStopVector;
+ std::vector< uno::Reference<xml::dom::XElement> > maElementVector;
+ std::vector< uno::Reference<xml::dom::XElement> >& mrUseElementVector;
ElementRefMapType maGradientIdMap;
ElementRefMapType maStopIdMap;
+ ElementRefMapType maElementIdMap;
};
/// Annotate svg styles with unique references to state pool
static void annotateStyles( StatePool& rStatePool,
StateMap& rStateMap,
const State& rInitialState,
- const uno::Reference<xml::dom::XElement>& rElem,
- const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
+ uno::Reference<xml::dom::XElement>& rElem,
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl,
+ std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector )
{
- AnnotatingVisitor aVisitor(rStatePool,rStateMap,rInitialState,xDocHdl);
+
+ AnnotatingVisitor aVisitor(rStatePool,rStateMap,rInitialState,xDocHdl,rUseElementVector);
visitElements(aVisitor, rElem, STYLE_ANNOTATOR);
}
@@ -1786,10 +1868,17 @@ struct ShapeWritingVisitor
static void writeShapes( StatePool& rStatePool,
StateMap& rStateMap,
const uno::Reference<xml::dom::XElement>& rElem,
- const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl,
+ std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector )
{
ShapeWritingVisitor aVisitor(rStatePool,rStateMap,xDocHdl);
visitElements(aVisitor, rElem, SHAPE_WRITER);
+
+ std::vector< uno::Reference<xml::dom::XElement> >::iterator it;
+ for ( it = rUseElementVector.begin() ; it != rUseElementVector.end(); ++it)
+ {
+ visitElements(aVisitor, *it, SHAPE_WRITER);
+ }
}
} // namespace
@@ -1906,6 +1995,7 @@ static void writeOfficeStyles( StateMap&
{
OfficeStylesWritingVisitor aVisitor( rStateMap, xDocHdl );
visitElements( aVisitor, rElem, STYLE_WRITER );
+
}
#if OSL_DEBUG_LEVEL > 2
@@ -2110,8 +2200,10 @@ bool SVGReader::parseAndConvert()
StatePool aStatePool;
StateMap aStateMap;
+ std::vector< uno::Reference<xml::dom::XElement> > maUseElementVector;
+
annotateStyles(aStatePool,aStateMap,aInitialState,
- xDocElem,m_xDocumentHandler);
+ xDocElem,m_xDocumentHandler,maUseElementVector);
#if OSL_DEBUG_LEVEL > 2
dumpTree(xDocElem);
@@ -2119,8 +2211,6 @@ bool SVGReader::parseAndConvert()
m_xDocumentHandler->endElement( "office:automatic-styles" );
-
-
xAttrs->Clear();
m_xDocumentHandler->startElement( "office:styles", xUnoAttrs);
writeOfficeStyles( aStateMap,
@@ -2129,7 +2219,6 @@ bool SVGReader::parseAndConvert()
m_xDocumentHandler->endElement( "office:styles" );
-
m_xDocumentHandler->startElement( "office:master-styles", xUnoAttrs );
xAttrs->Clear();
xAttrs->AddAttribute( "style:name", "Default");
@@ -2155,7 +2244,8 @@ bool SVGReader::parseAndConvert()
writeShapes(aStatePool,
aStateMap,
xDocElem,
- m_xDocumentHandler);
+ m_xDocumentHandler,
+ maUseElementVector);
m_xDocumentHandler->endElement( "draw:page" );
m_xDocumentHandler->endElement( "office:drawing" );
diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx
index 062852b80357..5e3dcc03cc8f 100644
--- a/include/xmloff/xmltoken.hxx
+++ b/include/xmloff/xmltoken.hxx
@@ -1931,6 +1931,7 @@ namespace xmloff { namespace token {
XML_UPLIMIT,
XML_UPRIGHT,
XML_URL,
+ XML_USE,
XML_USE_CAPTION,
XML_USE_CELL_PROTECTION,
XML_USE_CHART_OBJECTS,
diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx
index 0ebf728308f6..157030123106 100644
--- a/xmloff/source/core/xmltoken.cxx
+++ b/xmloff/source/core/xmltoken.cxx
@@ -1936,6 +1936,7 @@ namespace xmloff { namespace token {
TOKEN( "uplimit", XML_UPLIMIT ),
TOKEN( "upright", XML_UPRIGHT ),
TOKEN( "url", XML_URL ),
+ TOKEN( "use", XML_USE ),
TOKEN( "use-caption", XML_USE_CAPTION ),
TOKEN( "use-cell-protection", XML_USE_CELL_PROTECTION ),
TOKEN( "use-chart-objects", XML_USE_CHART_OBJECTS ),