コード例 #1
0
ファイル: bdf.py プロジェクト: begss/neosiji
 def parse(name, value):
     words = fnutil.split_words(name, value, 4)
     return BBX(
         fnutil.parse_dec('width', words[0], 1, DPARSE_LIMIT),
         fnutil.parse_dec('height', words[1], 1, DPARSE_LIMIT),
         fnutil.parse_dec('bbxoff', words[2], -DPARSE_LIMIT, DPARSE_LIMIT),
         fnutil.parse_dec('bbyoff', words[3], -DPARSE_LIMIT, DPARSE_LIMIT))
コード例 #2
0
	def expand(self):
		# PREXPAND / VERTICAL
		ascent = self.props.get('FONT_ASCENT')
		descent = self.props.get('FONT_DESCENT')
		px_ascent = 0 if ascent is None else fnutil.parse_dec('FONT_ASCENT', ascent, 0, bdf.DPARSE_LIMIT)
		px_descent = 0 if descent is None else fnutil.parse_dec('FONT_DESCENT', descent, 0, bdf.DPARSE_LIMIT)

		for char in self.chars:
			px_ascent = max(px_ascent, char.bbx.height + char.bbx.yoff)
			px_descent = max(px_descent, -char.bbx.yoff)

		self.bbx.height = px_ascent + px_descent
		self.bbx.yoff = -px_descent

		# EXPAND / HORIZONTAL
		total_width = 0
		self.min_width = self.chars[0].bbx.width

		for char in self.chars:
			self._expand(char)
			self.min_width = min(self.min_width, char.bbx.width)
			self.bbx.width = max(self.bbx.width, char.bbx.width)
			self.bbx.xoff = min(self.bbx.xoff, char.bbx.xoff)
			total_width += char.bbx.width

		self.avg_width = round(total_width / len(self.chars))
		self.props.set('FONTBOUNDINGBOX', self.bbx)
コード例 #3
0
	def parse(self, name, value, params):
		if name == '-c':
			params.char_set = fnutil.parse_dec('charset', value, 0, 255)
		elif name == '-m':
			params.min_char = fnutil.parse_dec('minchar', value, 0, 255)
		elif name == '-f':
			if value in FNT_FAMILIES:
				params.fnt_family = FNT_FAMILIES.index(value)
			else:
				raise Exception('invalid fnt family')
		elif name == '-o':
			params.output = value
		else:
			self.fallback(name, params)
コード例 #4
0
	def parse(self, name, optarg):
		if name == '-c':
			self.char_set = fnutil.parse_dec('charset', optarg, 0, 255)
		elif name == '-m':
			self.min_char = fnutil.parse_dec('minchar', optarg, 0, 255)
		elif name == '-f':
			if optarg in FNT_FAMILIES:
				self.fnt_family = FNT_FAMILIES.index(optarg)
			else:
				raise Exception('invalid fnt family')
		elif name == '-o':
			self.output = optarg
		else:
			fncli.Options.parse(self, name, optarg)
コード例 #5
0
	def get_ascent(self):
		ascent = self.props.get('FONT_ASCENT')

		if ascent is not None:
			return fnutil.parse_dec('FONT_ASCENT', ascent, -HEIGHT_MAX, HEIGHT_MAX)

		return self.bbx.height + self.bbx.yoff
コード例 #6
0
ファイル: bdfcheck.py プロジェクト: begss/neosiji
	def check_prop(self, line):
		match = re.fullmatch(br'(\w+)\s+([-\d"].*)', line)

		if not match:
			raise Exception('invalid property format')

		name = match.group(1)
		value = match.group(2)

		if value.startswith(b'"'):
			if len(value) < 2 or not value.endswith(b'"'):
				raise Exception('no closing double quote')
			if re.search(b'[^"]"[^"]', value[1 : len(value) - 1]):
				raise Exception('unescaped double quote')
		else:
			fnutil.parse_dec('value', value, None, None)

		self.append(self.parsed.dupl_props, self.proplocs, name)
		return b'P%d 1' % self.line_no
コード例 #7
0
ファイル: otb1exp.py プロジェクト: begss/neosiji
 def parse(self, name, value, params):
     if name == '-d':
         params.dir_hint = fnutil.parse_dec('DIR-HINT', value, -2, 2)
     elif name == '-e':
         params.em_size = fnutil.parse_dec('EM-SIZE', value, EM_SIZE_MIN,
                                           EM_SIZE_MAX)
     elif name == '-g':
         params.line_gap = fnutil.parse_dec('LINE-GAP', value, 0,
                                            EM_SIZE_MAX << 1)
     elif name == '-l':
         params.low_ppem = fnutil.parse_dec('LOW-PPEM', value, 1,
                                            bdf.DPARSE_LIMIT)
     elif name == '-E':
         params.encoding = value
     elif name == '-W':
         params.w_lang_id = fnutil.parse_hex('WLANG-ID', value, 0, 0x7FFF)
     elif name == '-X':
         params.x_max_extent = False
     elif name == '-L':
         params.single_loca = True
     elif name == '-P':
         params.post_names = True
     else:
         self.fallback(name, params)
