summaryrefslogtreecommitdiff
path: root/svgio/source/svgreader/svgnode.cxx
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2014-07-25 15:38:47 +0000
committerCaolán McNamara <caolanm@redhat.com>2014-07-26 14:51:33 +0100
commit0347e5c77d281e4a25f79660aafb625691c4f883 (patch)
tree1878ccaa3f4fb7dcf878566ccc672912d11863dc /svgio/source/svgreader/svgnode.cxx
parente5dd2e8826433566e223d0572ed73f21d0b992f1 (diff)
Related: #i125293# Further corrections for CssStyle handling in SVG importer
(cherry picked from commit f00d6d2ea3e73e687edb1da4c32c0960eaf5010b) Conflicts: svgio/source/svgreader/svgnode.cxx svgio/source/svgreader/svgstyleattributes.cxx svgio/source/svgreader/svgstylenode.cxx svgio/source/svgreader/svgsvgnode.cxx Change-Id: I335b292fcdf1ebac925c9fd76ad624efb923447d
Diffstat (limited to 'svgio/source/svgreader/svgnode.cxx')
-rw-r--r--svgio/source/svgreader/svgnode.cxx234
1 files changed, 140 insertions, 94 deletions
diff --git a/svgio/source/svgreader/svgnode.cxx b/svgio/source/svgreader/svgnode.cxx
index 431ba0c26a9f..24decd3e4b1a 100644
--- a/svgio/source/svgreader/svgnode.cxx
+++ b/svgio/source/svgreader/svgnode.cxx
@@ -40,96 +40,131 @@ namespace svgio
return 0;
}
- const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const
+ void SvgNode::fillCssStyleVector(const rtl::OUString& rClassStr)
{
- if(maCssStyleVector.empty()) // #120435# Evaluate for CSS styles only once, this cannot change
+ OSL_ENSURE(!mbCssStyleVectorBuilt, "OOps, fillCssStyleVector called double ?!?");
+ mbCssStyleVectorBuilt = true;
+
+ // #125293# If we have CssStyles we need to buuild a linked list of SvgStyleAttributes
+ // which represent this for the current object. There are various methods to
+ // specify CssStyles which need to be taken into account in a given order:
+ // - local CssStyle (independent from global CssStyles at SvgDocument)
+ // - 'id' CssStyle
+ // - 'class' CssStyle(s)
+ // - type-dependent elements (e..g. 'rect' for all rect elements)
+ // - local attributes (rOriginal)
+ // - inherited attributes (up the hierarchy)
+ // The first four will be collected in maCssStyleVector for the current element
+ // (once, this will not change) and be linked in the needed order using the
+ // get/setCssStyleParent at the SvgStyleAttributes which will be used preferred in
+ // member evaluation over the existing parent hierarchy
+
+ // check for local CssStyle with highest priority
+ if(mpLocalCssStyle)
{
- const SvgDocument& rDocument = getDocument();
+ // if we have one, use as first entry
+ maCssStyleVector.push_back(mpLocalCssStyle);
+ }
+
+ const SvgDocument& rDocument = getDocument();
- if(rDocument.hasSvgStyleAttributesById())
+ if(rDocument.hasSvgStyleAttributesById())
+ {
+ // check for 'id' references
+ if(getId())
{
- // #i125293# If we have CssStyles we need to buuild a linked list of SvgStyleAttributes
- // which represent this for the current object. There are various methods to
- // specify CssStyles which need to be taken into account in a given order:
- // - 'id' element
- // - 'class' element(s)
- // - type-dependent elements (e..g. 'rect' for all rect elements)
- // - local firect attributes (rOriginal)
- // - inherited attributes (up the hierarchy)
- // The first three will be collected in maCssStyleVector for the current element
- // (once, this will not change) and be linked in the needed order using the
- // get/setCssStyleParent at the SvgStyleAttributes which will be used preferred in
- // member evaluation over the existing parent hierarchy
-
- // check for 'id' references
- if(getId())
+ // concatenate combined style name during search for CSS style equal to Id
+ // when travelling over node parents
+ rtl::OUString aConcatenatedStyleName;
+ const SvgNode* pCurrent = this;
+ const SvgStyleAttributes* pNew = 0;
+
+ while(!pNew && pCurrent)
{
- // search for CSS style equal to Id
- const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(*getId());
+ if(pCurrent->getId())
+ {
+ aConcatenatedStyleName = *pCurrent->getId() + aConcatenatedStyleName;
+ }
- if(pNew)
+ if(aConcatenatedStyleName.getLength())
{
- const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
+ pNew = rDocument.findSvgStyleAttributesById(aConcatenatedStyleName);
}
+
+ pCurrent = pCurrent->getParent();
}
- // check for 'class' references
- if(getClass())
+ if(pNew)
{
- // find all referenced CSS styles, a list of entries is allowed
- const rtl::OUString* pClassList = getClass();
- const sal_Int32 nLen(pClassList->getLength());
- sal_Int32 nPos(0);
- const SvgStyleAttributes* pNew = 0;
+ maCssStyleVector.push_back(pNew);
+ }
+ }
- skip_char(*pClassList, ' ', nPos, nLen);
+ // check for 'class' references
+ if(getClass())
+ {
+ // find all referenced CSS styles (a list of entries is allowed)
+ const rtl::OUString* pClassList = getClass();
+ const sal_Int32 nLen(pClassList->getLength());
+ sal_Int32 nPos(0);
+ const SvgStyleAttributes* pNew = 0;
- while(nPos < nLen)
- {
- rtl::OUStringBuffer aTokenValue;
+ skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
- copyToLimiter(*pClassList, ' ', nPos, aTokenValue, nLen);
- skip_char(*pClassList, ' ', nPos, nLen);
+ while(nPos < nLen)
+ {
+ rtl::OUStringBuffer aTokenValue;
- rtl::OUString aId(".");
- const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
+ copyToLimiter(*pClassList, sal_Unicode(' '), nPos, aTokenValue, nLen);
+ skip_char(*pClassList, sal_Unicode(' '), nPos, nLen);
- // look for CSS style common to token
- aId += aOUTokenValue;
- pNew = rDocument.findSvgStyleAttributesById(aId);
+ rtl::OUString aId(rtl::OUString::createFromAscii("."));
+ const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
- if(!pNew && !rClassStr.isEmpty())
- {
- // look for CSS style common to class.token
- aId = rClassStr + aId;
+ // look for CSS style common to token
+ aId = aId + aOUTokenValue;
+ pNew = rDocument.findSvgStyleAttributesById(aId);
- pNew = rDocument.findSvgStyleAttributesById(aId);
- }
+ if(!pNew && rClassStr.getLength())
+ {
+ // look for CSS style common to class.token
+ aId = rClassStr + aId;
- if(pNew)
- {
- const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
- }
+ pNew = rDocument.findSvgStyleAttributesById(aId);
}
- }
-
- // check for class-dependent references to CssStyles
- if(rClassStr.getLength())
- {
- // search for CSS style equal to class type
- const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(rClassStr);
if(pNew)
{
- const_cast< SvgNode* >(this)->maCssStyleVector.push_back(pNew);
+ maCssStyleVector.push_back(pNew);
}
}
}
+
+ // check for class-dependent references to CssStyles
+ if(rClassStr.getLength())
+ {
+ // search for CSS style equal to class type
+ const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(rClassStr);
+
+ if(pNew)
+ {
+ maCssStyleVector.push_back(pNew);
+ }
+ }
+ }
+ }
+
+ const SvgStyleAttributes* SvgNode::checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const
+ {
+ if(!mbCssStyleVectorBuilt)
+ {
+ // build needed CssStyleVector for local node
+ const_cast< SvgNode* >(this)->fillCssStyleVector(rClassStr);
}
if(maCssStyleVector.empty())
{
- // return original if no CssStlyes found
+ // return given original if no CssStlyes found
return &rOriginal;
}
else
@@ -186,7 +221,9 @@ namespace svgio
mpClass(0),
maXmlSpace(XmlSpace_notset),
maDisplay(Display_inline),
- maCssStyleVector()
+ maCssStyleVector(),
+ mpLocalCssStyle(0),
+ mbCssStyleVectorBuilt(false)
{
OSL_ENSURE(SVGTokenUnknown != maType, "SvgNode with unknown type created (!)");
@@ -213,50 +250,59 @@ namespace svgio
maChildren.pop_back();
}
- if(mpId) delete mpId;
- if(mpClass) delete mpClass;
+ if(mpId)
+ {
+ delete mpId;
+ }
+
+ if(mpClass)
+ {
+ delete mpClass;
+ }
+
+ if(mpLocalCssStyle)
+ {
+ delete mpLocalCssStyle;
+ }
+ }
+
+ void SvgNode::readLocalCssStyle(const rtl::OUString& aContent)
+ {
+ if(!mpLocalCssStyle)
+ {
+ // create LocalCssStyle if needed but not yet added
+ mpLocalCssStyle = new SvgStyleAttributes(*this);
+ }
+ else
+ {
+ // 2nd fill would be an error
+ OSL_ENSURE(false, "Svg node has two local CssStyles, this may lead to problems (!)");
+ }
+
+ if(mpLocalCssStyle)
+ {
+ // parse and set values to it
+ mpLocalCssStyle->readStyle(aContent);
+ }
+ else
+ {
+ OSL_ENSURE(false, "Could not get/create a local CssStyle for a node (!)");
+ }
}
void SvgNode::parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs)
{
+ // no longer need to pre-sort moving 'style' entries to the back so that
+ // values get overwritten - that was the previous, not complete solution for
+ // handling the priorities between svg and Css properties
const sal_uInt32 nAttributes(xAttribs->getLength());
- // #i122522# SVG defines that 'In general, this means that the presentation attributes have
- // lower priority than other CSS style rules specified in author style sheets or style
- // attributes.' in http://www.w3.org/TR/SVG/styling.html#UsingPresentationAttributes
- // (6.4 Specifying properties using the presentation attributes SVG 1.1). That means that
- // e.g. font-size will appear as presentation attribute and CSS style attribute. In these
- // cases, CSS style attributes need to have precedence. To do so it is possible to create
- // a proirity system for all properties of a shape, but it will also work to parse the
- // presentation attributes of type 'style' last, so they will overwrite the less-prioritized
- // already interpreted ones. Thus, remember SVGTokenStyle entries and parse them last.
- // To make this work it is required that parseAttribute is only called by parseAttributes
- // which is the case.
- std::vector< sal_uInt32 > aSVGTokenStyleIndexes;
for(sal_uInt32 a(0); a < nAttributes; a++)
{
const OUString aTokenName(xAttribs->getNameByIndex(a));
const SVGToken aSVGToken(StrToSVGToken(aTokenName));
- if(SVGTokenStyle == aSVGToken)
- {
- // #i122522# remember SVGTokenStyle entry
- aSVGTokenStyleIndexes.push_back(a);
- }
- else
- {
- parseAttribute(aTokenName, aSVGToken, xAttribs->getValueByIndex(a));
- }
- }
-
- // #i122522# parse SVGTokenStyle entries last to override already interpreted
- // 'presentation attributes' of potenially the same type
- for(sal_uInt32 b(0); b < aSVGTokenStyleIndexes.size(); b++)
- {
- const sal_uInt32 nSVGTokenStyleIndex(aSVGTokenStyleIndexes[b]);
- const ::rtl::OUString aTokenName(xAttribs->getNameByIndex(nSVGTokenStyleIndex));
-
- parseAttribute(aTokenName, SVGTokenStyle, xAttribs->getValueByIndex(nSVGTokenStyleIndex));
+ parseAttribute(aTokenName, aSVGToken, xAttribs->getValueByIndex(a));
}
}