|
#!/usr/bin/python |
|
|
|
import sys |
|
import getopt |
|
from time import time |
|
from math import sqrt |
|
from re import subn |
|
|
|
from svgpath import parse, get_d |
|
|
|
output = sys.stdout |
|
message = sys.stderr |
|
|
|
RADIUS = 32.0 |
|
label_it = False |
|
font_size = 6 |
|
font_color = 'brown' |
|
add_circle = True |
|
optimize = True |
|
join_paths = True |
|
|
|
CIRCLE_CONFIG = { |
|
'fill': 'none', |
|
'stroke': 'yellow', |
|
'stroke-width': 1, |
|
'opacity': 0, |
|
'stroke-opacity': 0.7, |
|
|
|
'hl-fill': 'yellow', |
|
'hl-stroke': 'yellow', |
|
'hl-stroke-width': 1, |
|
'hl-opacity': 0.5, |
|
'hl-stroke-opacity': 0.7, |
|
|
|
'sel-fill': 'pink', |
|
'sel-stroke': 'pink', |
|
'sel-stroke-width': 1, |
|
'sel-opacity': 0.7, |
|
'sel-stroke-opacity': 0.9, |
|
} |
|
|
|
def say(msg, *av, **kw): |
|
'Write a message to <message> stream.' |
|
if av: |
|
o = msg % av |
|
elif kw: |
|
o = msg % kw |
|
else: |
|
o = msg |
|
message.write(o) |
|
|
|
_last_N = 0 |
|
def tick(N, NN, n=4096): |
|
'Show some life on screen' |
|
global _last_N |
|
if NN == 0: |
|
_last_N = 0 |
|
say('\r\t' + ' ' * 40 + '\r') |
|
elif N - _last_N >= n: |
|
_last_N = N |
|
say('\r\t%8d / %8d (%s) ...', N, NN, per100(NN, NN - N)) |
|
|
|
def writer(obj): |
|
'Return a method to "write" to the <obj>' |
|
if hasattr(obj, 'write'): |
|
return obj.write |
|
return obj.append |
|
|
|
def flush(cache, output): |
|
if cache: |
|
wr = writer(output) |
|
while cache : |
|
wr(cache.pop(0)) |
|
|
|
def fetch_args(d): |
|
c = '' |
|
while d and d[0] in '0123456789. ,': |
|
c, d = c + d[0], d[1:] |
|
return map(float, c.replace(',', ' ').split()) |
|
|
|
def dM(entry): |
|
'Returns start coordinates of a path' |
|
d = get_d(entry).strip() |
|
if not d: |
|
return None |
|
closed = d.upper().endswith('Z') # not in use so far... |
|
if d.upper().startswith('M'): |
|
d = d[1:].strip() |
|
if d[0] in '0123456789.': |
|
x, y = fetch_args(d)[:2] |
|
else: |
|
x, y = 0.0, 0.0 |
|
return x, y, closed |
|
|
|
def add_css(call): |
|
'Insert CSS <style> section into the output.' |
|
call(('<style type="text/css">\n<![CDATA[\ncircle.boxId {\n' |
|
+ '\tfill: %(fill)s;\n\topacity: %(opacity).2f;\n' |
|
+ '\tstroke: %(stroke)s\n\tstroke-width: %(stroke-width)d;\n' |
|
+ '\tstroke-opacity: %(stroke-opacity).2f;\n' |
|
+ '}\ncircle.boxShowId {\n' |
|
+ '\tfill: %(hl-fill)s;\n\topacity: %(hl-opacity).2f;\n' |
|
+ '\tstroke: %(hl-stroke)s\n\tstroke-width: %(hl-stroke-width)d;\n' |
|
+ '\tstroke-opacity: %(hl-stroke-opacity).2f;\n' |
|
+ '}\ncircle.boxSelectId {\n' |
|
+ '\tfill: %(sel-fill)s;\n\topacity: %(sel-opacity).2f;\n' |
|
+ '\tstroke: %(sel-stroke)s\n\tstroke-width: %(sel-stroke-width)d;\n' |
|
+ '\tstroke-opacity: %(sel-stroke-opacity).2f;\n' |
|
+ '}\n]]>\n</style>\n') % CIRCLE_CONFIG) |
|
|
|
def circle(center, call): |
|
'Output the <circle/>' |
|
cx, cy = center |
|
call(('<circle cx="%(cx)d" cy="%(cy)d" r="%(r).0f" class="boxId" id="%(id)s" />') |
|
% {'cx': cx, 'cy': cy, 'r': RADIUS, 'id': 'C%08x' % p_serial}) |
|
|
|
def label(point, call): |
|
'Output a label as <text/>' |
|
x, y = point |
|
call('<text stroke="none" x="%.2f" y="%.2f" font-size="%d" fill="%s">P.%x</text>' |
|
% (x, y, font_size, font_color, p_serial)) |
|
|
|
def group(cache, output): |
|
'Output the IDentified <g> (plus <circle/> and <text/>, if any)' |
|
|
|
writer(output)('<g id="P%08x">' % (p_serial,)) |
|
|
|
if add_circle: |
|
circle(cache_avg(cache), writer(output)) |
|
|
|
if label_it: |
|
label(dM(cache[0])[:2], writer(output)) |
|
|
|
flush(cache, output) |
|
|
|
writer(output)('</g>\n') |
|
|
|
p_serial = 0 |
|
def make_group(cache, output): |
|
'Output IDentified group, if any cached' |
|
global p_serial |
|
|
|
if not cache: |
|
return |
|
|
|
if len(cache) == 1: |
|
return flush(cache, output) |
|
|
|
if p_serial == 0: |
|
writer(output)('<!-- Radius=%f -->\n' % (RADIUS,)) |
|
if add_circle: |
|
add_css(writer(output)) |
|
|
|
group(cache, output) |
|
p_serial += 1 |
|
|
|
def in_circle(x, y, cx, cy, r): |
|
'Weather the <x,y> point is in <cx,cy,r> circle?' |
|
dx, dy = x - cx, y - cy |
|
return (dx * dx + dy * dy) <= (r * r) |
|
|
|
def cache_rms(cache): |
|
'root mean square' |
|
cx, cy, N = 1.0, 1.0, 0 |
|
for entry in cache: |
|
x, y, c = dM(entry) |
|
cx += x * x |
|
cy += y * y |
|
N += 1 |
|
N = float(N) |
|
return sqrt(cx / N), sqrt(cy / N) |
|
|
|
def cache_am(cache): |
|
'arithmetic mean' |
|
cx, cy, N = 0.0, 0.0, 0 |
|
for entry in cache: |
|
x, y, c = dM(entry) |
|
cx += x |
|
cy += y |
|
N += 1 |
|
N = float(N) |
|
return cx / N, cy / N |
|
|
|
cache_avg = cache_am |
|
|
|
def same_place(entry, cache, delta): |
|
'Weather <entry> starts in about the same place as the rest of the cache do?' |
|
if not cache: |
|
return False |
|
x, y, c = dM(entry) |
|
cx, cy = cache_avg(cache) |
|
return in_circle(x, y, cx, cy, float(delta)) |
|
|
|
def parse_first_entry(cache): |
|
'Cut off and parse the 1st entry of the <cache> list.' |
|
if not cache: |
|
return None |
|
|
|
entry = source = cache.pop(0) |
|
|
|
assert entry.startswith('<') and entry.endswith('>') |
|
entry = entry[1:-1] |
|
|
|
closed = entry.endswith('/') |
|
if closed: |
|
entry = entry[:-1] |
|
|
|
tmp = entry.split() |
|
|
|
tag = tmp.pop(0) |
|
|
|
attributes = {} |
|
keep = [] |
|
while tmp: |
|
word = tmp.pop(0) |
|
if '="' in word: |
|
if keep: |
|
attr_name, attr_value = map(lambda x: x.strip('"'), (' '.join(keep)).split('=', 1)) |
|
attributes[attr_name] = attributes.get(attr_name, []) |
|
attributes[attr_name].append(attr_value) |
|
while keep: |
|
keep.pop(0) |
|
keep.append(word) |
|
if keep: |
|
attr_name, attr_value = map(lambda x: x.strip('"'), (' '.join(keep)).split('=', 1)) |
|
attributes[attr_name] = attributes.get(attr_name, []) |
|
attributes[attr_name].append(attr_value) |
|
return (tag, closed, attributes) |
|
|
|
def make_tag(tag, attributes, closed=False): |
|
'Reverse to the parse_first_entry() call -- returns the re-built entry.' |
|
entry = tag |
|
for attribute_name in sorted(attributes): |
|
for attribute_value in attributes[attribute_name]: |
|
if attribute_value is not None: |
|
entry += ' ' + attribute_name + '="' + attribute_value + '"' |
|
if closed: |
|
entry += ' /' |
|
return '<' + entry + '>' |
|
|
|
SVG_D_ABS_COMMANDS = 'MZLHVCSQTA' |
|
SVG_D_REL_COMMANDS = 'mzlhvcsqta' |
|
SVG_D_COMMANDS = SVG_D_ABS_COMMANDS + SVG_D_REL_COMMANDS |
|
SVG_D_WSP = ' \t\r\n' |
|
SVG_D_WSP_COMMA = SVG_D_WSP + ',' |
|
SVG_D_WSPC_OR_COMMAND = SVG_D_WSP_COMMA + SVG_D_COMMANDS |
|
SVG_D_DIGITS = '0123456789' |
|
SVG_D_NUMERICS = SVG_D_DIGITS + '.+-' # don't want to handle exponents here |
|
|
|
def simple_parse_d(ds): |
|
'Parse the d="" string (ds) into the list of tuples [(cmd, args...), ...]' |
|
if not ds: |
|
return None |
|
if ds[0] in SVG_D_NUMERICS: |
|
ds = 'M' + ds |
|
assert ds[0] in SVG_D_COMMANDS |
|
c, ds = ds[0], ds[1:] |
|
dl, n, tmp = [], '', [c] |
|
while ds: |
|
c, ds = ds[0], ds[1:] |
|
if c in SVG_D_NUMERICS: |
|
if c == '.': |
|
assert '.' not in n |
|
elif c in '+-': |
|
assert tmp[0] in SVG_D_REL_COMMANDS |
|
if n : |
|
tmp.append(n) |
|
n = '' |
|
n += c |
|
continue |
|
if c in SVG_D_WSPC_OR_COMMAND: |
|
if n: |
|
tmp.append(n) |
|
n = '' |
|
if c in SVG_D_COMMANDS: |
|
dl.append(tuple(tmp)) |
|
while tmp: |
|
tmp.pop() |
|
tmp.append(c) |
|
continue |
|
assert False, 'simple_parse_d @ ' + `c` |
|
tmp.append(n) |
|
dl.append(tuple(tmp)) |
|
return dl |
|
|
|
def simple_merge_d(dl): |
|
'reverse simple_parse_d() result' |
|
# join every tuple without space between command and 1st argument |
|
# then join the list tightly |
|
return ''.join(map(lambda cmd: ' '.join(cmd).replace(' ', '', 1), dl)) |
|
|
|
def optimize_d_HV(ds): |
|
'Replace (L)s with (H)s and (V)s respectively, track "current coordinate".' |
|
# eliminate moves to the last visited point first |
|
if not optimize: |
|
return ds |
|
ds = subn(r'(L(?P<x>[0-9.]+) (?P<y>[0-9.]+))M(?P=x) (?P=y)',r'\1',ds)[0].strip() |
|
dl, x0, y0, x, y, X, Y = [], None, None, None, None, None, None |
|
for entry in simple_parse_d(ds): |
|
# say('optimize_d_HV: entry=%s\n', `entry`) |
|
cmd, xyz = entry[0], entry[1:] |
|
if cmd == 'M': |
|
while xyz: # count anonymous (M)oves |
|
try: |
|
X, Y = xyz[:2] |
|
xyz = xyz[2:] |
|
except: |
|
say('\n\nBad coordinates:\nds=%s\nxyz=%s\n\n', `ds`, `xyz`) |
|
raise |
|
if x0 is None: |
|
x0, y0 = X, Y |
|
if x != X or y != Y: |
|
# skip (M)oves to already taken position |
|
dl.append(('M', X, Y)) |
|
x, y = X, Y |
|
elif cmd == 'L': |
|
while True: |
|
X, Y = xyz[:2] |
|
xyz = xyz[2:] |
|
if x0 is None: |
|
x0, y0 = x, y |
|
if x0 is None: |
|
x0, y0 = X, Y |
|
if x != X or y != Y: # ignore (L)ines to current point |
|
if x == X: |
|
dl.append(('V', Y)) |
|
elif y == Y: |
|
dl.append(('H', X)) |
|
else: |
|
dl.append(('L', X, Y)) |
|
x, y = X, Y |
|
if not xyz: |
|
break |
|
elif cmd == 'H': |
|
while True: |
|
X = xyz[:1] |
|
xyz = xyz[1:] |
|
x = X # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd == 'V': |
|
while True: |
|
Y = xyz[:1] |
|
xyz = xyz[1:] |
|
y = Y # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd == 'C': |
|
while True: |
|
_X1, _Y1, _X2, _Y2, X, Y = xyz[:6] |
|
xyz = xyz[6:] |
|
x, y = X, Y # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd in 'SQ': |
|
while True: |
|
_X2, _Y2, X, Y = xyz[:4] |
|
xyz = xyz[4:] |
|
x, y = X, Y # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd == 'T': |
|
while True: |
|
X, Y = xyz[:2] |
|
xyz = xyz[2:] |
|
x, y = X, Y # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd == 'A': |
|
while True: |
|
_RX, _RY, _XR, _LAF, _SF, X, Y = xyz[:7] |
|
xyz = xyz[7:] |
|
x, y = X, Y # just update coordinates |
|
if not xyz: |
|
break |
|
dl.append(entry) |
|
elif cmd == 'Z': |
|
dl.append(('Z',)) |
|
x, y = x0, y0 |
|
x0 = y0 = None |
|
|
|
while xyz: |
|
_ = xyz[:1] |
|
xyz = xyz[1:] |
|
# x, y = X, Y # just update coordinates |
|
else: |
|
say('Unhandled command %s', `cmd`) |
|
x = y = None |
|
dl.append(entry) |
|
return simple_merge_d(dl) |
|
|
|
def optimize_d(d): |
|
'Optimizes a list of d-entries' |
|
if d and d[0]: |
|
# return optimize and map(optimize_d_HV, d) or d |
|
return map(optimize_d_HV, d) |
|
|
|
def per100(x, y): |
|
'returns string represtntation of (x-y)/x in percents' |
|
pc = (100.0 * float(x - y)) / float(x) |
|
return '%.1f%%' % (pc,) |
|
|
|
def load(filename): |
|
'Returns the entier data from a file.' |
|
with open(filename) as fp: |
|
return fp.read() |
|
|
|
def load_and_normalize(filename): |
|
'Performs initial phases of SVG processing: load, normalize, degroup' |
|
|
|
say('\tphase #0 -- loading...\n') |
|
data = load(filename) |
|
N0 = len(data) |
|
say('\t\t%d bytes loaded.\n', N0) |
|
|
|
def say_done(NX, N0=N0, extra=''): |
|
say('\t\tdone, %d bytes (%s saved)%s.\n', NX, per100(N0, NX), extra) |
|
|
|
say('\tphase #1 -- normalizing spaces...\n') |
|
data = (' '.join(data.split())).replace('> <', '><') |
|
N1 = len(data) |
|
say_done(N1) |
|
|
|
say('\tphase #2 -- removing single path groups (<g><path/></g> becomes <path/>)...\n') |
|
count = 0 |
|
cnt = -1 |
|
while cnt: |
|
data, cnt = subn(r'<g>(<path[^>]+>)</g>', r'\1', data) |
|
count += cnt |
|
N2 = len(data) |
|
say_done(N2, extra=', %d groups removed' % count) |
|
|
|
return N0, data |
|
|
|
def regroup(cache): |
|
'Gather <path>es to <g>roups on their attributes.' |
|
o = '' |
|
g = None |
|
save, count = None, 0 |
|
while cache: |
|
tag, closed, attributes = parse_first_entry(cache) |
|
d = {'d': optimize_d(attributes.pop('d', [None]))} |
|
xattr = attributes.copy() |
|
xattr.update(d) |
|
entry = make_tag(tag, xattr, closed) |
|
fixed = make_tag(tag, d, closed) |
|
|
|
if g == attributes: |
|
# at least 2 adjacent tags found... |
|
if save: |
|
# <g> and the 1st one |
|
o += make_tag('g', g) + save[0] |
|
save = None |
|
o += fixed # next one |
|
count += 1 |
|
continue |
|
|
|
if g: |
|
# end of group (single entry groups have no <g></g> braces) |
|
o += save and save[1] or '</g>' |
|
|
|
g = attributes # new group suspection |
|
save = fixed, entry, tag, closed, attributes, d |
|
count = 1 |
|
if save: |
|
o += save[1] |
|
if g and count > 1: |
|
o += '</g>' |
|
return o |
|
|
|
def group_path_entries(data): |
|
'Grab <path>es and try to <g>roups them.' |
|
N, NN = 0, len(data) |
|
cache = [] |
|
R = '' |
|
tick(0, 0) |
|
for line in data.replace('>', '>\n').splitlines(): |
|
N += len(line) |
|
tick(N, NN) |
|
|
|
if line.startswith('<path'): |
|
cache.append(line) |
|
else: |
|
R += regroup(cache) + line |
|
tick(0, 0) |
|
R += regroup(cache) |
|
return len(R), R |
|
|
|
def byte_size_of_list(data): |
|
'Returns len(''.join(data))' |
|
return reduce(lambda x, y: (x and ((type(x) == int) and x or len(x)) or 0) + len(y), data) |
|
|
|
def squeeze_svg(data): |
|
'Reduce size of the resulting SVG by removing extraneous chars' |
|
|
|
zerz = '0' * (8 - len('%x' % (p_serial,))) |
|
data, cnt = subn(r' id="([PC])(' + zerz + r')([0-9a-f]+)"', # remove extraneous zeroes in IDs |
|
r' id="\1\3"', data) |
|
# say('\t\t%d zeroes removed\n', len(zerz) * cnt) |
|
|
|
if join_paths: |
|
cnt = -1 |
|
while cnt: # join adjacent <path>s |
|
data, cnt = subn(r'<path d="([^"]+)" /><path d="([^"]+)" />', |
|
r'<path d="\1 \2" />', data) |
|
|
|
# one may want to get rid of <path>es like that one: |
|
# <path d="M376.99 373.27H383.31V377.95H376.99V373.27Z" fill="black" fill-rule="nonzero" /> |
|
cnt = -1 |
|
while cnt: |
|
data, cnt = subn(r'<path d="M[0-9. ,LHV]+Z" fill="black" fill-rule="nonzero" />', |
|
r'', data) # black spills over labels we don't want to see |
|
|
|
cnt = -1 |
|
while cnt: # ungroup single path groups: <g a=x><path/></g> becomes <path a=x/> |
|
data, cnt = subn(r'<g id="(P[^"]+)"><path d="([^"]+)" /></g>', # just NOP with <circle>s |
|
r'<path id="\1" d="\2" />', data) |
|
return len(data), data |
|
|
|
def perform_svg_path_grouping(data): |
|
'Move the pathes that starts in nearly same place (within RADIUS) to an IDentified group.' |
|
cache = [] |
|
out = [] |
|
N, NN = 0, len(data) |
|
tick(0, 0) |
|
for line in data.replace('>', '>\n').splitlines(): |
|
N += len(line) |
|
tick(N, NN) |
|
|
|
if line.startswith('<path'): |
|
if not same_place(line, cache, RADIUS): |
|
make_group(cache, out) |
|
cache.append(line) |
|
else: |
|
if cache: |
|
make_group(cache, out) |
|
out.append(line) |
|
flush(cache, out) |
|
tick(0, 0) |
|
out = ''.join(out) |
|
return len(out), out |
|
|
|
def perform_svg_path_optimization(fname): |
|
say('Performing SVG optimization (%s -> %s)...\n', fname, output.name) |
|
|
|
N0, data = load_and_normalize(fname) # phases 0, 1, 2 |
|
|
|
def say_done(NX, N0=N0): |
|
say('\t\tdone, %d bytes (%s saved).\n', NX, per100(N0, NX)) |
|
|
|
say('\tphase #3 -- grouping pathes on attributes%s...\n', |
|
optimize and ', optimizing d' or '') |
|
N3, data = group_path_entries(data) |
|
say_done(N3) |
|
|
|
say('\tphase #4 -- grouping pathes using %s in radius of %.2f, %s circles...\n', |
|
cache_avg.__doc__, RADIUS, add_circle and 'with' or 'without') |
|
N4, data = perform_svg_path_grouping(data) |
|
say_done(N4) |
|
|
|
say('\tphase #5 -- fixing IDs%s (%d > P%x)...\n', |
|
join_paths and ', joining pathes' or '', p_serial, p_serial - 1) |
|
N5, data = squeeze_svg(data) |
|
say_done(N5) |
|
|
|
output.write(data) |
|
return N0 |
|
|
|
def handle_file(fname): |
|
'Convert this one file.' |
|
p0 = p_serial |
|
t0 = time() |
|
N = perform_svg_path_optimization(fname) |
|
pn = p_serial - p0 |
|
t1 = time() |
|
say('%s groups found using radius of %.2f and %s in %d lines for %.2f seconds.\n', |
|
pn or 'No', RADIUS, cache_avg.__doc__, N, t1 - t0) |
|
|
|
def help_values(): |
|
hv = { |
|
'r': RADIUS, |
|
'a': cache_avg.__doc__, |
|
'l': label_it, |
|
'C': font_color, |
|
'S': font_size, |
|
'R': add_circle, |
|
'O': optimize, |
|
'J': join_paths, |
|
'o': output.name, |
|
} |
|
hv.update(CIRCLE_CONFIG) |
|
return hv |
|
|
|
HELP = '''[options] <files...> |
|
|
|
Options: |
|
-h, --help -- this help |
|
|
|
-o, --output=<F> -- write output to a file (=%(o)s) |
|
|
|
-r, --radius=<R> -- radius to group pathes within (=%(r).2f) |
|
-a, --average=<M> -- algo to calc averages ('A' or 'S') (=%(a)s) |
|
|
|
-R, --add-circle -- add <circle> to any idenitified <g>roup (=%(R)s) |
|
--fill=<X> -- fill="%(fill)s" |
|
--stroke=<X> -- stroke="%(stroke)s" |
|
--stroke-width=<X> -- stroke-width="%(stroke-width)s" |
|
--opacity=<X> -- opacity="%(opacity)s" |
|
--stroke-opacity=<X> -- stroke-opacity="%(stroke-opacity)s" |
|
|
|
-O, --optimize -- do/dont run SVG path optimization (=%(O)s) |
|
-J, --join-paths -- do/dont join adjacent <path>s (=%(J)s) |
|
|
|
Debug tools: |
|
-l, --label -- add labels to groups (=%(l)s) |
|
-C, --font-color=<C> -- use this font color (=%(C)s) |
|
-S, --font-size=<S> -- use this font size (=%(S)d) |
|
''' |
|
|
|
def main(): |
|
try: |
|
opts, args = getopt.getopt( |
|
sys.argv[1:], |
|
'hr:a:lS:C:ROJo:', |
|
('help', |
|
'radius=', |
|
'average=', |
|
'label', |
|
'font-size=', |
|
'font-color=', |
|
'add-circle', |
|
'fill=', |
|
'stroke=', |
|
'stroke-width=', |
|
'opacity=', |
|
'stroke-opacity=', |
|
'optimize', |
|
'join-paths', |
|
'output=', |
|
) |
|
) |
|
except getopt.error, why: |
|
sys.stderr.write(`why`) |
|
return 1 |
|
else: |
|
for o, v in opts: |
|
if o in ('-h', '--help'): |
|
print sys.argv[0], HELP % help_values() |
|
return 0 |
|
elif o in ('-o', '--output'): |
|
global output |
|
output = (v == '-') and sys.stdout or open(v, 'w') |
|
elif o in ('-O', '--no-optimize'): |
|
global optimize |
|
optimize = not optimize |
|
elif o in ('-S', '--font-size'): |
|
global font_size |
|
font_size = int(v) |
|
elif o in ('-C', '--font-color'): |
|
global font_color |
|
font_color = v |
|
elif o in ('-R', '--add-circle'): |
|
global add_circle |
|
add_circle = not add_circle |
|
elif o in ('-l', '--label'): |
|
global label_it |
|
label_it = not label_it |
|
elif o in ('-a', '--average'): |
|
global cache_avg |
|
if v.upper()[0] in ('A', 'M'): |
|
cache_avg = cache_am |
|
elif v.upper()[0] in ('R', 'S', 'Q'): |
|
cache_avg = cache_rms |
|
else: |
|
sys.stderr.write('I dunno how to use "%s" method.\n' % (v,)) |
|
return 1 |
|
elif o in ('-r', '--radius'): |
|
global RADIUS |
|
RADIUS=float(v) |
|
elif o in ('-J', '--join-paths'): |
|
global join_paths |
|
join_paths = not join_paths |
|
elif o == '--fill': |
|
CIRCLE_CONFIG['fill'] = v |
|
elif o == '--stroke': |
|
CIRCLE_CONFIG['stroke'] = v |
|
elif o == '--stroke-width': |
|
CIRCLE_CONFIG['stroke-width'] = int(v) |
|
elif o == '--opacity': |
|
CIRCLE_CONFIG['opacity'] = float(v) |
|
elif o == '--stroke-opacity': |
|
CIRCLE_CONFIG['stroke-opacity'] = float(v) |
|
if label_it: |
|
sys.stderr.write('Label with font size of %d and color of "%s".\n' % (font_size, font_color)) |
|
if not args: |
|
print sys.argv[0], HELP % help_values() |
|
return 1 |
|
for arg in args: |
|
handle_file(arg) |
|
return 0 |
|
|
|
if __name__ == '__main__': |
|
sys.exit(main()) |
|
|
|
# EOF # |