diff options
author | Armin Le Grand <alg@apache.org> | 2014-07-25 15:38:47 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2014-07-26 14:51:33 +0100 |
commit | 0347e5c77d281e4a25f79660aafb625691c4f883 (patch) | |
tree | 1878ccaa3f4fb7dcf878566ccc672912d11863dc /svgio | |
parent | e5dd2e8826433566e223d0572ed73f21d0b992f1 (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')
25 files changed, 279 insertions, 136 deletions
diff --git a/svgio/inc/svgio/svgreader/svgnode.hxx b/svgio/inc/svgio/svgreader/svgnode.hxx index cc88b264370e..6a5217ce4b21 100644 --- a/svgio/inc/svgio/svgreader/svgnode.hxx +++ b/svgio/inc/svgio/svgreader/svgnode.hxx @@ -108,13 +108,25 @@ namespace svgio /// Display value #i121656# Display maDisplay; - /// CSS styles + // CSS style vector chain, used in decompose phase and built up once per node. + // It contains the StyleHierarchy for the local node. INdependent from the + // node hierarchy itself which also needs to be used in style entry solving SvgStyleAttributeVector maCssStyleVector; + /// possibbe local CssStyle, e.g. style="fill:red; stroke:red;" + SvgStyleAttributes* mpLocalCssStyle; + + /// bitfield + // flag if maCssStyleVector is already computed (done only once) + bool mbCssStyleVectorBuilt : 1; + protected: /// helper to evtl. link to css style const SvgStyleAttributes* checkForCssStyle(const rtl::OUString& rClassStr, const SvgStyleAttributes& rOriginal) const; + /// helper for filling the CssStyle vector once dependent on mbCssStyleVectorBuilt + void fillCssStyleVector(const rtl::OUString& rClassStr); + public: SvgNode( SVGToken aType, @@ -122,6 +134,10 @@ namespace svgio SvgNode* pParent); virtual ~SvgNode(); + /// scan helper to read and interpret a local CssStyle to mpLocalCssStyle + void readLocalCssStyle(const rtl::OUString& aContent); + + /// style helpers void parseAttributes(const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs); virtual const SvgStyleAttributes* getSvgStyleAttributes() const; virtual void parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent); diff --git a/svgio/source/svgreader/svgcirclenode.cxx b/svgio/source/svgreader/svgcirclenode.cxx index 38daca19864d..db75fde1a308 100644 --- a/svgio/source/svgreader/svgcirclenode.cxx +++ b/svgio/source/svgreader/svgcirclenode.cxx @@ -60,7 +60,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenCx: diff --git a/svgio/source/svgreader/svgclippathnode.cxx b/svgio/source/svgreader/svgclippathnode.cxx index 0a7f0f4a7369..7b65f943fa24 100644 --- a/svgio/source/svgreader/svgclippathnode.cxx +++ b/svgio/source/svgreader/svgclippathnode.cxx @@ -63,7 +63,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenTransform: diff --git a/svgio/source/svgreader/svgellipsenode.cxx b/svgio/source/svgreader/svgellipsenode.cxx index 5818a1c07aa6..03a5f6fa4360 100644 --- a/svgio/source/svgreader/svgellipsenode.cxx +++ b/svgio/source/svgreader/svgellipsenode.cxx @@ -61,7 +61,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenCx: diff --git a/svgio/source/svgreader/svggnode.cxx b/svgio/source/svgreader/svggnode.cxx index c3957c729fa9..85a97bdf4548 100644 --- a/svgio/source/svgreader/svggnode.cxx +++ b/svgio/source/svgreader/svggnode.cxx @@ -68,7 +68,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenTransform: diff --git a/svgio/source/svgreader/svggradientnode.cxx b/svgio/source/svgreader/svggradientnode.cxx index 893ff9657b93..92ea5b5a13f1 100644 --- a/svgio/source/svgreader/svggradientnode.cxx +++ b/svgio/source/svgreader/svggradientnode.cxx @@ -65,7 +65,12 @@ namespace svgio const SvgStyleAttributes* SvgGradientNode::getSvgStyleAttributes() const { - return &maSvgStyleAttributes; + static rtl::OUString aClassStrA(rtl::OUString::createFromAscii("linearGradient")); + static rtl::OUString aClassStrB(rtl::OUString::createFromAscii("radialGradient")); + + return checkForCssStyle( + SVGTokenLinearGradient == getType() ? aClassStrA : aClassStrB, + maSvgStyleAttributes); } void SvgGradientNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent) @@ -81,7 +86,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenX1: diff --git a/svgio/source/svgreader/svggradientstopnode.cxx b/svgio/source/svgreader/svggradientstopnode.cxx index 55a46cfd3456..6c6d758ee375 100644 --- a/svgio/source/svgreader/svggradientstopnode.cxx +++ b/svgio/source/svgreader/svggradientstopnode.cxx @@ -38,7 +38,9 @@ namespace svgio const SvgStyleAttributes* SvgGradientStopNode::getSvgStyleAttributes() const { - return &maSvgStyleAttributes; + static rtl::OUString aClassStr(rtl::OUString::createFromAscii("stop")); + + return checkForCssStyle(aClassStr, maSvgStyleAttributes); } void SvgGradientStopNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent) @@ -54,7 +56,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenOffset: diff --git a/svgio/source/svgreader/svgimagenode.cxx b/svgio/source/svgreader/svgimagenode.cxx index 951d72b8edcb..cebd6137a4d2 100644 --- a/svgio/source/svgreader/svgimagenode.cxx +++ b/svgio/source/svgreader/svgimagenode.cxx @@ -78,7 +78,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenPreserveAspectRatio: diff --git a/svgio/source/svgreader/svglinenode.cxx b/svgio/source/svgreader/svglinenode.cxx index f4b503560dc2..5bba7d50acc8 100644 --- a/svgio/source/svgreader/svglinenode.cxx +++ b/svgio/source/svgreader/svglinenode.cxx @@ -61,7 +61,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenX1: diff --git a/svgio/source/svgreader/svgmarkernode.cxx b/svgio/source/svgreader/svgmarkernode.cxx index 73661431d4b8..5bad024c48a6 100644 --- a/svgio/source/svgreader/svgmarkernode.cxx +++ b/svgio/source/svgreader/svgmarkernode.cxx @@ -64,7 +64,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenViewBox: diff --git a/svgio/source/svgreader/svgmasknode.cxx b/svgio/source/svgreader/svgmasknode.cxx index e80f2e82c97c..736ce1489036 100644 --- a/svgio/source/svgreader/svgmasknode.cxx +++ b/svgio/source/svgreader/svgmasknode.cxx @@ -69,7 +69,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenX: 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)); } } diff --git a/svgio/source/svgreader/svgpathnode.cxx b/svgio/source/svgreader/svgpathnode.cxx index 73beb8079bb4..cf13a37fe548 100644 --- a/svgio/source/svgreader/svgpathnode.cxx +++ b/svgio/source/svgreader/svgpathnode.cxx @@ -59,7 +59,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenD: diff --git a/svgio/source/svgreader/svgpatternnode.cxx b/svgio/source/svgreader/svgpatternnode.cxx index a9abed5dc89e..a50892e9ac77 100644 --- a/svgio/source/svgreader/svgpatternnode.cxx +++ b/svgio/source/svgreader/svgpatternnode.cxx @@ -78,7 +78,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenViewBox: diff --git a/svgio/source/svgreader/svgpolynode.cxx b/svgio/source/svgreader/svgpolynode.cxx index 3b52ce4995e7..09da02daefba 100644 --- a/svgio/source/svgreader/svgpolynode.cxx +++ b/svgio/source/svgreader/svgpolynode.cxx @@ -62,7 +62,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenPoints: diff --git a/svgio/source/svgreader/svgrectnode.cxx b/svgio/source/svgreader/svgrectnode.cxx index cd89c08db972..2ee394968f7f 100644 --- a/svgio/source/svgreader/svgrectnode.cxx +++ b/svgio/source/svgreader/svgrectnode.cxx @@ -63,7 +63,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenX: diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 4d9448a5491f..b48431d3311d 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -183,12 +183,38 @@ namespace svgio if(!aTokenName.isEmpty()) { - skip_char(rCandidate, ' ', ':', nPos, nLen); - OUStringBuffer aTokenValue; - copyToLimiter(rCandidate, ';', nPos, aTokenValue, nLen); - skip_char(rCandidate, ' ', ';', nPos, nLen); - const OUString aOUTokenName(aTokenName.makeStringAndClear()); - const OUString aOUTokenValue(aTokenValue.makeStringAndClear()); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(':'), nPos, nLen); + rtl::OUStringBuffer aTokenValue; + copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aTokenValue, nLen); + skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); + const rtl::OUString aOUTokenName(aTokenName.makeStringAndClear()); + rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear()); + + // check for '!important' CssStyle mark, currently not supported + // but neds to be extracted for correct parsing + static rtl::OUString aTokenImportant(RTL_CONSTASCII_USTRINGPARAM("!important")); + const sal_Int32 nIndexTokenImportant(aOUTokenValue.indexOf(aTokenImportant)); + + if(-1 != nIndexTokenImportant) + { + // if there currently just remove it and remove spaces to have the value only + rtl::OUString aNewOUTokenValue; + + if(nIndexTokenImportant > 0) + { + // copy content before token + aNewOUTokenValue += aOUTokenValue.copy(0, nIndexTokenImportant); + } + + if(aOUTokenValue.getLength() > nIndexTokenImportant + aTokenImportant.getLength()) + { + // copy content after token + aNewOUTokenValue += aOUTokenValue.copy(nIndexTokenImportant + aTokenImportant.getLength()); + } + + // remove spaces + aOUTokenValue = aNewOUTokenValue.trim(); + } parseStyleAttribute(aOUTokenName, StrToSVGToken(aOUTokenName), aOUTokenValue); } diff --git a/svgio/source/svgreader/svgstylenode.cxx b/svgio/source/svgreader/svgstylenode.cxx index 99f7ff53e9ce..b17c52853db1 100644 --- a/svgio/source/svgreader/svgstylenode.cxx +++ b/svgio/source/svgreader/svgstylenode.cxx @@ -92,17 +92,42 @@ namespace svgio while(nPos < nLen) { + // read the full style node names (may be multiple) and put to aStyleName const sal_Int32 nInitPos(nPos); - skip_char(aContent, ' ', '#', nPos, nLen); - copyToLimiter(aContent, '{', nPos, aTokenValue, nLen); - const OUString aStyleName = aTokenValue.makeStringAndClear().trim(); + skip_char(aContent, sal_Unicode(' '), nPos, nLen); + copyToLimiter(aContent, sal_Unicode('{'), nPos, aTokenValue, nLen); + skip_char(aContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen); - if(!aStyleName.isEmpty() && nPos < nLen) + const rtl::OUString aStyleName(aTokenValue.makeStringAndClear().trim()); + const sal_Int32 nLen2(aStyleName.getLength()); + std::vector< rtl::OUString > aStyleNames; + + if(nLen2) { - skip_char(aContent, ' ', '{', nPos, nLen); - copyToLimiter(aContent, '}', nPos, aTokenValue, nLen); - skip_char(aContent, ' ', '}', nPos, nLen); - const OUString aStyleContent = aTokenValue.makeStringAndClear().trim(); + // extract names + sal_Int32 nPos2(0); + rtl::OUStringBuffer aSingleName; + + while(nPos2 < nLen2) + { + skip_char(aStyleName, sal_Unicode('#'), nPos2, nLen2); + copyToLimiter(aStyleName, sal_Unicode(' '), nPos2, aSingleName, nLen2); + skip_char(aStyleName, sal_Unicode(' '), nPos2, nLen2); + + const rtl::OUString aOUSingleName(aSingleName.makeStringAndClear().trim()); + + if(aOUSingleName.getLength()) + { + aStyleNames.push_back(aOUSingleName); + } + } + } + + if(aStyleNames.size() && nPos < nLen) + { + copyToLimiter(aContent, sal_Unicode('}'), nPos, aTokenValue, nLen); + skip_char(aContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen); + const rtl::OUString aStyleContent(aTokenValue.makeStringAndClear().trim()); if(!aStyleContent.isEmpty()) { @@ -113,8 +138,16 @@ namespace svgio // fill with content pNewStyle->readStyle(aStyleContent); - // register new style at document - const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aStyleName, *pNewStyle); + // concatenate combined style name + rtl::OUString aConcatenatedStyleName; + + for(sal_uInt32 a(0); a < aStyleNames.size(); a++) + { + aConcatenatedStyleName += aStyleNames[a]; + } + + // register new style at document for (evtl. concatenated) stylename + const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedStyleName, *pNewStyle); } } diff --git a/svgio/source/svgreader/svgsvgnode.cxx b/svgio/source/svgreader/svgsvgnode.cxx index 6c39cc996c31..d6d2a8379573 100644 --- a/svgio/source/svgreader/svgsvgnode.cxx +++ b/svgio/source/svgreader/svgsvgnode.cxx @@ -69,8 +69,23 @@ namespace svgio if(pStyles && pStyles->getParentStyle()) { - // #i125258# no initial values when SVG has a parent style (probably CssStyle) - bSetInitialValues = false; + // SVG has a parent style (probably CssStyle), check if fill is set there anywhere + // already. If yes, do not set the default fill (black) + bool bFillSet(false); + const SvgStyleAttributes* pParentStyle = pStyles->getParentStyle(); + + while(pParentStyle && !bFillSet) + { + bFillSet = pParentStyle->isFillSet(); + pParentStyle = pParentStyle->getParentStyle(); + } + + if(bFillSet) + { + // #125258# no initial values when SVG has a parent style at which a fill + // is already set + bSetInitialValues = false; + } } } @@ -113,7 +128,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenViewBox: diff --git a/svgio/source/svgreader/svgsymbolnode.cxx b/svgio/source/svgreader/svgsymbolnode.cxx index ca76e1a65c94..c1310597ab60 100644 --- a/svgio/source/svgreader/svgsymbolnode.cxx +++ b/svgio/source/svgreader/svgsymbolnode.cxx @@ -58,7 +58,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenViewBox: diff --git a/svgio/source/svgreader/svgtextnode.cxx b/svgio/source/svgreader/svgtextnode.cxx index 21565a3f6a78..9ef3c7fc726e 100644 --- a/svgio/source/svgreader/svgtextnode.cxx +++ b/svgio/source/svgreader/svgtextnode.cxx @@ -66,7 +66,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenTransform: diff --git a/svgio/source/svgreader/svgtextpathnode.cxx b/svgio/source/svgreader/svgtextpathnode.cxx index 7934a1d7b2a3..aba2624bf7a4 100644 --- a/svgio/source/svgreader/svgtextpathnode.cxx +++ b/svgio/source/svgreader/svgtextpathnode.cxx @@ -280,7 +280,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenStartOffset: diff --git a/svgio/source/svgreader/svgtrefnode.cxx b/svgio/source/svgreader/svgtrefnode.cxx index 8e37b9e6cbc0..961e1a46dcd9 100644 --- a/svgio/source/svgreader/svgtrefnode.cxx +++ b/svgio/source/svgreader/svgtrefnode.cxx @@ -55,7 +55,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenXlinkHref: diff --git a/svgio/source/svgreader/svgtspannode.cxx b/svgio/source/svgreader/svgtspannode.cxx index 139724934303..b837e72246be 100644 --- a/svgio/source/svgreader/svgtspannode.cxx +++ b/svgio/source/svgreader/svgtspannode.cxx @@ -58,7 +58,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } default: diff --git a/svgio/source/svgreader/svgusenode.cxx b/svgio/source/svgreader/svgusenode.cxx index 650b73e22758..c0220b70ae93 100644 --- a/svgio/source/svgreader/svgusenode.cxx +++ b/svgio/source/svgreader/svgusenode.cxx @@ -62,7 +62,7 @@ namespace svgio { case SVGTokenStyle: { - maSvgStyleAttributes.readStyle(aContent); + readLocalCssStyle(aContent); break; } case SVGTokenTransform: |