コード例 #8
0
 def _parse(name, value, limit_x, limit_y):
     words = fnutil.split_words(name, value, 2)
     return Width(fnutil.parse_dec('width x', words[0], -limit_x, limit_x),
                  fnutil.parse_dec('width y', words[1], -limit_y, limit_y))
コード例 #9
0
ファイル: bdf.py プロジェクト: begss/neosiji
 def parse(name, value, limit):
     words = fnutil.split_words(name, value, 2)
     return Width(fnutil.parse_dec(name + '.x', words[0], -limit, limit),
                  fnutil.parse_dec(name + '.y', words[1], -limit, limit))
コード例 #10
0
ファイル: bdf.py プロジェクト: begss/neosiji
    def _read(self, input):
        # HEADER
        line = input.read_line()

        if self.props.parse(line, 'STARTFONT') != b'2.1':
            raise Exception('STARTFONT 2.1 expected')

        self.xlfd = self.props.read(input, '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.props.read(input, 'SIZE')
        self.bbx = self.props.read(input, 'FONTBOUNDINGBOX', BBX.parse)
        line = input.read_lines(skip_comments)

        if line and line.startswith(b'STARTPROPERTIES'):
            num_props = self.props.parse(line, 'STARTPROPERTIES',
                                         fnutil.parse_dec)

            for _ in range(0, num_props):
                line = input.read_lines(skip_comments)

                if line is None:
                    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 self.props.get(name) is not None:
                    raise Exception('duplicate property')

                if name == 'DEFAULT_CHAR':
                    self.default_code = fnutil.parse_dec(name, value)

                self.props[name] = value

            if self.props.read(input, 'ENDPROPERTIES') != b'':
                raise Exception('ENDPROPERTIES expected')

            line = input.read_lines(skip_comments)

        # GLYPHS
        num_chars = fnutil.parse_dec('CHARS', self.props.parse(line, 'CHARS'),
                                     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')

        # FINAL
        if input.read_lines(skip_comments) != b'ENDFONT':
            raise Exception('ENDFONT expected')

        if input.read_line() is not None:
            raise Exception('garbage after ENDFONT')

        return self
コード例 #11
0
ファイル: bdfcheck.py プロジェクト: begss/neosiji
	def check_size(value):
		words = fnutil.split_words('SIZE', value, 3)
		fnutil.parse_dec('point size', words[0], 1, None)
		fnutil.parse_dec('x resolution', words[1], 1, None)
		fnutil.parse_dec('y resolution', words[2], 1, None)
コード例 #12
0
ファイル: bdfcheck.py プロジェクト: begss/neosiji
	def append_code(self, value):
		fnutil.parse_dec('encoding', value)
		self.append(self.parsed.dupl_codes, self.codelocs, value)
コード例 #13
0
def main_program(nonopt, parsed):
    bstr = lambda number: bytes(str(number), 'ascii')

    # NON-OPTIONS
    if len(nonopt) < 4:
        raise Exception('invalid number of arguments, try --help')

    input = nonopt[0]
    registry = nonopt[1]
    encoding = nonopt[2]
    new_codes = []

    if not re.fullmatch(r'[A-Za-z][\w.:()]*', registry) or not re.fullmatch(
            r'[\w.:()]+', encoding):
        raise Exception('invalid registry or encoding')

    # READ INPUT
    ifs = fnio.InputStream(input)

    try:
        old_font = bdf.Font.read(ifs)
        ifs.close()
    except Exception as ex:
        raise Exception(ifs.location() + str(ex))

    # READ TABLES
    def load_code(line):
        new_codes.append(fnutil.parse_hex('unicode', line))

    for name in nonopt[3:]:
        ifs = fnio.InputStream(name)

        try:
            ifs.read_lines(load_code)
            ifs.close()
        except Exception as ex:
            raise Exception(ifs.location() + str(ex))

    if not new_codes:
        raise Exception('no characters in the output font')

    # CREATE GLYPHS
    new_font = bdf.Font()
    charmap = {char.code: char for char in old_font.chars}
    index = 0
    unstart = 0
    family = parsed.family if parsed.family is not None else old_font.xlfd[
        bdf.XLFD.FAMILY_NAME]

    if parsed.filter:
        unstart = 32 if registry == 'ISO10646' else bdf.CHARS_MAX

    for code in new_codes:
        if code == 0xFFFF and parsed.filter:
            index += 1
            continue

        if code in charmap:
            old_char = charmap[code]
            uni_ffff = False
        else:
            uni_ffff = True

            if code != 0xFFFF:
                raise Exception('%s does not contain U+%04X' % (input, code))

            if old_font.default_code != -1:
                old_char = charmap[old_font.default_code]
            elif 0xFFFD in charmap:
                old_char = charmap[0xFFFD]
            else:
                raise Exception(
                    '%s does not contain U+FFFF, and no replacement found' %
                    input)

        new_char = copy.copy(old_char)
        new_char.code = code if index >= unstart else index
        index += 1
        new_char.props = new_char.props.clone()
        new_char.props.set('ENCODING', bstr(new_char.code))
        new_font.chars.append(new_char)

        if uni_ffff:
            new_char.props.set('STARTCHAR', b'uniFFFF')
        elif old_char.code == old_font.default_code or (
                old_char.code == 0xFFFD and new_font.default_code == -1):
            new_font.default_code = new_char.code

    # CREATE HEADER
    registry = bytes(registry, 'ascii')
    encoding = bytes(encoding, 'ascii')

    for [name, value] in old_font.props:
        if name == 'FONT':
            new_font.xlfd = old_font.xlfd[:]
            new_font.xlfd[bdf.XLFD.FAMILY_NAME] = family
            new_font.xlfd[bdf.XLFD.CHARSET_REGISTRY] = registry
            new_font.xlfd[bdf.XLFD.CHARSET_ENCODING] = encoding
            value = b'-'.join(new_font.xlfd)
        elif name == 'STARTPROPERTIES':
            num_props = fnutil.parse_dec(name, value, 1)
        elif name == 'FAMILY_NAME':
            value = fnutil.quote(family)
        elif name == 'CHARSET_REGISTRY':
            value = fnutil.quote(registry)
        elif name == 'CHARSET_ENCODING':
            value = fnutil.quote(encoding)
        elif name == 'DEFAULT_CHAR':
            if new_font.default_code != -1:
                value = bstr(new_font.default_code)
            else:
                num_props -= 1
                continue
        elif name == 'ENDPROPERTIES':
            if new_font.default_code != -1 and new_font.props.get(
                    'DEFAULT_CHAR') is None:
                new_font.props.add('DEFAULT_CHAR', bstr(new_font.default_code))
                num_props += 1

            new_font.props.set('STARTPROPERTIES', bstr(num_props))
        elif name == 'CHARS':
            value = bstr(len(new_font.chars))

        new_font.props.add(name, value)

    # COPY FIELDS
    new_font.bbx = old_font.bbx
    new_font.finis = old_font.finis

    # WRITE OUTPUT
    ofs = fnio.OutputStream(parsed.output)

    try:
        new_font.write(ofs)
        ofs.close()
    except Exception as ex:
        raise Exception(ofs.location() + str(ex) + ofs.destroy())
コード例 #14
0
 def parse(name, value):
     words = fnutil.split_words(name, value, 4)
     return BBX(fnutil.parse_dec('width', words[0], 1, WIDTH_MAX),
                fnutil.parse_dec('height', words[1], 1, HEIGHT_MAX),
                fnutil.parse_dec('bbxoff', words[2], -WIDTH_MAX, WIDTH_MAX),
                fnutil.parse_dec('bbyoff', words[3], -WIDTH_MAX, WIDTH_MAX))
コード例 #15
0
    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
コード例 #16
0
 def get_ascent(self):
     try:
         return fnutil.parse_dec('FONT_ASCENT', self.props['FONT_ASCENT'],
                                 -HEIGHT_MAX, HEIGHT_MAX)
     except KeyError:
         return self.bbx.height + self.bbx.yoff
コード例 #17
0
ファイル: otb1exp.py プロジェクト: begss/neosiji
 def italic_angle(self):
     value = self.props.get('ITALIC_ANGLE')  # must be integer
     return fnutil.parse_dec('ITALIC_ANGLE', value, -45,
                             45) if value else -11.5 if self.italic else 0
コード例 #18
0
	def _read(self, input):
		# HEADER
		read_next = lambda: input.read_lines(lambda line: self.keep_comments(line))
		read_prop = lambda name, callback=None: self.props.parse(read_next(), name, callback)
		line = input.read_lines(Font.skip_empty)

		if self.props.parse(line, 'STARTFONT') != b'2.1':
			raise Exception('STARTFONT 2.1 expected')

		self.xlfd = read_prop('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')

		read_prop('SIZE')
		self.bbx = read_prop('FONTBOUNDINGBOX', BBX.parse)
		line = read_next()

		if line and line.startswith(b'STARTPROPERTIES'):
			num_props = self.props.parse(line, 'STARTPROPERTIES', fnutil.parse_dec)

			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.add(name, value)

			if read_prop('ENDPROPERTIES') != b'':
				raise Exception('ENDPROPERTIES expected')

			line = read_next()

		# GLYPHS
		num_chars = self.props.parse(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')

		# FINAL
		if input.read_lines(lambda line: self.keep_finishes(line)) != b'ENDFONT':
			raise Exception('ENDFONT expected')

		if input.read_lines(Font.skip_empty):
			raise Exception('garbage after ENDFONT')

		return self