initial source import (v0.26) and packaging

This commit is contained in:
Tobias Oberstein 2013-10-22 16:31:42 +02:00
parent 39fb9eee02
commit 6372b8a2a7
7 changed files with 389 additions and 297 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.py[cod]
*.sublime-workspace
build
dist
*.egg-info

9
Makefile Normal file
View file

@ -0,0 +1,9 @@
all: clean install
install:
python setup.py install
clean:
rm -rf build
rm -rf dist
rm -rf scour.egg-info

View file

@ -1,5 +1,4 @@
Scour # Scour
=====
Scour is a Python module that takes an input SVG and outputs a cleaner, Scour is a Python module that takes an input SVG and outputs a cleaner,
more concise SVG file. The goal is that authors will use this script after more concise SVG file. The goal is that authors will use this script after
@ -11,13 +10,23 @@ such as openclipart.org
Ideas are pulled from three places: Ideas are pulled from three places:
- my head * my head
- Sam Ruby's SVG Tidy script: http://intertwingly.net/code/svgtidy/svgtidy.rb * Sam Ruby's SVG Tidy script: http://intertwingly.net/code/svgtidy/svgtidy.rb
- Inkscape's proposal for a 'cleaned SVG': http://wiki.inkscape.org/wiki/index.php/Save_Cleaned_SVG * Inkscape's proposal for a 'cleaned SVG': http://wiki.inkscape.org/wiki/index.php/Save_Cleaned_SVG
Regards, Regards,
Jeff Schiller Jeff Schiller, 2009-04-06
2009-04-06
codedread@gmail.com codedread@gmail.com
http://blog.codedread.com/ http://blog.codedread.com/
http://www.codedread.com/scour/
## Notes
Packaging from [sources](http://www.codedread.com/scour/) retrieved on 2013/20/22:
* done by Tavendo GmbH, Tobias Oberstein
* license same as upstream (Apache 2.0)

21
scour.sublime-project Normal file
View file

@ -0,0 +1,21 @@
{
"folders":
[
{
"name": "Scour",
"path": ".",
"folder_exclude_patterns": ["*.egg-info", "build", "dist"],
"file_exclude_patterns": ["*.pyc", "*.pyo", "*.pyd"]
}
],
"settings":
{
"default_encoding": "UTF-8",
"detect_indentation": false,
"ensure_newline_at_eof_on_save": true,
"tab_size": 3,
"translate_tabs_to_spaces": true,
"trim_trailing_white_space_on_save": true,
"use_tab_stops": true
}
}

22
scour/__init__.py Normal file
View file

@ -0,0 +1,22 @@
###############################################################################
##
## Copyright (C) 2013 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import scour
import svg_regex
import svg_transform
import yocto_css

47
scour/scour.py Executable file → Normal file
View file

@ -565,25 +565,6 @@ numBytesSavedInTransforms = 0
numPointsRemovedFromPolygon = 0 numPointsRemovedFromPolygon = 0
numCommentBytes = 0 numCommentBytes = 0
def flattenDefs(doc):
"""
Puts all defined elements into a newly created defs in the document. This function
handles recursive defs elements.
"""
defs = doc.documentElement.getElementsByTagName('defs')
if defs.length > 1:
topDef = doc.createElementNS(NS['SVG'], 'defs')
for defElem in defs:
# Remove all children of this defs and put it into the topDef.
while defElem.hasChildNodes():
topDef.appendChild(defElem.firstChild)
defElem.parentNode.removeChild(defElem)
if topDef.hasChildNodes():
doc.documentElement.insertBefore(topDef, doc.documentElement.firstChild)
def removeUnusedDefs(doc, defElem, elemsToRemove=None): def removeUnusedDefs(doc, defElem, elemsToRemove=None):
if elemsToRemove is None: if elemsToRemove is None:
elemsToRemove = [] elemsToRemove = []
@ -2144,13 +2125,10 @@ def parseListOfPoints(s):
# we got negative coords # we got negative coords
else: else:
for j in xrange(len(negcoords)): for j in xrange(len(negcoords)):
# first number could be positive
if j == 0: if j == 0:
# first number could be positive
if negcoords[0] != '': if negcoords[0] != '':
nums.append(negcoords[0]) nums.append(negcoords[0])
# but it could also be negative
elif len(nums) == 0:
nums.append('-' + negcoords[j])
# otherwise all other strings will be negative # otherwise all other strings will be negative
else: else:
# unless we accidentally split a number that was in scientific notation # unless we accidentally split a number that was in scientific notation
@ -2575,21 +2553,17 @@ def removeComments(element) :
if isinstance(element, xml.dom.minidom.Document): if isinstance(element, xml.dom.minidom.Document):
# must process the document object separately, because its # must process the document object separately, because its
# documentElement's nodes have None as their parentNode # documentElement's nodes have None as their parentNode
# iterate in reverse order to prevent mess-ups with renumbering for subelement in element.childNodes:
for index in xrange(len(element.childNodes) - 1, -1, -1): if isinstance(element, xml.dom.minidom.Comment):
subelement = element.childNodes[index] numCommentBytes += len(element.data)
if isinstance(subelement, xml.dom.minidom.Comment): element.documentElement.removeChild(subelement)
numCommentBytes += len(subelement.data)
element.removeChild(subelement)
else: else:
removeComments(subelement) removeComments(subelement)
elif isinstance(element, xml.dom.minidom.Comment): elif isinstance(element, xml.dom.minidom.Comment):
numCommentBytes += len(element.data) numCommentBytes += len(element.data)
element.parentNode.removeChild(element) element.parentNode.removeChild(element)
else: else:
# iterate in reverse order to prevent mess-ups with renumbering for subelement in element.childNodes:
for index in xrange(len(element.childNodes) - 1, -1, -1):
subelement = element.childNodes[index]
removeComments(subelement) removeComments(subelement)
def embedRasters(element, options) : def embedRasters(element, options) :
@ -2910,9 +2884,6 @@ def scourString(in_string, options=None):
if options.remove_metadata: if options.remove_metadata:
removeMetadataElements(doc) removeMetadataElements(doc)
# flattend defs elements into just one defs element
flattenDefs(doc)
# remove unreferenced gradients/patterns outside of defs # remove unreferenced gradients/patterns outside of defs
# and most unreferenced elements inside of defs # and most unreferenced elements inside of defs
while removeUnreferencedElements(doc) > 0: while removeUnreferencedElements(doc) > 0:
@ -3192,7 +3163,7 @@ def getReport():
' Number of bytes saved in lengths: ' + str(numBytesSavedInLengths) + os.linesep + \ ' Number of bytes saved in lengths: ' + str(numBytesSavedInLengths) + os.linesep + \
' Number of bytes saved in transformations: ' + str(numBytesSavedInTransforms) ' Number of bytes saved in transformations: ' + str(numBytesSavedInTransforms)
if __name__ == '__main__': def run():
if sys.platform == "win32": if sys.platform == "win32":
from time import clock as get_tick from time import clock as get_tick
else: else:
@ -3229,3 +3200,7 @@ if __name__ == '__main__':
sizediff = (newsize / oldsize) * 100 sizediff = (newsize / oldsize) * 100
print >>sys.stderr, ' Original file size:', oldsize, 'bytes;', \ print >>sys.stderr, ' Original file size:', oldsize, 'bytes;', \
'new file size:', newsize, 'bytes (' + str(sizediff)[:5] + '%)' 'new file size:', newsize, 'bytes (' + str(sizediff)[:5] + '%)'
if __name__ == '__main__':
run()

51
setup.py Normal file
View file

@ -0,0 +1,51 @@
###############################################################################
##
## Copyright (C) 2013 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from setuptools import setup, find_packages
setup (
name = 'scour',
version = '0.26',
description = 'Scour SVG Optimizer',
long_description = open("README.md").read(),
license = 'Apache License 2.0',
author = 'Jeff Schiller',
author_email = 'codedread@gmail.com',
url = 'http://blog.codedread.com/',
platforms = ('Any'),
install_requires = [],
packages = find_packages(),
zip_safe = True,
entry_points = {
'console_scripts': [
'scour = scour.scour:run'
]},
classifiers = ["License :: OSI Approved :: Apache Software License",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Pre-processors",
"Topic :: Multimedia :: Graphics :: Graphics Conversion",
"Topic :: Utilities"],
keywords = 'svg optimizer'
)