Пример #1
0
    def parse_fonts(content):
        """
        :param filepath: 请求ttf地址的响应
        :return: 字体字典
        """
        font = TTFont(BytesIO(content))
        glyphnames = font.getGlyphNames()
        unknown_list, fonts = [], {}
        for glyphname in glyphnames[1:]:
            item = {}
            glyph = font['glyf'][glyphname]
            item["cp"] = glyph.endPtsOfContours
            item["glyphname"] = glyphname
            if item['cp'] == [11]:
                item['xy'] = glyph.coordinates[0]
            unknown_list.append(item)
        for font in fonts_list:
            for dom in unknown_list:
                if dom.get("cp") == font.get("cp") and dom.get("cp") != [12]:
                    fonts[dom['glyphname'][3:]] = font.get("value")
                else:
                    if dom.get("cp") == [12]:

                        if int(dom.get("xy")[0][1]) > 200:
                            fonts[dom['glyphname'][3:]] = "十"
                        else:
                            fonts[dom['glyphname'][3:]] = "上"
        return fonts
Пример #2
0
def main():
    font = TTFont('0805.woff')
    glyf = font.get('glyf')
    result = font['cmap']
    cmap_dict = result.getBestCmap()
    for key, value in cmap_dict.items():
        k_tmp = str(hex(eval(str(key))))
        b = k_tmp.replace("0x", '')
        glyf = font.get('glyf')
        c = glyf[value]
        sql = "insert into woff20190806(name,ten_key,sixteen_key,position) values (\'%s\',%s,\'%s\',\'%s\')" % (
            value, key, b, c.coordinates)
        print(sql)
Пример #3
0
def save_word(filename):
    tablename = filename.replace('.woff', '') + "_dic_tmp"
    font = TTFont(filename)
    glyf = font.get('glyf')
    result = font['cmap']
    sql_delete = "truncate table %s" % (tablename)
    db.inset_data(sql_delete)
    cmap_dict = result.getBestCmap()
    for key, value in cmap_dict.items():
        k_tmp = str(hex(eval(str(key))))
        b = k_tmp.replace("0x", '')
        glyf = font.get('glyf')
        c = glyf[value]
        sql_insert = "insert into %s (name,ten_key,sixteen_key,position) values (\'%s\',%s,\'%s\',\'%s\')" % (
            tablename, value, key, b, c.coordinates)
        db.inset_data(sql_insert)
Пример #4
0
def getAddrMapping(url):
    res = {}
    json_data = getDict()
    woff = getAddrWoff(url)
    rs = requests.get(woff)
    with open('../dzdp_woff/addrTest.woff', "wb") as f:
        f.write(rs.content)
    f.close()
    font = TTFont('addrTest.woff')  # 读取woff文件
    font.saveXML('addrTest.xml')  # 转成xml
    result = font['cmap']
    cmap_dict = result.getBestCmap()
    for key, value in cmap_dict.items():
        k_tmp = str(hex(eval(str(key))))
        b = k_tmp.replace("0x", '')
        glyf = font.get('glyf')
        c = glyf[value]
        coordinates = str(c.coordinates)
        for data in json_data:
            position = data["position"]
            if position == coordinates and data["word"] not in [
                    '', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
            ]:
                res[value.replace("uni", "&#x")] = data["word"]
    print("getAddrMapping", res)
    return res
Пример #5
0
def save_word(filename):
    tablename = filename.replace('.woff', '') + "_dic"
    font = TTFont(filename)
    glyf = font.get('glyf')
    result = font['cmap']
    sql_delete = "truncate table %s" % (tablename)
    db.execute(sql_delete)
    cmap_dict = result.getBestCmap()
    insert_data = []
    for key, value in cmap_dict.items():
        k_tmp = str(hex(eval(str(key))))
        b = k_tmp.replace("0x", '')
        glyf = font.get('glyf')
        c = glyf[value]
        temp = (str(value), str(key), str(b), str(c.coordinates))
        insert_data.append(temp)

    #print(insert_data)
    sql_insert = "insert into {0} (name, ten_key, sixteen_key, position) values (%s, %s, %s, %s)".format(
        tablename)
    db.insertmany(sql_insert, insert_data)
