def select(self, spec): current = spec.get('face', _ctx._typestyle.face) if isinstance(current, basestring): current = font_face(current) axes = ('weight','width','italic','variant') opts = {k:v for k,v in spec.items() if k in axes} defaults = dict( (k, getattr(current, k)) for k in axes + ('wid', 'wgt')) # map the requested weight/width onto what's available in the family w_spans = {"wgt":[1,14], "wid":[-15,15]} for axis, num_axis in dict(weight='wgt', width='wid').items(): w_vals = [getattr(f, num_axis) for f in self._faces.values()] w_spans[num_axis] = [min(w_vals), max(w_vals)] dst = opts if axis in opts else defaults wname, wval = self._closest(axis, opts.get(axis, getattr(current,axis))) dst.update({axis:wname, num_axis:wval}) def score(axis, f): bonus = 2 if axis in opts else 1 val = opts[axis] if axis in opts else defaults.get(axis) vs = getattr(f,axis) if axis in ('wgt','wid'): w_min, w_max = w_spans[axis] agree = 1 if val==vs else -abs(val-vs) / float(max(w_max-w_min, 1)) elif axis in ('weight','width'): # agree = 1 if (val or None) == (vs or None) else 0 agree = 0 else: agree = 1 if (val or None) == (vs or None) else -1 return agree * bonus scores = ddict(int) for f in self.faces.values(): # consider = 'italic', 'weight', 'width', 'variant', 'wgt', 'wid' # print [score(axis,f) for axis in consider], [getattr(f,axis) for axis in consider] scores[f] += sum([score(axis,f) for axis in 'italic', 'weight', 'width', 'variant', 'wgt', 'wid']) candidates = [dict(score=s, face=f, ps=f.psname) for f,s in scores.items()] candidates.sort(key=itemgetter('ps')) candidates.sort(key=itemgetter('score'), reverse=True) # for c in candidates[:10]: # print " %0.2f"%c['score'], c['face'] return odict( (c['face'],c['score']) for c in candidates)
def __init__(self, txt): # configure the parsing machinery/callbacks p = expat.ParserCreate() p.StartElementHandler = self._enter p.EndElementHandler = self._leave p.CharacterDataHandler = self._chars self._expat = p # set up state attrs to record the parse results self.stack = [] self.cursor = 0 self.regions = ddict(list) self.body = [] try: # parse the input xml string if isinstance(txt, unicode): txt = txt.encode('utf-8') wrap = "<%s>" % ">%s</".join([DEFAULT]*2) self._expat.Parse(wrap%txt, True) except expat.ExpatError, e: # go a little overboard providing context for syntax errors line = self.xml.split('\n')[e.lineno-1] self._expat_error(e, line)