Beispiel #1
0
    def restrict_format_0(self, raw, glyph_ids):
        if self._version == 0:
            version, length, coverage, npairs = unpack_from(b'>4H', raw)
            headerfmt = b'>3H'
        else:
            length, coverage, tuple_index, npairs = unpack_from(b'>L3H', raw)
            headerfmt = b'>L2H'

        offset = calcsize(headerfmt + b'4H')
        entries = []
        entrysz = calcsize(b'>2Hh')
        for i in xrange(npairs):
            try:
                left, right, value = unpack_from(b'>2Hh', raw, offset)
            except struct_error:
                offset = len(raw)
                break # Buggy kern table
            if left in glyph_ids and right in glyph_ids:
                entries.append(pack(b'>2Hh', left, right, value))
            offset += entrysz

        if offset != len(raw):
            raise UnsupportedFont('This font has extra data at the end of'
                    ' a Format 0 kern subtable')

        npairs = len(entries)
        if npairs == 0:
            return b''

		entry_selector = max_power_of_two(npairs)
		search_range = (2 ** entry_selector) * 6
		range_shift = (npairs - (2 ** entry_selector)) * 6
Beispiel #2
0
    def set_character_map(self, cmap):
        self.version, self.num_tables = 0, 1
        fmt = b'>7H'
        codes = list(cmap.iterkeys())
        codes.sort()

        if not codes:
            start_code = [0xffff]
            end_code = [0xffff]
        else:
            last_code = codes[0]
            end_code = []
            start_code = [last_code]

            for code in codes[1:]:
				if code == last_code + 1:
					last_code = code
					continue
				start, end = split_range(start_code[-1], last_code, cmap)
				start_code.extend(start)
				end_code.extend(end)
				start_code.append(code)
				last_code = code
			end_code.append(last_code)
			start_code.append(0xffff)
			end_code.append(0xffff)

		id_delta = []
		id_range_offset = []
		glyph_index_array = []
		for i in xrange(len(end_code)-1):  # skip the closing codes (0xffff)
			indices = []
			for char_code in xrange(start_code[i], end_code[i] + 1):
				indices.append(cmap[char_code])
			if  (indices == xrange(indices[0], indices[0] + len(indices))):
				id_delta_temp = set_id_delta(indices[0] - start_code[i])
				id_delta.append(id_delta_temp)
				id_range_offset.append(0)
			else:
				id_delta.append(0)
				id_range_offset.append(2 * (len(end_code) +
                    len(glyph_index_array) - i))
				glyph_index_array.extend(indices)
		id_delta.append(1)  # 0xffff + 1 == 0. So this end code maps to .notdef
		id_range_offset.append(0)

		seg_count = len(end_code)
		max_exponent = max_power_of_two(seg_count)
		search_range = 2 * (2 ** max_exponent)
		entry_selector = max_exponent
		range_shift = 2 * seg_count - search_range
