def type2(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 assert cmap12,'cmap format 12 table is needed' ourData = cmap12 deltaCodePoints = generateDeltaArray(ourData['startCodes']) lengths = ourData['lengths'] deltaGids = generateDeltaArray(ourData['gids']) nGroups = len(deltaGids) gos_data = Bits() escaped_data = Bits() gos_data.frombytes(struct.pack('>B',2)) #GOS type gos_data.frombytes(struct.pack('>H',nGroups)) for idx in xrange(nGroups): delta_code_result = NumberEncoders.BitEncodeAllOnesEscape(deltaCodePoints[idx],3) extend_bits_or_escape(gos_data, escaped_data, delta_code_result) len_result = NumberEncoders.BitEncodeAllOnesEscape(lengths[idx],2) extend_bits_or_escape(gos_data, escaped_data, len_result) gid_result = NumberEncoders.BitEncodeAllOnesEscape(deltaGids[idx],3) extend_bits_or_escape(gos_data, escaped_data, gid_result) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') whole_data = gos_data.tobytes() + escaped_data.tobytes() #print 'type2 size',len(whole_data) return whole_data
def type2(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13, _decompile_in_cmap_format_12_13, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 assert cmap12, 'cmap format 12 table is needed' ourData = cmap12 deltaCodePoints = generateDeltaArray(ourData['startCodes']) lengths = ourData['lengths'] deltaGids = generateDeltaArray(ourData['gids']) nGroups = len(deltaGids) gos_data = Bits() escaped_data = Bits() gos_data.frombytes(struct.pack('>B', 2)) #GOS type gos_data.frombytes(struct.pack('>H', nGroups)) for idx in xrange(nGroups): delta_code_result = NumberEncoders.BitEncodeAllOnesEscape( deltaCodePoints[idx], 3) extend_bits_or_escape(gos_data, escaped_data, delta_code_result) len_result = NumberEncoders.BitEncodeAllOnesEscape(lengths[idx], 2) extend_bits_or_escape(gos_data, escaped_data, len_result) gid_result = NumberEncoders.BitEncodeAllOnesEscape( deltaGids[idx], 3) extend_bits_or_escape(gos_data, escaped_data, gid_result) change_method(_c_m_a_p.cmap_format_12_or_13, old_12_method, 'decompile') whole_data = gos_data.tobytes() + escaped_data.tobytes() #print 'type2 size',len(whole_data) return whole_data
def type3(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 assert cmap12,'cmap format 12 table is needed' ourData = cmap12 deltaCodePoints = generateDeltaArray(ourData['startCodes']) lengths = ourData['lengths'] gids = ourData['gids'] nGroups = len(gids) gos_data = bitarray.bitarray(endian='big') extra_data = bitarray.bitarray(endian='big') gos_data.frombytes(struct.pack('>B',3)) #GOS type gos_data.frombytes(struct.pack('>H',nGroups)) for idx in xrange(nGroups): delta_code_result = NumberEncoders.AOE(deltaCodePoints[idx],5) add_to_extra_if_necessary(gos_data, extra_data, delta_code_result) len_result = NumberEncoders.AOE(lengths[idx],3) add_to_extra_if_necessary(gos_data, extra_data, len_result) gid_result = NumberEncoders.AOE(gids[idx],16) add_to_extra_if_necessary(gos_data, extra_data, gid_result) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') whole_data = gos_data.tobytes() + extra_data.tobytes() #print 'type3 size',len(whole_data) return whole_data
def clean_invalid_glyphs_and_remove_hinting(fontfile, hinting, output): whitespace_and_ignorable_list = get_whitespace_and_ignorable_list() cleaner = Cleaner(fontfile, hinting, whitespace_and_ignorable_list) cleaner.clean() # Flatten cmap format 4 (no idRangeOffset/glyphIdArray) so it is a simple # subset of format 12. change_method(_c_m_a_p.cmap_format_4,_cmap_format_4_compile, 'compile') cleaner.save(output) cleaner.close()
def __zero_cmaps(self,output): font = TTFont(output) old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap,'decompile') old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') old_4_method = change_method(_c_m_a_p.cmap_format_4,_decompile_in_cmap_format_4, 'decompile') cmap_offset = font.reader.tables['cmap'].offset cmapTables = font['cmap'] cmap12 = cmapTables.getcmap(3, 10) #format 12 cmap4 = cmapTables.getcmap(3, 1) #format 4 ranges_to_zero = [] if cmap12: ranges_to_zero.append((cmap_offset+cmap12.offset+16,cmap12.length-16)) #if cmap4: # ranges_to_zero.append((cmap_offset+cmap4.offset+14,cmap4.length-14)) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') change_method(_c_m_a_p.cmap_format_4,old_4_method,'decompile') change_method(_c_m_a_p.table__c_m_a_p,old_cmap_method,'decompile') font.close() #if len(ranges_to_zero)<2: #return if both doesn't exist # return for block in ranges_to_zero: filler = Filler(output) filler.fill(block[0], block[1], '\x00') filler.close()
def clean_invalid_glyphs_and_remove_hinting(fontfile, hinting, output, verbose): whitespace_and_ignorable_list = get_whitespace_and_ignorable_list() cleaner = Cleaner(fontfile, hinting, whitespace_and_ignorable_list) cleaner.clean(verbose) # Flatten cmap format 4 (no idRangeOffset/glyphIdArray) so it is a simple # subset of format 12. # do we still what this? change_method(_c_m_a_p.cmap_format_4, _cmap_format_4_compile, "compile") old_12_or_13_compile = change_method(_c_m_a_p.cmap_format_12_or_13, _cmap_format_12_or_13_compile, "compile") cleaner.save(output) cleaner.close() change_method(_c_m_a_p.cmap_format_12_or_13, old_12_or_13_compile, "compile")
def _getCM04(font): old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap,'decompile') cmap_offset = font.reader.tables['cmap'].offset cmapTables = font['cmap'] change_method(_c_m_a_p.table__c_m_a_p,old_cmap_method,'decompile') cmap12 = cmapTables.getcmap(3, 10) #format 12 cmap4 = cmapTables.getcmap(3, 1) #format 4 if cmap4 and cmap12: offset = cmap_offset + cmap4.offset length = cmap4.length #print 'cmap4 size',cmap4.length,'bytes' return pack('>LL',offset,length) return None
def _getCM12(font): old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap,'decompile') cmap_offset = font.reader.tables['cmap'].offset cmapTables = font['cmap'] change_method(_c_m_a_p.table__c_m_a_p,old_cmap_method,'decompile') cmap12 = cmapTables.getcmap(3, 10) #format 12 if cmap12: offset = cmap_offset + cmap12.offset nGroups =cmap12.nGroups #print 'cmap12 size',cmap12.length,'bytes' return pack('>LL',offset,nGroups) return None
def type5(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 assert cmap12,'cmap format 12 table is needed' ourData = cmap12 nGroups = len(ourData['startCodes']) gos_data = bytearray() gos_data.extend(struct.pack('>B',5)) gos_data.extend(struct.pack('>H',nGroups)) for i in xrange(nGroups): gos_data.extend(struct.pack('>LLL',ourData['startCodes'][i],ourData['lengths'][i],ourData['gids'][i])) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') #print 'type5 size',len(gos_data) return gos_data
def _getCM04(font): old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap, 'decompile') cmap_offset = font.reader.tables['cmap'].offset cmapTables = font['cmap'] change_method(_c_m_a_p.table__c_m_a_p, old_cmap_method, 'decompile') cmap12 = cmapTables.getcmap(3, 10) #format 12 cmap4 = cmapTables.getcmap(3, 1) #format 4 if cmap4 and cmap12: offset = cmap_offset + cmap4.offset length = cmap4.length #print 'cmap4 size',cmap4.length,'bytes' return pack('>LL', offset, length) return None
def _getCM12(font): old_cmap_method = change_method(_c_m_a_p.table__c_m_a_p, _decompile_in_table_cmap, 'decompile') cmap_offset = font.reader.tables['cmap'].offset cmapTables = font['cmap'] change_method(_c_m_a_p.table__c_m_a_p, old_cmap_method, 'decompile') cmap12 = cmapTables.getcmap(3, 10) #format 12 if cmap12: offset = cmap_offset + cmap12.offset nGroups = cmap12.nGroups #print 'cmap12 size',cmap12.length,'bytes' return pack('>LL', offset, nGroups) return None
def clean_invalid_glyphs_and_remove_hinting(fontfile, hinting, output, verbose): whitespace_and_ignorable_list = get_whitespace_and_ignorable_list() cleaner = Cleaner(fontfile, hinting, whitespace_and_ignorable_list) cleaner.clean(verbose) # Flatten cmap format 4 (no idRangeOffset/glyphIdArray) so it is a simple # subset of format 12. # do we still what this? change_method(_c_m_a_p.cmap_format_4, _cmap_format_4_compile, 'compile') old_12_or_13_compile = change_method(_c_m_a_p.cmap_format_12_or_13, _cmap_format_12_or_13_compile, 'compile') cleaner.save(output) cleaner.close() change_method(_c_m_a_p.cmap_format_12_or_13, old_12_or_13_compile, 'compile')
def type5(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13, _decompile_in_cmap_format_12_13, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 assert cmap12, 'cmap format 12 table is needed' ourData = cmap12 nGroups = len(ourData['startCodes']) gos_data = bytearray() gos_data.extend(struct.pack('>B', 5)) gos_data.extend(struct.pack('>H', nGroups)) for i in xrange(nGroups): gos_data.extend( struct.pack('>LLL', ourData['startCodes'][i], ourData['lengths'][i], ourData['gids'][i])) change_method(_c_m_a_p.cmap_format_12_or_13, old_12_method, 'decompile') #print 'type5 size',len(gos_data) return gos_data
def type4(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') old_4_method = change_method(_c_m_a_p.cmap_format_4,_decompile_in_cmap_format_4, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 cmap4 = cmapTable.getcmap(3, 1).cmap #format 4 assert cmap12 and cmap4, 'Both cmap format 12 and 4 tables are needed' cmap4_endCodes = cmap4['endCode'] cmap4_startCodes = cmap4['startCode'] cmap12_startCodes = cmap12['startCodes'] cmap12_lengths = cmap12['lengths'] fmt12SegCount = len(cmap12_startCodes) fmt4SegCount = len(cmap4_startCodes) # TODO(bstell): the code in this section seems to only work if there number # of fmt4 segments is smaller than the number of fmt12 segments. assert fmt12SegCount >= (fmt4SegCount-1), '' #finds segment mappings fmt4Seg = 0 fmt12Seg = 0 mapping = defaultdict(list) while fmt12Seg < fmt12SegCount and fmt4Seg < fmt4SegCount: cmap12SegStart = cmap12_startCodes[fmt12Seg] cmap12SegEnd = cmap12_startCodes[fmt12Seg] + cmap12_lengths[fmt12Seg] - 1 cmap4SegStart =cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] if cmap12SegStart>= cmap4SegStart and cmap12SegEnd <= cmap4SegEnd: mapping[fmt4Seg].append(fmt12Seg) fmt12Seg += 1 elif cmap12SegStart > cmap4_endCodes[fmt4Seg]: fmt4Seg += 1 else: #case of where format12 segment overlap end of format4 segment print cmap12SegStart,cmap12SegEnd,cmap4_startCodes[fmt4Seg],cmap4_endCodes[fmt4Seg] raise('unexpected tables') # Handle format 4's special 0xFFFF segment #assert fmt4Seg == fmt4SegCount, 'only the 0xFFFF segment left' mapping[fmt4Seg] # Make an empty segment gos_data = Bits() escaped_data = Bits() gos_data.frombytes(struct.pack('>B',4)) #GOS type gos_data.frombytes(struct.pack('>H', fmt4SegCount)) #now checks if segments in good condition segLens = [] idRangeOffsets = cmap4['idRangeOffset'] idDelta = cmap4['idDelta'] for fmt4Seg,fmt12SegList in mapping.iteritems(): lenFmt12Segs = len(fmt12SegList) segLens.append(lenFmt12Segs) if lenFmt12Segs == 0: continue # check the segments cmap12SegStart = cmap12_startCodes[fmt12SegList[0]] cmap12SegEnd = cmap12_startCodes[fmt12SegList[-1]] + cmap12_lengths[fmt12SegList[-1]] - 1 cmap4SegStart = cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] assert cmap12SegStart == cmap4SegStart and cmap12SegEnd == cmap4SegEnd if lenFmt12Segs == 1: assert idRangeOffsets[fmt4Seg] == 0 else: assert idRangeOffsets[fmt4Seg] != 0 and idDelta[fmt4Seg] == 0 for segLen in segLens: encoded_value = NumberEncoders.BitEncodeAllOnesEscape(segLen,2) extend_bits_or_escape(gos_data, escaped_data, encoded_value) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') change_method(_c_m_a_p.cmap_format_4,old_4_method,'decompile') whole_data = gos_data.tobytes() + escaped_data.tobytes() #print 'type4 size',len(whole_data) return whole_data
def type4(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13,_decompile_in_cmap_format_12_13, 'decompile') old_4_method = change_method(_c_m_a_p.cmap_format_4,_decompile_in_cmap_format_4, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 cmap4 = cmapTable.getcmap(3, 1).cmap #format 4 assert cmap12 and cmap4, 'Both cmap format 12 and 4 tables are needed' cmap4_endCodes = cmap4['endCode'] cmap4_startCodes = cmap4['startCode'] cmap12_startCodes = cmap12['startCodes'] cmap12_lengths = cmap12['lengths'] fmt12SegCount = len(cmap12_startCodes) fmt4SegCount = len(cmap4_startCodes) - 1 # Don't compare 0xFFFF #finds segment mappings fmt4Seg = 0 fmt12Seg = 0 mapping = defaultdict(list) while fmt12Seg < fmt12SegCount and fmt4Seg < fmt4SegCount: cmap12SegStart = cmap12_startCodes[fmt12Seg] cmap12SegEnd = cmap12_startCodes[fmt12Seg] + cmap12_lengths[fmt12Seg] - 1 cmap4SegStart =cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] if cmap12SegStart>= cmap4SegStart and cmap12SegEnd <= cmap4SegEnd: mapping[fmt4Seg].append(fmt12Seg) fmt12Seg += 1 elif cmap12SegStart > cmap4_endCodes[fmt4Seg]: fmt4Seg += 1 else: #case of where format12 segment overlap end of format4 segment print cmap12SegStart,cmap12SegEnd,cmap4_startCodes[fmt4Seg],cmap4_endCodes[fmt4Seg] raise('unexpected tables') assert fmt4Seg >= fmt4SegCount - 2, 'all format 4 segments consumed,possibly except last one(startCode0xFFFF)' gos_data = bitarray.bitarray(endian='big') extra_data = bitarray.bitarray(endian='big') gos_data.frombytes(struct.pack('>B',4)) #GOS type gos_data.frombytes(struct.pack('>H',min(fmt4SegCount-1,fmt4Seg+1))) #now checks if segments in good condition segLens = [] idRangeOffsets = cmap4['idRangeOffset'] idDelta = cmap4['idDelta'] for fmt4Seg,fmt12SegList in mapping.iteritems(): lenFmt12Segs = len(fmt12SegList) cmap12SegStart = cmap12_startCodes[fmt12SegList[0]] cmap12SegEnd = cmap12_startCodes[fmt12SegList[-1]] + cmap12_lengths[fmt12SegList[-1]] - 1 cmap4SegStart =cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] segLens.append(lenFmt12Segs) assert cmap12SegStart == cmap4SegStart and cmap12SegEnd == cmap4SegEnd if lenFmt12Segs == 1: assert idRangeOffsets[fmt4Seg] == 0 else: assert idRangeOffsets[fmt4Seg] != 0 and idDelta[fmt4Seg] == 0 for segLen in segLens: enc_len = NumberEncoders.AOE(segLen,2) add_to_extra_if_necessary(gos_data, extra_data, enc_len) change_method(_c_m_a_p.cmap_format_12_or_13,old_12_method,'decompile') change_method(_c_m_a_p.cmap_format_4,old_4_method,'decompile') whole_data = gos_data.tobytes() + extra_data.tobytes() #print 'type4 size',len(whole_data) return whole_data
def type4(font): old_12_method = change_method(_c_m_a_p.cmap_format_12_or_13, _decompile_in_cmap_format_12_13, 'decompile') old_4_method = change_method(_c_m_a_p.cmap_format_4, _decompile_in_cmap_format_4, 'decompile') cmapTable = font['cmap'] cmap12 = cmapTable.getcmap(3, 10).cmap #format 12 cmap4 = cmapTable.getcmap(3, 1).cmap #format 4 assert cmap12 and cmap4, 'Both cmap format 12 and 4 tables are needed' cmap4_endCodes = cmap4['endCode'] cmap4_startCodes = cmap4['startCode'] cmap12_startCodes = cmap12['startCodes'] cmap12_lengths = cmap12['lengths'] fmt12SegCount = len(cmap12_startCodes) fmt4SegCount = len(cmap4_startCodes) # TODO(bstell): the code in this section seems to only work if there number # of fmt4 segments is smaller than the number of fmt12 segments. assert fmt12SegCount >= (fmt4SegCount - 1), '' #finds segment mappings fmt4Seg = 0 fmt12Seg = 0 mapping = defaultdict(list) while fmt12Seg < fmt12SegCount and fmt4Seg < fmt4SegCount: cmap12SegStart = cmap12_startCodes[fmt12Seg] cmap12SegEnd = cmap12_startCodes[fmt12Seg] + cmap12_lengths[ fmt12Seg] - 1 cmap4SegStart = cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] if cmap12SegStart >= cmap4SegStart and cmap12SegEnd <= cmap4SegEnd: mapping[fmt4Seg].append(fmt12Seg) fmt12Seg += 1 elif cmap12SegStart > cmap4_endCodes[fmt4Seg]: fmt4Seg += 1 else: #case of where format12 segment overlap end of format4 segment print cmap12SegStart, cmap12SegEnd, cmap4_startCodes[ fmt4Seg], cmap4_endCodes[fmt4Seg] raise ('unexpected tables') # Handle format 4's special 0xFFFF segment #assert fmt4Seg == fmt4SegCount, 'only the 0xFFFF segment left' mapping[fmt4Seg] # Make an empty segment gos_data = Bits() escaped_data = Bits() gos_data.frombytes(struct.pack('>B', 4)) #GOS type gos_data.frombytes(struct.pack('>H', fmt4SegCount)) #now checks if segments in good condition segLens = [] idRangeOffsets = cmap4['idRangeOffset'] idDelta = cmap4['idDelta'] for fmt4Seg, fmt12SegList in mapping.iteritems(): lenFmt12Segs = len(fmt12SegList) segLens.append(lenFmt12Segs) if lenFmt12Segs == 0: continue # check the segments cmap12SegStart = cmap12_startCodes[fmt12SegList[0]] cmap12SegEnd = cmap12_startCodes[ fmt12SegList[-1]] + cmap12_lengths[fmt12SegList[-1]] - 1 cmap4SegStart = cmap4_startCodes[fmt4Seg] cmap4SegEnd = cmap4_endCodes[fmt4Seg] assert cmap12SegStart == cmap4SegStart and cmap12SegEnd == cmap4SegEnd if lenFmt12Segs == 1: assert idRangeOffsets[fmt4Seg] == 0 else: assert idRangeOffsets[fmt4Seg] != 0 and idDelta[fmt4Seg] == 0 for segLen in segLens: encoded_value = NumberEncoders.BitEncodeAllOnesEscape(segLen, 2) extend_bits_or_escape(gos_data, escaped_data, encoded_value) change_method(_c_m_a_p.cmap_format_12_or_13, old_12_method, 'decompile') change_method(_c_m_a_p.cmap_format_4, old_4_method, 'decompile') whole_data = gos_data.tobytes() + escaped_data.tobytes() #print 'type4 size',len(whole_data) return whole_data