def check_line(self, line): if re.search(b'[^\t\f\v\x20-\xff]', line): raise Exception('control character(s)') if self.parsed.ascii_chars and re.search(b'[\x7f-\xff]', line): fnutil.warning(self.location(), 'non-ascii character(s)') if self.mode == MODE.META: if not self.xlfd_name and line.startswith(b'FONT'): line = self.check_font(line) self.xlfd_name = True else: for handler in self.handlers: if line.startswith(handler[0]): handler[1](line[len(handler[0]):].lstrip()) break elif self.mode == MODE.PROPS: if line.startswith(b'ENDPROPERTIES'): self.mode = MODE.META else: line = self.check_prop(line) else: # MODE.BITMAP if line.startswith(b'ENDCHAR'): self.mode = MODE.META else: self.check_bitmap(line) return line
def check_italic(self, prefix, verb='will'): slant = str(self.xlfd[XLFD.SLANT], 'ascii') consider = ['Regular', 'Italic'][self.get_italic()] if slant[:1].upper() != consider[:1].upper(): fnutil.warning( prefix, 'slant "%s" %s be considered %s' % (slant, verb, consider))
def check_bold(self, prefix, verb='will'): weight = str(self.xlfd[XLFD.WEIGHT_NAME], 'ascii') compare = weight.lower() consider = ['Normal', 'Bold'][self.get_bold()] if compare == 'medium': compare = 'normal' if compare != consider.lower(): fnutil.warning( prefix, 'weight "%s" %s be considered %s' % (weight, verb, consider))
def read_otb(ifs): if parsed.real_time: try: stat = ifs.fstat() if stat: parsed.created = datetime.fromtimestamp( stat.st_ctime, timezone.utc) parsed.modified = datetime.fromtimestamp( stat.st_mtime, timezone.utc) except Exception as ex: fnutil.warning(ifs.location(), str(ex)) return otb1exp.Font.read(ifs, parsed)
def check_bitmap(self, line): if len(line) != self.last_box.row_size() * 2: raise Exception('invalid bitmap length') data = codecs.decode(line, 'hex') if self.parsed.extra_bits: check_x = (self.last_box.width - 1) | 7 last_byte = data[len(data) - 1] bit_no = 7 - (self.last_box.width & 7) for x in range(self.last_box.width, check_x + 1): if last_byte & (1 << bit_no): fnutil.warning(self.location(), 'extra bit(s) starting with x=%d' % x) break bit_no -= 1
def check_font(self, value): xlfd = value[4:].lstrip().split(b'-', 15) if len(xlfd) == 15 and xlfd[0] == b'': unicode = (xlfd[bdf.XLFD.CHARSET_REGISTRY].upper() == b'ISO10646') if self.parsed.dupl_codes == -1: self.parsed.dupl_codes = unicode if self.parsed.dupl_names == -1: self.parsed.dupl_names = unicode if self.parsed.common_weight: weight = str(xlfd[bdf.XLFD.WEIGHT_NAME], 'ascii') compare = weight.lower() consider = 'Bold' if 'bold' in compare else 'Normal' if compare in ['medium', 'regular']: compare = 'normal' if compare != consider.lower(): fnutil.warning(self.location(), 'weight "%s" may be considered %s' % (weight, consider)) if self.parsed.common_slant: slant = str(xlfd[bdf.XLFD.SLANT], 'ascii') consider = 'Italic' if re.search('^[IO]', slant) else 'Regular' if not re.fullmatch('[IOR]', slant): fnutil.warning(self.location(), 'slant "%s" may be considered %s' % (slant, consider)) else: if self.parsed.xlfd_fontnm: fnutil.warning(self.location(), 'non-XLFD font name') value = b'FONT --------------' return value
def check_attr(self, value): if not re.fullmatch(br'[\dA-Fa-f]{4}', value): raise Exception('ATTRIBUTES must be 4 hex-encoded characters') if self.parsed.attributes: fnutil.warning(self.location(), 'ATTRIBUTES may cause problems with freetype')
def check_width(self, name, value, parse): if self.parsed.ywidth_zero and parse(name, value).y != 0: fnutil.warning(self.location(), 'non-zero %s Y' % name)
def _read(self, input): # HEADER line = input.read_line() read_next = lambda: input.read_lines(_Base.skip_comments) if self.set_prop(line, 'STARTFONT') != b'2.1': raise Exception('STARTFONT 2.1 expected') self.xlfd = self.set_prop(read_next(), 'FONT', lambda name, value: value.split(b'-', 15)) if len(self.xlfd) != 15 or self.xlfd[0] != b'': raise Exception('non-XLFD font names are not supported') self.set_prop(read_next(), 'SIZE') self.bbx = self.set_prop(read_next(), 'FONTBOUNDINGBOX', lambda name, value: BBX.parse(name, value)) line = read_next() if line and line.startswith(b'STARTPROPERTIES'): num_props = self.set_prop( line, 'STARTPROPERTIES', lambda name, value: fnutil.parse_dec(name, value)) start_index = len(self.props) for _ in range(0, num_props): line = read_next() if not line: raise Exception('property expected') match = re.fullmatch(br'(\w+)\s+([\d"].*)', line) if not match: raise Exception('invalid property format') name = str(match.group(1), 'ascii') value = match.group(2) if name == 'DEFAULT_CHAR': self.default_code = fnutil.parse_dec(name, value) self.props[name] = value if self.set_prop(read_next(), 'ENDPROPERTIES') != b'': raise Exception('ENDPROPERTIES expected') if len(self.props) != start_index + num_props + 1: fnutil.warning(input.location(), 'duplicate properties') self.props['STARTPROPERTIES'] = bytes(str(len(self.props)), 'ascii') line = read_next() # GLYPHS num_chars = self.set_prop( line, 'CHARS', lambda name, value: fnutil.parse_dec(name, value, 1, CHARS_MAX)) for _ in range(0, num_chars): self.chars.append(Char.read(input)) if next((char.code for char in self.chars if char.code == self.default_code), -1) != self.default_code: raise Exception('invalid DEFAULT_CHAR') # ENDING if read_next() != b'ENDFONT': raise Exception('ENDFONT expected') if read_next(): raise Exception('garbage after ENDFONT') return self