Beispiel #3
0
    def __call__(self, stream=None):
        stream = BytesIO() if stream is None else stream

        def spack(*args):
            stream.write(pack(*args))

        stream.seek(0)

        # Write header
        num_tables = len(self.tables)
        ln2 = max_power_of_two(num_tables)
        srange = (2**ln2) * 16
        spack(b'>4s4H',
            self.sfnt_version, num_tables, srange, ln2, num_tables * 16 - srange)

        # Write tables
        head_offset = None
        table_data = []
        offset = stream.tell() + (calcsize(b'>4s3L') * num_tables)
        sizes = OrderedDict()
        for tag in self:
            table = self.tables[tag]
            raw = table()
            table_len = len(raw)
            if tag == b'head':
                head_offset = offset
                raw = raw[:8] + b'\0\0\0\0' + raw[12:]
            raw = align_block(raw)
            checksum = checksum_of_block(raw)
            spack(b'>4s3L', tag, checksum, offset, table_len)
            offset += len(raw)
            table_data.append(raw)
            sizes[tag] = table_len

        for x in table_data:
            stream.write(x)

        checksum = checksum_of_block(stream.getvalue())
        q = (0xB1B0AFBA - checksum) & 0xffffffff
        stream.seek(head_offset + 8)
        spack(b'>L', q)

        return stream.getvalue(), sizes
    def __call__(self, stream=None):
        stream = BytesIO() if stream is None else stream

        def spack(*args):
            stream.write(pack(*args))

        stream.seek(0)

        # Write header
        num_tables = len(self.tables)
        ln2 = max_power_of_two(num_tables)
        srange = (2**ln2) * 16
        spack(b'>4s4H',
            self.sfnt_version, num_tables, srange, ln2, num_tables * 16 - srange)

        # Write tables
        head_offset = None
        table_data = []
        offset = stream.tell() + (calcsize(b'>4s3L') * num_tables)
        sizes = OrderedDict()
        for tag in self:
            table = self.tables[tag]
            raw = table()
            table_len = len(raw)
            if tag == b'head':
                head_offset = offset
                raw = raw[:8] + b'\0\0\0\0' + raw[12:]
            raw = align_block(raw)
            checksum = checksum_of_block(raw)
            spack(b'>4s3L', tag, checksum, offset, table_len)
            offset += len(raw)
            table_data.append(raw)
            sizes[tag] = table_len

        for x in table_data:
            stream.write(x)

        checksum = checksum_of_block(stream.getvalue())
        q = (0xB1B0AFBA - checksum) & 0xffffffff
        stream.seek(head_offset + 8)
        spack(b'>L', q)

        return stream.getvalue(), sizes
Beispiel #5
0
    def restrict_format_0(self, raw, glyph_ids):
        if self._version == 0:
            version, length, coverage, npairs = unpack_from(b'>4H', raw)
            headerfmt = b'>3H'
        else:
            length, coverage, tuple_index, npairs = unpack_from(b'>L3H', raw)
            headerfmt = b'>L2H'

        offset = calcsize(headerfmt + b'4H')
        entries = []
        entrysz = calcsize(b'>2Hh')
        for i in range(npairs):
            try:
                left, right, value = unpack_from(b'>2Hh', raw, offset)
            except struct_error:
                offset = len(raw)
                break  # Buggy kern table
            if left in glyph_ids and right in glyph_ids:
                entries.append(pack(b'>2Hh', left, right, value))
            offset += entrysz

        if offset != len(raw):
            raise UnsupportedFont('This font has extra data at the end of'
                                  ' a Format 0 kern subtable')

        npairs = len(entries)
        if npairs == 0:
            return b''

        entry_selector = max_power_of_two(npairs)
        search_range = (2**entry_selector) * 6
        range_shift = (npairs - (2**entry_selector)) * 6

        entries = b''.join(entries)
        length = calcsize(headerfmt + b'4H') + len(entries)
        if self._version == 0:
            header = pack(headerfmt, version, length, coverage)
        else:
            header = pack(headerfmt, length, coverage, tuple_index)
        return header + pack(b'>4H', npairs, search_range, entry_selector,
                             range_shift) + entries
Beispiel #6
0
    def set_character_map(self, cmap):
        self.version, self.num_tables = 0, 1
        fmt = b'>7H'
        codes = list(cmap.iterkeys())
        codes.sort()

        if not codes:
            start_code = [0xffff]
            end_code = [0xffff]
        else:
            last_code = codes[0]
            end_code = []
            start_code = [last_code]

            for code in codes[1:]:
                if code == last_code + 1:
                    last_code = code
                    continue
                start, end = split_range(start_code[-1], last_code, cmap)
                start_code.extend(start)
                end_code.extend(end)
                start_code.append(code)
                last_code = code
            end_code.append(last_code)
            start_code.append(0xffff)
            end_code.append(0xffff)

        id_delta = []
        id_range_offset = []
        glyph_index_array = []
        for i in xrange(len(end_code) - 1):  # skip the closing codes (0xffff)
            indices = list(cmap[char_code]
                           for char_code in xrange(start_code[i], end_code[i] +
                                                   1))
            if indices == list(xrange(indices[0], indices[0] + len(indices))):
                # indices is a contiguous list
                id_delta_temp = set_id_delta(indices[0] - start_code[i])
                id_delta.append(id_delta_temp)
                id_range_offset.append(0)
            else:
                id_delta.append(0)
                id_range_offset.append(
                    2 * (len(end_code) + len(glyph_index_array) - i))
                glyph_index_array.extend(indices)
        id_delta.append(1)  # 0xffff + 1 == 0. So this end code maps to .notdef
        id_range_offset.append(0)

        seg_count = len(end_code)
        max_exponent = max_power_of_two(seg_count)
        search_range = 2 * (2**max_exponent)
        entry_selector = max_exponent
        range_shift = 2 * seg_count - search_range

        char_code_array = end_code + [0] + start_code
        char_code_array = pack(b'>%dH' % len(char_code_array),
                               *char_code_array)
        id_delta_array = pack(b'>%dh' % len(id_delta), *id_delta)
        rest_array = id_range_offset + glyph_index_array
        rest_array = pack(b'>%dH' % len(rest_array), *rest_array)
        data = char_code_array + id_delta_array + rest_array

        length = calcsize(fmt) + len(data)
        header = pack(fmt, 4, length, 0, 2 * seg_count, search_range,
                      entry_selector, range_shift)
        self.bmp_table = header + data

        fmt = b'>4HL'
        offset = calcsize(fmt)
        self.raw = pack(fmt, self.version, self.num_tables, 3, 1,
                        offset) + self.bmp_table
Beispiel #7
0
    def set_character_map(self, cmap):
        self.version, self.num_tables = 0, 1
        fmt = b'>7H'
        codes = sorted(cmap)

        if not codes:
            start_code = [0xffff]
            end_code = [0xffff]
        else:
            last_code = codes[0]
            end_code = []
            start_code = [last_code]

            for code in codes[1:]:
                if code == last_code + 1:
                    last_code = code
                    continue
                start, end = split_range(start_code[-1], last_code, cmap)
                start_code.extend(start)
                end_code.extend(end)
                start_code.append(code)
                last_code = code
            end_code.append(last_code)
            start_code.append(0xffff)
            end_code.append(0xffff)

        id_delta = []
        id_range_offset = []
        glyph_index_array = []
        for i in range(len(end_code)-1):  # skip the closing codes (0xffff)
            indices = list(cmap[char_code] for char_code in range(start_code[i], end_code[i] + 1))
            if indices == list(range(indices[0], indices[0] + len(indices))):
                # indices is a contiguous list
                id_delta_temp = set_id_delta(indices[0] - start_code[i])
                id_delta.append(id_delta_temp)
                id_range_offset.append(0)
            else:
                id_delta.append(0)
                id_range_offset.append(2 * (len(end_code) + len(glyph_index_array) - i))
                glyph_index_array.extend(indices)
        id_delta.append(1)  # 0xffff + 1 == 0. So this end code maps to .notdef
        id_range_offset.append(0)

        seg_count = len(end_code)
        max_exponent = max_power_of_two(seg_count)
        search_range = 2 * (2 ** max_exponent)
        entry_selector = max_exponent
        range_shift = 2 * seg_count - search_range

        char_code_array = end_code + [0] + start_code
        char_code_array = pack(b'>%dH'%len(char_code_array), *char_code_array)
        id_delta_array = pack(b'>%dh'%len(id_delta), *id_delta)
        rest_array = id_range_offset + glyph_index_array
        rest_array = pack(b'>%dH'%len(rest_array), *rest_array)
        data = char_code_array + id_delta_array + rest_array

        length = calcsize(fmt) + len(data)
        header = pack(fmt, 4, length, 0, 2*seg_count, search_range, entry_selector, range_shift)
        self.bmp_table = header + data

        fmt = b'>4HL'
        offset = calcsize(fmt)
        self.raw = pack(fmt, self.version, self.num_tables, 3, 1, offset) + self.bmp_table