Пример #6
0
def getSortInfoOTF(fontPath: PathLike, fontNum: int):
    from fontTools.ttLib import TTFont
    suffix = fontPath.suffix.lower().lstrip(".")
    ttf = TTFont(fontPath, fontNumber=fontNum, lazy=True)
    sortInfo = dict(suffix=suffix)
    name = ttf.get("name")
    os2 = ttf.get("OS/2")
    post = ttf.get("post")
    if name is not None:
        for key, nameIDs in [("familyName", [16, 1]), ("styleName", [17, 2])]:
            for nameID in nameIDs:
                nameRec = name.getName(nameID, 3, 1)
                if nameRec is not None:
                    sortInfo[key] = str(nameRec)
                    break
    if os2 is not None:
        sortInfo["weight"] = os2.usWeightClass
        sortInfo["width"] = os2.usWidthClass
    if post is not None:
        sortInfo[
            "italicAngle"] = -post.italicAngle  # negative for intuitive sort order
    return sortInfo
Пример #7
0
def get_real_word(fake_word, html):
    font_ttf = re.findall("charset=utf-8;base64,(.*?)'\)", html)[0]
    #print(font_ttf)
    font = TTFont(BytesIO(base64.decodebytes(font_ttf.encode())))
    numbering = font.get('cmap').tables[0].ttFont.get('cmap').tables[0].cmap
    word_list = []
    for char in fake_word:
        decode_num = ord(char)
        if decode_num in numbering:
            num = numbering[decode_num]
            num = int(num[-2:]) - 1
            word_list.append(num)
        else:
            word_list.append(char)
    real_word = ''
    for num in word_list:
        real_word += str(num)
    return real_word
Пример #8
0
def create_mapping(font_file):
    """ 打开字体文件并创建字符和数字之间的映射. """
    # 打开字体文件,加载glyf
    font = TTFont(font_file)
    glyf = font.get('glyf')
    current_map = {}
    # 创建当前字体文件的数字映射
    for i in glyf.keys():
        # 忽略不是uni开头的字符
        if not i.startswith('uni'):
            continue
        c = glyf[i]
        number = get_number_offset(c)
        # 发现有字符不在已有的集合中, 抛出异常.
        if number is None:
            print((c.yMax, c.xMax, c.yMin, c.xMin))
            raise Exception
        current_map[i.strip('uni')] = number
    # print(json.dumps(current_map, indent=4))
    return current_map
Пример #9
0
def double_encode_uc(input_path, output_dir, subfolder):
    t = time.time()
    print("AllCapist")
    font_count = 0

    # walk the i,put directory
    input_dir, font_path = walk_input_path(input_path,
                                           target_extentions=TARGETS,
                                           recursive=subfolder)

    for p in font_path:

        if output_dir:
            dir_, font_file = os.path.split(p)
            out_path = os.path.join(output_dir, font_file)
        else:
            out_path = p

        f = TTFont(p)
        f_cmap = f.get("cmap")

        for table in f_cmap.tables:
            # if table.format in [4, 12, 13, 14]:
            cmap = {}
            for u, n in list(table.cmap.items()):
                cmap[u] = n
                if u not in IGNORE_UNICODES:
                    lc = get_lowercase_unicode(u)
                    if lc and lc != u and lc not in list(table.cmap.keys()):
                        cmap[lc] = n
            table.cmap = cmap

        f.save(out_path)
        f.close()
        print(f"{p} -> done")
        font_count += 1

    print("")
    print(f"All done: {font_count} font processed in {time.time() - t} secs")
Пример #10
0
class TTVarCFont:
    def __init__(self, path, ttFont=None, hbFont=None):
        if ttFont is not None:
            assert hbFont is not None
            assert path is None
            self.ttFont = ttFont
        else:
            assert hbFont is None
            self.ttFont = TTFont(path, lazy=True)
        self.axes = {
            axis.axisTag: (axis.minValue, axis.defaultValue, axis.maxValue)
            for axis in self.ttFont["fvar"].axes
        }
        if hbFont is not None:
            self.hbFont = hbFont
        else:
            with open(path, "rb") as f:
                face = hb.Face(f.read())
            self.hbFont = hb.Font(face)

    def keys(self):
        return self.ttFont.getGlyphNames()

    def __contains__(self, glyphName):
        return glyphName in self.ttFont.getReverseGlyphMap()

    def drawGlyph(self, pen, glyphName, location):
        normLocation = normalizeLocation(location, self.axes)
        fvarTable = self.ttFont["fvar"]
        glyfTable = self.ttFont["glyf"]
        varcTable = self.ttFont.get("VarC")
        if varcTable is not None:
            glyphData = varcTable.GlyphData
        else:
            glyphData = {}

        g = glyfTable[glyphName]
        varComponents = glyphData.get(glyphName)
        if g.isComposite():
            componentOffsets = instantiateComponentOffsets(
                self.ttFont, glyphName, normLocation
            )
            if varComponents is not None:
                assert len(g.components) == len(varComponents)
                varcInstancer = VarStoreInstancer(
                    varcTable.VarStore, fvarTable.axes, normLocation
                )
                for (x, y), gc, vc in zip(
                    componentOffsets, g.components, varComponents
                ):
                    componentLocation = unpackComponentLocation(vc.coord, varcInstancer)
                    transform = unpackComponentTransform(
                        vc.transform, varcInstancer, vc.numIntBitsForScale
                    )
                    tPen = TransformPen(pen, _makeTransform(x, y, transform))
                    self.drawGlyph(tPen, gc.glyphName, componentLocation)
            else:
                for (x, y), gc in zip(componentOffsets, g.components):
                    tPen = TransformPen(pen, (1, 0, 0, 1, x, y))
                    self.drawGlyph(tPen, gc.glyphName, {})
        else:
            glyphID = self.ttFont.getGlyphID(glyphName)
            self.hbFont.set_variations(location)
            self.hbFont.draw_glyph_with_pen(glyphID, pen)
Пример #11
0
def instantiateVariableFont(varfont, location, inplace=False, overlap=True):
    """ Generate a static instance from a variable TTFont and a dictionary
	defining the desired location along the variable font's axes.
	The location values must be specified as user-space coordinates, e.g.:

		{'wght': 400, 'wdth': 100}

	By default, a new TTFont object is returned. If ``inplace`` is True, the
	input varfont is modified and reduced to a static font.

	When the overlap parameter is defined as True,
	OVERLAP_SIMPLE and OVERLAP_COMPOUND bits are set to 1.  See
	https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
	"""
    if not inplace:
        # make a copy to leave input varfont unmodified
        stream = BytesIO()
        varfont.save(stream)
        stream.seek(0)
        varfont = TTFont(stream)

    fvar = varfont['fvar']
    axes = {
        a.axisTag: (a.minValue, a.defaultValue, a.maxValue)
        for a in fvar.axes
    }
    loc = normalizeLocation(location, axes)
    if 'avar' in varfont:
        maps = varfont['avar'].segments
        loc = {k: piecewiseLinearMap(v, maps[k]) for k, v in loc.items()}
    # Quantize to F2Dot14, to avoid surprise interpolations.
    loc = {k: floatToFixedToFloat(v, 14) for k, v in loc.items()}
    # Location is normalized now
    log.info("Normalized location: %s", loc)

    if 'gvar' in varfont:
        log.info("Mutating glyf/gvar tables")
        gvar = varfont['gvar']
        glyf = varfont['glyf']
        hMetrics = varfont['hmtx'].metrics
        vMetrics = getattr(varfont.get('vmtx'), 'metrics', None)
        # get list of glyph names in gvar sorted by component depth
        glyphnames = sorted(
            gvar.variations.keys(),
            key=lambda name:
            (glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth
             if glyf[name].isComposite() else 0, name))
        for glyphname in glyphnames:
            variations = gvar.variations[glyphname]
            coordinates, _ = glyf._getCoordinatesAndControls(
                glyphname, hMetrics, vMetrics)
            origCoords, endPts = None, None
            for var in variations:
                scalar = supportScalar(loc, var.axes)
                if not scalar: continue
                delta = var.coordinates
                if None in delta:
                    if origCoords is None:
                        origCoords, g = glyf._getCoordinatesAndControls(
                            glyphname, hMetrics, vMetrics)
                    delta = iup_delta(delta, origCoords, g.endPts)
                coordinates += GlyphCoordinates(delta) * scalar
            glyf._setCoordinates(glyphname, coordinates, hMetrics, vMetrics)
    else:
        glyf = None

    if 'cvar' in varfont:
        log.info("Mutating cvt/cvar tables")
        cvar = varfont['cvar']
        cvt = varfont['cvt ']
        deltas = {}
        for var in cvar.variations:
            scalar = supportScalar(loc, var.axes)
            if not scalar: continue
            for i, c in enumerate(var.coordinates):
                if c is not None:
                    deltas[i] = deltas.get(i, 0) + scalar * c
        for i, delta in deltas.items():
            cvt[i] += otRound(delta)

    if 'CFF2' in varfont:
        log.info("Mutating CFF2 table")
        glyphOrder = varfont.getGlyphOrder()
        CFF2 = varfont['CFF2']
        topDict = CFF2.cff.topDictIndex[0]
        vsInstancer = VarStoreInstancer(topDict.VarStore.otVarStore, fvar.axes,
                                        loc)
        interpolateFromDeltas = vsInstancer.interpolateFromDeltas
        interpolate_cff2_PrivateDict(topDict, interpolateFromDeltas)
        CFF2.desubroutinize()
        interpolate_cff2_charstrings(topDict, interpolateFromDeltas,
                                     glyphOrder)
        interpolate_cff2_metrics(varfont, topDict, glyphOrder, loc)
        del topDict.rawDict['VarStore']
        del topDict.VarStore

    if 'MVAR' in varfont:
        log.info("Mutating MVAR table")
        mvar = varfont['MVAR'].table
        varStoreInstancer = VarStoreInstancer(mvar.VarStore, fvar.axes, loc)
        records = mvar.ValueRecord
        for rec in records:
            mvarTag = rec.ValueTag
            if mvarTag not in MVAR_ENTRIES:
                continue
            tableTag, itemName = MVAR_ENTRIES[mvarTag]
            delta = otRound(varStoreInstancer[rec.VarIdx])
            if not delta:
                continue
            setattr(varfont[tableTag], itemName,
                    getattr(varfont[tableTag], itemName) + delta)

    log.info("Mutating FeatureVariations")
    for tableTag in 'GSUB', 'GPOS':
        if not tableTag in varfont:
            continue
        table = varfont[tableTag].table
        if not getattr(table, 'FeatureVariations', None):
            continue
        variations = table.FeatureVariations
        for record in variations.FeatureVariationRecord:
            applies = True
            for condition in record.ConditionSet.ConditionTable:
                if condition.Format == 1:
                    axisIdx = condition.AxisIndex
                    axisTag = fvar.axes[axisIdx].axisTag
                    Min = condition.FilterRangeMinValue
                    Max = condition.FilterRangeMaxValue
                    v = loc[axisTag]
                    if not (Min <= v <= Max):
                        applies = False
                else:
                    applies = False
                if not applies:
                    break

            if applies:
                assert record.FeatureTableSubstitution.Version == 0x00010000
                for rec in record.FeatureTableSubstitution.SubstitutionRecord:
                    table.FeatureList.FeatureRecord[
                        rec.FeatureIndex].Feature = rec.Feature
                break
        del table.FeatureVariations

    if 'GDEF' in varfont and varfont['GDEF'].table.Version >= 0x00010003:
        log.info("Mutating GDEF/GPOS/GSUB tables")
        gdef = varfont['GDEF'].table
        instancer = VarStoreInstancer(gdef.VarStore, fvar.axes, loc)

        merger = MutatorMerger(varfont, instancer)
        merger.mergeTables(varfont, [varfont], ['GDEF', 'GPOS'])

        # Downgrade GDEF.
        del gdef.VarStore
        gdef.Version = 0x00010002
        if gdef.MarkGlyphSetsDef is None:
            del gdef.MarkGlyphSetsDef
            gdef.Version = 0x00010000

        if not (gdef.LigCaretList or gdef.MarkAttachClassDef
                or gdef.GlyphClassDef or gdef.AttachList or
                (gdef.Version >= 0x00010002 and gdef.MarkGlyphSetsDef)):
            del varfont['GDEF']

    addidef = False
    if glyf:
        for glyph in glyf.glyphs.values():
            if hasattr(glyph, "program"):
                instructions = glyph.program.getAssembly()
                # If GETVARIATION opcode is used in bytecode of any glyph add IDEF
                addidef = any(
                    op.startswith("GETVARIATION") for op in instructions)
                if addidef:
                    break
        if overlap:
            for glyph_name in glyf.keys():
                glyph = glyf[glyph_name]
                # Set OVERLAP_COMPOUND bit for compound glyphs
                if glyph.isComposite():
                    glyph.components[0].flags |= OVERLAP_COMPOUND
                # Set OVERLAP_SIMPLE bit for simple glyphs
                elif glyph.numberOfContours > 0:
                    glyph.flags[0] |= flagOverlapSimple
    if addidef:
        log.info("Adding IDEF to fpgm table for GETVARIATION opcode")
        asm = []
        if 'fpgm' in varfont:
            fpgm = varfont['fpgm']
            asm = fpgm.program.getAssembly()
        else:
            fpgm = newTable('fpgm')
            fpgm.program = ttProgram.Program()
            varfont['fpgm'] = fpgm
        asm.append("PUSHB[000] 145")
        asm.append("IDEF[ ]")
        args = [str(len(loc))]
        for a in fvar.axes:
            args.append(str(floatToFixed(loc[a.axisTag], 14)))
        asm.append("NPUSHW[ ] " + ' '.join(args))
        asm.append("ENDF[ ]")
        fpgm.program.fromAssembly(asm)

        # Change maxp attributes as IDEF is added
        if 'maxp' in varfont:
            maxp = varfont['maxp']
            setattr(maxp, "maxInstructionDefs",
                    1 + getattr(maxp, "maxInstructionDefs", 0))
            setattr(maxp, "maxStackElements",
                    max(len(loc), getattr(maxp, "maxStackElements", 0)))

    if 'name' in varfont:
        log.info("Pruning name table")
        exclude = {a.axisNameID for a in fvar.axes}
        for i in fvar.instances:
            exclude.add(i.subfamilyNameID)
            exclude.add(i.postscriptNameID)
        if 'ltag' in varfont:
            # Drop the whole 'ltag' table if all its language tags are referenced by
            # name records to be pruned.
            # TODO: prune unused ltag tags and re-enumerate langIDs accordingly
            excludedUnicodeLangIDs = [
                n.langID for n in varfont['name'].names if n.nameID in exclude
                and n.platformID == 0 and n.langID != 0xFFFF
            ]
            if set(excludedUnicodeLangIDs) == set(
                    range(len((varfont['ltag'].tags)))):
                del varfont['ltag']
        varfont['name'].names[:] = [
            n for n in varfont['name'].names if n.nameID not in exclude
        ]

    if "wght" in location and "OS/2" in varfont:
        varfont["OS/2"].usWeightClass = otRound(
            max(1, min(location["wght"], 1000)))
    if "wdth" in location:
        wdth = location["wdth"]
        for percent, widthClass in sorted(OS2_WIDTH_CLASS_VALUES.items()):
            if wdth < percent:
                varfont["OS/2"].usWidthClass = widthClass
                break
        else:
            varfont["OS/2"].usWidthClass = 9
    if "slnt" in location and "post" in varfont:
        varfont["post"].italicAngle = max(-90, min(location["slnt"], 90))

    log.info("Removing variable tables")
    for tag in ('avar', 'cvar', 'fvar', 'gvar', 'HVAR', 'MVAR', 'VVAR',
                'STAT'):
        if tag in varfont:
            del varfont[tag]

    return varfont
Пример #12
0
    def parse(self, response, **kwargs):
        # 58.com uses custom fonts to hide price and room count
        # To extract these data, we need to load the embedded font from the source code first
        font_ttf = re.findall("charset=utf-8;base64,(.*?)'\)",
                              response.text)[0]
        font = TTFont(BytesIO(base64.decodebytes(font_ttf.encode())))
        numbering = font.get('cmap').tables[0].ttFont.get(
            'cmap').tables[0].cmap

        lis = response.xpath(
            '//ul[@class="house-list"]/li[@class="house-cell"]')
        for li in lis:
            infor = li.xpath(
                'div[@class="des"]/p[@class="infor"]//text()').extract()
            infor = [x.strip() for x in infor if x.strip()]
            if len(infor) < 2:
                print(infor)
                continue

            item = A58SpiderItem()
            item['url'] = li.xpath('div[@class="des"]/h2/a/@href').extract()[0]
            item['area'] = infor[0]
            item['community'] = infor[1]

            sent_time = li.xpath(
                'div[@class="list-li-right"]/div[@class="send-time"]/text()'
            ).extract()
            sent_time = [x.strip() for x in sent_time if x.strip()]
            item['date'] = self.convert_time(
                sent_time[0].strip()) if sent_time else 'Unknown'

            if len(infor) >= 3:
                metro_data = re.match(r'距(.*)号线(.*?)地铁站步行(.*?)m', infor[2])
                if metro_data:
                    item['metro'] = metro_data.group(1)
                    item['subway_station'] = metro_data.group(2)
                    item['distance'] = int(metro_data.group(3))
                else:
                    print(infor[2])
                    continue
            else:
                # item['metro'] = 'Unknown'
                # item['subway_station'] = 'Unknown'
                # item['distance'] = 'Unknown'
                print('No subway info, drop', item['community'])
                continue

            price = li.xpath(
                'div[@class="list-li-right"]/div[@class="money"]/b/text()'
            ).extract()[0]
            item['price'] = self.convert_real_word(numbering, price)

            rooms = li.xpath('div[@class="des"]/h2'
                             '/a/text()').extract()[0].replace(
                                 item['community'], '').strip()
            item['rooms'] = self.convert_real_word(numbering, rooms)

            yield item

        next_page = response.xpath(
            '//div[@class="pager"]/a[@class="next"]/@href').extract()
        if next_page:
            yield scrapy.Request(next_page[0])
