Improve precision options for smaller output size

Add a seperate precision option for curve control points
(--set-c-precision) . Interpret precision digits = 0 as round to nearest
integer between -1 and 1. Add option to preserves all digits left of
decimal point regardless of set precision.
This commit is contained in:
pborunda 2017-02-08 14:08:04 -07:00
parent 210c5f64ab
commit f5ad0f4988

View file

@ -2539,7 +2539,7 @@ def serializePath(pathObj, options):
""" """
# elliptical arc commands must have comma/wsp separating the coordinates # elliptical arc commands must have comma/wsp separating the coordinates
# this fixes an issue outlined in Fix https://bugs.launchpad.net/scour/+bug/412754 # this fixes an issue outlined in Fix https://bugs.launchpad.net/scour/+bug/412754
return ''.join([cmd + scourCoordinates(data, options, (cmd == 'a')) for cmd, data in pathObj]) return ''.join([cmd + scourCoordinates(data, options, (cmd == 'a'), cmd) for cmd, data in pathObj])
def serializeTransform(transformObj): def serializeTransform(transformObj):
@ -2554,7 +2554,7 @@ def serializeTransform(transformObj):
) )
def scourCoordinates(data, options, forceCommaWsp=False): def scourCoordinates(data, options, forceCommaWsp=False, cmd=''):
""" """
Serializes coordinate data with some cleanups: Serializes coordinate data with some cleanups:
- removes all trailing zeros after the decimal - removes all trailing zeros after the decimal
@ -2567,7 +2567,7 @@ def scourCoordinates(data, options, forceCommaWsp=False):
c = 0 c = 0
previousCoord = '' previousCoord = ''
for coord in data: for coord in data:
scouredCoord = scourUnitlessLength(coord, needsRendererWorkaround=options.renderer_workaround) scouredCoord = scourUnitlessLength(coord, needsRendererWorkaround=options.renderer_workaround, isControlPoint=((cmd == 'c' and (c % 6) < 4) or (cmd == 's' and (c % 4) < 2)))
# only need the comma if the current number starts with a digit # only need the comma if the current number starts with a digit
# (numbers can start with - without needing a comma before) # (numbers can start with - without needing a comma before)
# or if forceCommaWsp is True # or if forceCommaWsp is True
@ -2613,7 +2613,7 @@ def scourLength(length):
return scourUnitlessLength(length.value) + Unit.str(length.units) return scourUnitlessLength(length.value) + Unit.str(length.units)
def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of a numeric type def scourUnitlessLength(length, needsRendererWorkaround=False, isControlPoint=False): # length is of a numeric type
""" """
Scours the numeric part of a length only. Does not accept units. Scours the numeric part of a length only. Does not accept units.
@ -2625,7 +2625,26 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of
# reduce numeric precision # reduce numeric precision
# plus() corresponds to the unary prefix plus operator and applies context precision and rounding # plus() corresponds to the unary prefix plus operator and applies context precision and rounding
length = scouringContext.plus(length) sContext = scouringContext;
roundNearZero = scouringRoundNearZero
if(isControlPoint):
sContext = scouringContextC;
roundNearZero = scouringRoundNearZeroC;
if(roundNearZero and length > -1 and length < 1):
length = getcontext().create_decimal(str(int(round(length))))
else:
if(scouringKeepIntPrecision):
length_as_int = int(round(length))
len_length_as_int = len(str(abs(length_as_int)))
saved_prec = sContext.prec;
if(sContext.prec < len_length_as_int):
# preserve all digits left of the decimal point
sContext.prec = len_length_as_int;
length = sContext.plus(length)
sContext.prec = saved_prec;
else:
length = sContext.plus(length)
# remove trailing zeroes as we do not care for significance # remove trailing zeroes as we do not care for significance
intLength = length.to_integral_value() intLength = length.to_integral_value()
@ -3259,7 +3278,27 @@ def scourString(in_string, options=None):
# calculations should be done in the default context (precision defaults to 28 significant digits) # calculations should be done in the default context (precision defaults to 28 significant digits)
# to minimize errors # to minimize errors
global scouringContext global scouringContext
global scouringContextC
global scouringKeepIntPrecision
global scouringRoundNearZero
global scouringRoundNearZeroC
scouringKeepIntPrecision = options.keep_int_precision
scouringRoundNearZero = False
scouringRoundNearZeroC = False
# must have at least 1 significant digit
# interrept digits == 0 as rounding to nearest int for values between -1 and 1
if(options.digits == 0):
options.digits = 1
scouringRoundNearZero = True
if(options.cdigits == 0):
options.cdigits = 1
scouringRoundNearZeroC = True
scouringContext = Context(prec=options.digits) scouringContext = Context(prec=options.digits)
if(options.cdigits < options.digits):
scouringContextC = Context(prec=options.cdigits)
else:
scouringContextC = scouringContext
# globals for tracking statistics # globals for tracking statistics
# TODO: get rid of these globals... # TODO: get rid of these globals...
@ -3590,6 +3629,12 @@ _option_group_optimization = optparse.OptionGroup(_options_parser, "Optimization
_option_group_optimization.add_option("-p", "--set-precision", _option_group_optimization.add_option("-p", "--set-precision",
action="store", type=int, dest="digits", default=5, metavar="NUM", action="store", type=int, dest="digits", default=5, metavar="NUM",
help="set number of significant digits (default: %default)") help="set number of significant digits (default: %default)")
_option_group_optimization.add_option("-c", "--set-c-precision",
action="store", type=int, dest="cdigits", default=5, metavar="NUM",
help="set number of significant digits for curve control points (default: %default)")
_option_group_optimization.add_option("-k", "--keep-int-precision",
action="store_true", dest="keep_int_precision", default=False,
help="preserves all digits left of decimal point regardless of set precision")
_option_group_optimization.add_option("--disable-simplify-colors", _option_group_optimization.add_option("--disable-simplify-colors",
action="store_false", dest="simple_colors", default=True, action="store_false", dest="simple_colors", default=True,
help="won't convert all colors to #RRGGBB format") help="won't convert all colors to #RRGGBB format")
@ -3702,6 +3747,8 @@ def parse_args(args=None, ignore_additional_args=False):
_options_parser.error("Additional arguments not handled: %r, see --help" % rargs) _options_parser.error("Additional arguments not handled: %r, see --help" % rargs)
if options.digits < 0: if options.digits < 0:
_options_parser.error("Can't have negative significant digits, see --help") _options_parser.error("Can't have negative significant digits, see --help")
if options.cdigits < 0:
_options_parser.error("Can't have negative significant digits for curve control points , see --help")
if options.indent_type not in ['tab', 'space', 'none']: if options.indent_type not in ['tab', 'space', 'none']:
_options_parser.error("Invalid value for --indent, see --help") _options_parser.error("Invalid value for --indent, see --help")
if options.indent_depth < 0: if options.indent_depth < 0: