From d4efcaa9833ef3a067da98aa8499ef356f3c6553 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Tue, 16 May 2017 22:59:50 +0200 Subject: [PATCH] Optimize/simplify code for last commit and fix a longstanding indexing bug when collapsing subpaths (the first command of a path and all of its parameters were never optimized and as many paths consist only of one moveto command with many parameters the functionality might have been broken in many cases) --- scour/scour.py | 51 ++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/scour/scour.py b/scour/scour.py index a6248d6..424217f 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -404,6 +404,8 @@ default_properties = { # excluded all properties with 'auto' as default def is_same_sign(a, b): return (a <= 0 and b <= 0) or (a >= 0 and b >= 0) + + def is_same_slope(x1, y1, x2, y2): return y1/x1 - y2/x2 == 0 @@ -2407,28 +2409,33 @@ def cleanPath(element, options): # Reuse the data structure 'path', since we're not adding or removing subcommands. # Also reuse the coordinate lists, even if we're deleting items, because these # deletions are relatively cheap. - for pathIndex in range(1, len(path)): - cmd, data = path[pathIndex] - if cmd in ['h', 'v'] and len(data) > 1 and not has_markers: - coordIndex = 1 - while coordIndex < len(data): - if is_same_sign(data[coordIndex - 1], data[coordIndex]): - data[coordIndex - 1] += data[coordIndex] - del data[coordIndex] - _num_path_segments_removed += 1 - else: - coordIndex += 1 - if cmd in ['m', 'l'] and len(data) > 3 and not has_markers: - coordIndex = 2 - while coordIndex < len(data): - if is_same_slope(data[coordIndex-2], data[coordIndex-1], data[coordIndex], data[coordIndex+1]): - data[coordIndex - 2] += data[coordIndex] - data[coordIndex - 1] += data[coordIndex+1] - del data[coordIndex] - del data[coordIndex] - _num_path_segments_removed += 1 - else: - coordIndex += 2 + if not has_markers: + for pathIndex in range(len(path)): + cmd, data = path[pathIndex] + + # the first (moveto) command in a path is always absolute, so we have to skip it + startIndex = (pathIndex == 0) + + if cmd in ['h', 'v'] and len(data) > startIndex+1: # h,v expect only one parameter + coordIndex = startIndex + while coordIndex+1 < len(data): + if is_same_sign(data[coordIndex], data[coordIndex+1]): + data[coordIndex] += data[coordIndex+1] + del data[coordIndex+1] + _num_path_segments_removed += 1 + else: + coordIndex += 1 + elif cmd in ['m', 'l'] and len(data) > (startIndex+1)*2: # m,l expect two parameters + coordIndex = startIndex * 2 + while coordIndex+2 < len(data): + if is_same_slope(*data[coordIndex:coordIndex+4]): + data[coordIndex] += data[coordIndex+2] + data[coordIndex+1] += data[coordIndex+3] + del data[coordIndex+2] # delete the next two elements + del data[coordIndex+2] + _num_path_segments_removed += 1 + else: + coordIndex += 2 # it is possible that we have consecutive h, v, c, t commands now # so again collapse all consecutive commands of the same type into one command