Пример #13
0
class BMFontTTF:
    def __init__(self,
                 ttf,
                 chars="",
                 size=32,
                 stroke_color=None,
                 stroke_width=0):
        self.size = size
        self.chars = None
        self.stroke_color = stroke_color
        self.stroke_width = stroke_width
        self.ttf = None
        self.glyf = None
        self.font = None
        if self.__check_ttf(ttf):
            self.__check_chars(chars)

    def __check_ttf(self, ttf):
        if os.path.isfile(ttf) and (
                os.path.splitext(ttf)[-1]).lower() == ".ttf":
            self.ttf = ttf
            self.glyf = TTFont(ttf).getBestCmap()
            self.font = ImageFont.truetype(ttf, self.size)
        else:
            print("找不到字体: %s" % ttf)
            return False
        if not self.glyf or not self.font:
            print("无效的字体: %s" % ttf)
            return False
        return True

    def __check_chars(self, text):
        chars = []
        arr = list(set(list(text)))
        for char in arr:
            if self.has_char(char):
                chars.append(char)
        if len(chars) == 0:
            print("找不到有效的输入字符")
            return False
        self.chars = sorted(chars)
        self.chars.append(u"\u0020")
        return True

    def has_char(self, char):
        try:
            return self.glyf.get(ord(char)) is not None
        except Exception:
            print("无效的字符: %s" % char)
            return False

    def save(self, path, save_file):
        if path is None:
            print("无效的保存位置: %s" % str(path))
            return
        os.makedirs(path, exist_ok=True)
        if not os.path.isdir(path):
            print("无效的保存位置: %s" % str(path))
            return
        else:
            # rmtree(path, ignore_errors=True)
            os.makedirs(path, exist_ok=True)

        if not self.chars or len(self.chars) == 0:
            return

        channel = (0, 0, 0, 0)
        files = []
        from_path = os.path.join(get_app_cache_dir(),
                                 datetime.now().strftime("%Y%m%d%H%M%S"))
        os.makedirs(from_path, exist_ok=True)
        for char in self.chars:
            size = self.font.getsize(char, stroke_width=self.stroke_width)
            size2 = self.font.getsize(char)
            offset = ((size[0] - size2[0]), (size[1] - size2[1]))
            # size = (size[0] + offset[0], size[1] + offset[1])
            image = Image.new("RGBA", size, channel)
            draw = ImageDraw.Draw(image)
            draw.text(offset,
                      char,
                      font=self.font,
                      spacing=0,
                      stroke_fill=self.stroke_color,
                      stroke_width=self.stroke_width)
            repl = ESCAPE_SWAP_CHARS.get(char)
            repl = repl or char
            print("TTF正在添加字符: %s => %s" % (char, repl))
            filename = os.path.join(from_path, "%s.png" % repl)
            image.save(filename)
            files.append(filename)

        Atlas({
            "image": from_path,
            "output": path,
            "atlas": files,
            "max_width": Globals.get_max_width(),
            "save_file": save_file
        }).generate()
Пример #14
0
    ]):
    2,
    str([1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1]):
    7,
}
# decrypt = decrypt_collection.find_one({"_id": 1})["match"]

file_name = ttfUrl.split("/")[-1]
match = {}

# 获取ttf 文件
res = requests.get(ttfUrl)
with open(file_name, "wb") as file:
    file.write(res.content)

# ttf 文件解析
font = TTFont(file_name)
font.get("glyf")
font.getTableData("glyf")

for key in font["glyf"].glyphs:
    f = font["glyf"].glyphs[key]
    if not hasattr(f, "flags"):
        continue
    if str(f.flags.tolist()) in ttfMatch:
        match[key.lower().replace("uni", "&#x") + ";"] = str(ttfMatch[str(
            f.flags.tolist())])

# 粘贴到system_config 表
print("'{}': {}".format(file_name.split(".")[0], match))
Пример #15
0
class ChangeFontColor:
    """
    Tool that changes color in SVG/COLR font. 
    It tries to simplify the process a bit.
    """
    def __init__(self, path: Path, colors, inputType: str) -> None:
        self.font = TTFont(path)
        self.hexColors = (colors if inputType == "hex" else list(
            map(self.rgbToHex, colors)))
        self.rgbColors = (colors if inputType == "rgb" else list(
            map(self.hexToRgb, colors)))
        svg = self.font.get("SVG ")
        cpal = self.font.get("CPAL")
        if svg:
            self.changeSVGColor(svg)
        if cpal:
            self.changeCPALColor(cpal)
        self.font.save(path.absolute().with_name(f"colored_{path.name}"))

    def changeSVGColor(self, table: S_V_G_) -> None:
        """
        Regexes colors in svg data in given font and changes their color.
        """
        colors = self.hexColors[::-1]
        for i, entry in enumerate(table.docList):
            matches = re.finditer('fill="#([0-9]*)"', entry[0])
            spans = [match.span(1) for match in matches][::-1]
            if i == 0:
                assert len(spans) == len(
                    colors
                ), "have same number of new colors as in your input file"
            for color, (start, end) in zip(colors, spans):
                entry[0] = f"{entry[0][:start]}{color}{entry[0][end:]}"

    def changeCPALColor(self, table: C_P_A_L_) -> None:
        """
        Changes CPAL table in given font, this table contains palettes of colors.
        Currently, it works only with fonts that have only one color in their palette. 
        """
        colors = self.rgbColors

        for i, color in enumerate(colors):
            if len(color) == 3:
                colors[i] += (255, )

        table.palettes = [
            list(map(lambda x: Color(*x[:3][::-1], x[3]), colors))
        ]

    def hexToRgb(self, val: str) -> Tuple[int, ...]:
        """
        Converts hex value to rgb
        """
        splits = tuple(val[i:i + 2] for i in range(0, len(val), 2))
        rgbSpace = tuple(map(lambda x: int(x, 16), splits))
        return rgbSpace

    def rgbToHex(self, val: Tuple[int, ...]) -> str:
        """
        Converts rgb value to hex
        """
        return "".join(tuple(format(i, "x").zfill(2) for i in val))