From b661e479ea4068a633a866f9732aa109fe52aa0b Mon Sep 17 00:00:00 2001 From: Jeff Schiller Date: Sun, 11 Jul 2010 08:52:18 -0700 Subject: [PATCH] Fix Bug 603988: do not commonize attributes if element is referenced elsewhere --- release-notes.html | 3 ++- scour.py | 21 +++++++++++++------- testscour.py | 4 ++++ unittests/commonized-referenced-elements.svg | 9 +++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 unittests/commonized-referenced-elements.svg diff --git a/release-notes.html b/release-notes.html index 15b9f6c..91594d8 100644 --- a/release-notes.html +++ b/release-notes.html @@ -13,12 +13,13 @@

Version 0.25

-

2010-05-09

+

2010-07-11

diff --git a/scour.py b/scour.py index 8e0bc3c..161b45c 100755 --- a/scour.py +++ b/scour.py @@ -403,7 +403,10 @@ referencingProps = ['fill', 'stroke', 'filter', 'clip-path', 'mask', 'marker-st def findReferencedElements(node, ids=None): """ Returns the number of times an ID is referenced as well as all elements - that reference it. + that reference it. node is the node at which to start the search. The + return value is a map which has the id as key and each value is an array + where the first value is a count and the second value is a list of nodes + that referenced it. Currently looks at fill, stroke, clip-path, mask, marker, and xlink:href attributes. @@ -775,21 +778,24 @@ def removeNestedGroups(node): num += removeNestedGroups(child) return num -def moveCommonAttributesToParentGroup(elem): +def moveCommonAttributesToParentGroup(elem, referencedElements): """ This recursively calls this function on all children of the passed in element and then iterates over all child elements and removes common inheritable attributes from the children and places them in the parent group. But only if the parent contains - nothing but element children and whitespace. + nothing but element children and whitespace. The attributes are only removed from the + children if the children are not referenced by other elements in the document. """ num = 0 childElements = [] # recurse first into the children (depth-first) for child in elem.childNodes: - if child.nodeType == 1: - childElements.append(child) - num += moveCommonAttributesToParentGroup(child) + if child.nodeType == 1: + # only add and recurse if the child is not referenced elsewhere + if not child.getAttribute('id') in referencedElements: + childElements.append(child) + num += moveCommonAttributesToParentGroup(child, referencedElements) # else if the parent has non-whitespace text children, do not # try to move common attributes elif child.nodeType == 3 and child.nodeValue.strip(): @@ -2655,8 +2661,9 @@ def scourString(in_string, options=None): # all have the same value for an attribute, it must not # get moved to the element. The element # doesn't accept fill=, stroke= etc.! + referencedIds = findReferencedElements(doc.documentElement) for child in doc.documentElement.childNodes: - numAttrsRemoved += moveCommonAttributesToParentGroup(child) + numAttrsRemoved += moveCommonAttributesToParentGroup(child, referencedIds) # remove unused attributes from parent numAttrsRemoved += removeUnusedAttributesOnParent(doc.documentElement) diff --git a/testscour.py b/testscour.py index bd70c40..8349234 100755 --- a/testscour.py +++ b/testscour.py @@ -1097,6 +1097,10 @@ class GroupNoCreation(unittest.TestCase): self.assertEquals(doc.getElementsByTagName('g').length, 0, 'Created a for a run of elements having dissimilar attributes') +class DoNotCommonizeAttributesOnReferencedElements(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/commonized-referenced-elements.svg') + self.assertEquals(doc.getElementsByTagName('circle')[0].getAttribute('fill'), '#0f0') # TODO: write tests for --enable-viewboxing # TODO; write a test for embedding rasters diff --git a/unittests/commonized-referenced-elements.svg b/unittests/commonized-referenced-elements.svg new file mode 100644 index 0000000..3a84239 --- /dev/null +++ b/unittests/commonized-referenced-elements.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file