Python fontTools.ttLib.TTFont() Examples

The following are 30 code examples of fontTools.ttLib.TTFont(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module fontTools.ttLib , or try the search function .
Example #1
Source File: gftools-list-weightclass.py    From gftools with Apache License 2.0 8 votes vote down vote up
def main():
  args = parser.parse_args()
  headers = ['filename', 'usWeightClass']
  rows = []
  for font in args.font:
    ttfont = ttLib.TTFont(font)
    rows.append([os.path.basename(font), ttfont['OS/2'].usWeightClass])

  def as_csv(rows):
    import csv
    import sys
    writer = csv.writer(sys.stdout)
    writer.writerows([headers])
    writer.writerows(rows)
    sys.exit(0)

  if args.csv:
    as_csv(rows)

  print(tabulate.tabulate(rows, headers, tablefmt="pipe")) 
Example #2
Source File: gftools-fix-fsselection.py    From gftools with Apache License 2.0 7 votes vote down vote up
def printInfo(fonts, print_csv=False):
  rows = []
  headers = ['filename', 'fsSelection']
  for font in fonts:
    ttfont = ttLib.TTFont(font)
    row = [os.path.basename(font)]
    row.append(('{:#010b} '
                '{:#010b}'
                '').format(getByte2(ttfont),
                           getByte1(ttfont)).replace('0b', ''))
    rows.append(row)

  def as_csv(rows):
    writer = csv.writer(sys.stdout)
    writer.writerows([headers])
    writer.writerows(rows)
    sys.exit(0)

  if print_csv:
    as_csv(rows)
  else:
    print(tabulate.tabulate(rows, headers, tablefmt="pipe")) 
Example #3
Source File: ufoFont.py    From fontgoggles with Apache License 2.0 6 votes vote down vote up
def load(self, outputWriter):
        if hasattr(self, "reader"):
            self._cachedGlyphs = {}
            return
        self._setupReaderAndGlyphSet()
        self.info = SimpleNamespace()
        self.reader.readInfo(self.info)
        self.lib = self.reader.readLib()
        self._cachedGlyphs = {}
        if self.ufoState is None:
            includedFeatureFiles = extractIncludedFeatureFiles(self.fontPath, self.reader)
            self.ufoState = UFOState(self.reader, self.glyphSet,
                                     getUnicodesAndAnchors=self._getUnicodesAndAnchors,
                                     includedFeatureFiles=includedFeatureFiles)

        fontData = await compileUFOToBytes(self.fontPath, outputWriter)

        f = io.BytesIO(fontData)
        self.ttFont = TTFont(f, lazy=True)
        self.shaper = self._getShaper(fontData) 
Example #4
Source File: gftools-check-name.py    From gftools with Apache License 2.0 6 votes vote down vote up
def main():
  args = parser.parse_args()

  rows = []
  for font_filename in args.fonts:
    font = TTFont(font_filename)
    for field in font['name'].names:
      enc = field.getEncoding()
      rows.append([
        ('Font', ntpath.basename(font_filename)),
        ('platformID', field.platformID),
        ('encodingID', field.platEncID),
        ('languageID', field.langID),
        ('nameID', field.nameID),
        ('nameString', field.toUnicode()),
      ])

  if args.csv:
    printInfo(rows, save=True)
  else:
    printInfo(rows) 
Example #5
Source File: gftools-nametable-from-filename.py    From gftools with Apache License 2.0 6 votes vote down vote up
def main():
  args = parser.parse_args()

  for font_path in args.fonts:
    nametable = nametable_from_filename(font_path)
    font = TTFont(font_path)
    font_filename = ntpath.basename(font_path)

    font['name'] = nametable
    style = font_filename[:-4].split('-')[-1]
    font['OS/2'].usWeightClass = set_usWeightClass(style)
    font['OS/2'].fsSelection = set_fsSelection(font['OS/2'].fsSelection, style)
    win_style = font['name'].getName(2, 3, 1, 1033).string.decode('utf_16_be')
    font['head'].macStyle = set_macStyle(win_style)

    font.save(font_path + '.fix')
    print('font saved %s.fix' % font_path) 
Example #6
Source File: gftools-sanity-check.py    From gftools with Apache License 2.0 6 votes vote down vote up
def _CheckLSB0ForEmptyGlyphs(path, font, ttf):
  """Checks if font has empty (loca[n] == loca[n+1]) glyphs that have non-0 lsb.

  There is no reason to set such lsb's.

  Args:
    path: Path to directory containing font.
    font: A font record from a METADATA.pb.
    ttf: A fontTools.ttLib.TTFont for the font.
  Returns:
    A list of ResultMessageTuple for tests performed.
  """
  results = []
  if 'loca' not in ttf:
    return results
  for glyph_index, glyph_name in enumerate(ttf.getGlyphOrder()):
    is_empty = ttf['loca'][glyph_index] == ttf['loca'][glyph_index + 1]
    lsb = ttf['hmtx'][glyph_name][1]
    if is_empty and lsb != 0:
      results.append(
          _SadResult(
              '%s %s/%d [\'hmtx\'][\'%s\'][1] (lsb) should be 0 but is %d' %
              (font.name, font.style, font.weight, glyph_name, lsb),
              os.path.join(path, font.filename), _FixEmptyGlyphLsb(glyph_name)))
  return results 
Example #7
Source File: google_fonts.py    From gftools with Apache License 2.0 6 votes vote down vote up
def VFFamilyStyleWeight(path):
  """Extract family, style and weight from a variable font's name table.

  Args:
      path: Font path, eg ./fonts/ofl/lobster/Lobster[wght].ttf.
  Returns:
    FileFamilyStyleWeightTuple for file.
  """
  with ttLib.TTFont(path) as font:
    typoFamilyName = font['name'].getName(16, 3, 1, 1033)
    familyName = font['name'].getName(1, 3, 1, 1033)
    family = typoFamilyName.toUnicode() if typoFamilyName else \
             familyName.toUnicode()

    typoStyleName = font['name'].getName(17, 3, 1, 1033)
    styleName = font['name'].getName(2, 3, 1, 1033)
    style = typoStyleName.toUnicode() if typoStyleName else \
            styleName.toUnicode()
    style = "italic" if "Italic" in style.replace(" ", "") else "normal"
    # For each font in a variable font family, we do not want to return
    # the style's weight. We want to return 400 if 400 is within the
    # the wght axis range. If it isn't, we want the value closest to 400.
    weight = VFWeight(font)
    return FileFamilyStyleWeightTuple(path, family, style, weight) 
Example #8
Source File: google_fonts.py    From gftools with Apache License 2.0 6 votes vote down vote up
def VFWeight(font):
  """Return a variable fonts weight. Return 400 if 400 is within the wght
  axis range else return the value closest to 400

  Args:
    font: TTFont
  Returns:
    weight: integer
  """
  wght_axis = None
  for axis in font['fvar'].axes:
    if axis.axisTag == "wght":
      wght_axis = axis
      break
  value = 400
  if wght_axis:
    if wght_axis.minValue >= 400:
      value = wght_axis.minValue
    if wght_axis.maxValue <= 400:
      value = wght_axis.maxValue
  # TODO (MF) check with GF Eng if we should just assume it's safe to return
  # 400 if a wght axis doesn't exist.
  return int(value) 
Example #9
Source File: gftools-find-features.py    From gftools with Apache License 2.0 6 votes vote down vote up
def ListFeatures(font):
  """List features for specified font. Table assumed structured like GPS/GSUB.

  Args:
    font: a TTFont.
  Returns:
    List of 3-tuples of ('GPOS', tag, name) of the features in the font.
  """
  results = []
  for tbl in ["GPOS", "GSUB"]:
    if tbl in font.keys():
      results += [
        (tbl,
         f.FeatureTag,
         "lookups: [{}]".format(", ".join(map(str, f.Feature.LookupListIndex)))
        ) for f in font[tbl].table.FeatureList.FeatureRecord
      ]
  return results 
Example #10
Source File: __init__.py    From fonttools-opentype-feature-freezer with Apache License 2.0 6 votes vote down vote up
def __init__(self, options: SimpleNamespace):
        self.inpath: os.PathLike = options.inpath
        self.outpath: os.PathLike = options.outpath
        if not self.outpath:
            self.outpath = os.fspath(self.inpath) + ".featfreeze.otf"
        self.FeatureIndex = None
        self.filterByFeatures = None
        self.filterByLangSys = None
        self.filterByScript = None
        self.LookupList = None
        self.names: List[str] = []
        self.options: SimpleNamespace = options
        self.reportFeature: List[str] = []
        self.reportLangSys: List[str] = []
        self.subs0: List[str] = []
        self.subs1: List[str] = []
        self.substitution_mapping: MutableMapping[str, str] = {}
        self.success: bool = True
        self.ttx: Optional[ttLib.TTFont] = None
        logger.info("[RemapByOTL] Running with options: %s", self.options) 
Example #11
Source File: gftools-space-check.py    From gftools with Apache License 2.0 6 votes vote down vote up
def _CheckFont(font):
  """Inspects a font for space/nbsp issues.

  Args:
    font: A TTFont.
  Returns:
    A set of strings describing problems found in the font. Empty set if none.
  """
  problems = set()

  (space_cmap, _) = _LoadGlyf(font, 0x0020, 'SPACE', problems)
  (nbsp_cmap, _) = _LoadGlyf(font, 0x00A0, 'NBSP', problems)

  if nbsp_cmap and _HasInk(font, nbsp_cmap):
    problems.add('NBSP_HAS_INK')

  if space_cmap and _HasInk(font, space_cmap):
    problems.add('SPACE_HAS_INK')

  if nbsp_cmap and space_cmap:
    if font['hmtx'][nbsp_cmap][0] != font['hmtx'][space_cmap][0]:
      problems.add('SPACE_NBSP_WIDTH_MISMATCH')

  return set(problems) 
Example #12
Source File: gftools-namelist.py    From gftools with Apache License 2.0 6 votes vote down vote up
def namelist_from_font(file_name, out=None):
    if out is None:
        out = sys.stdout
    excluded_chars = ["????", "SPACE", "NO-BREAK SPACE"]
    font = TTFont(file_name)
    charcodes = set()
    for cmap in font["cmap"].tables:
        if not cmap.isUnicode():
            continue
        charcodes.update(cp for cp,name in cmap.cmap.items())
    charcodes = sorted(charcodes)
    for charcode in charcodes:
        hexchar, char, item_description = _format_codepoint(charcode)
        if item_description not in excluded_chars:
            string = "{} {} {}".format(hexchar, char, item_description)
            print(string, file=out)
    return
    font.close() 
Example #13
Source File: gftools-fix-weightclass.py    From gftools with Apache License 2.0 6 votes vote down vote up
def main(font_path):
    filename = os.path.basename(font_path)
    font = TTFont(font_path)
    desired_style = style_parse(font)
    current_weight_class = font["OS/2"].usWeightClass
    updated = False
    if current_weight_class != desired_style.usWeightClass:
        print(f"{filename}: Updating weightClass to {desired_style.usWeightClass}")
        font['OS/2'].usWeightClass = desired_style.usWeightClass
        updated = True
    # If static otf, update Thin and ExtraLight
    # TODO (M Foley) fontbakery's style_parse should do this
    if "CFF " in font and 'fvar' not in font:
        if desired_style.usWeightClass == 100:
            print(f"{filename}: Updating weightClass to {250}")
            font['OS/2'].usWeightClass = 250
            updated = True
        elif desired_style.usWeightClass == 200:
            print(f"{filename}: Updating weightClass to {275}")
            font['OS/2'].usWeightClass = 275
            updated = True
    if updated:
        font.save(font.reader.file.name + ".fix")
    else:
        print("{}: Skipping. Current WeightClass is correct".format(filename)) 
Example #14
Source File: gftools-list-widthclass.py    From gftools with Apache License 2.0 6 votes vote down vote up
def fix(fonts, value=None):
    rows = []
    headers = ['filename', 'usWidthClass was', 'usWidthClass now']

    for font in fonts:
        row = [font]
        ttfont = ttLib.TTFont(font)
        if not value:
            usWidthClass = getFromFilename(font)
        else:
            usWidthClass = value
        row.append(ttfont['OS/2'].usWidthClass)
        ttfont['OS/2'].usWidthClass = usWidthClass
        row.append(ttfont['OS/2'].usWidthClass)
        ttfont.save(font + '.fix')
        rows.append(row)

    if rows:
        print(tabulate.tabulate(rows, headers, tablefmt="pipe")) 
Example #15
Source File: gftools-font-diff.py    From gftools with Apache License 2.0 6 votes vote down vote up
def main(argv):
  print(argv)
  if len(argv) != 3:
    raise ValueError('Specify two files to diff')

  with warnings.catch_warnings():
    warnings.simplefilter('ignore')
    with open(argv[1], 'rb') as f1, open(argv[2], 'rb') as f2:
      lhs = ttLib.TTFont(f1)
      rhs = ttLib.TTFont(f2)
      font_diff = _DiffFont(lhs, rhs)

  for tag, one_side, diff_tuples, error in font_diff:
    if error:
      print('%s %s' % (tag, error))
    elif one_side:
      print('Only %s has %s' % (one_side.upper(), str(tag)))
    elif not diff_tuples:
      print('%s identical' % tag)
    else:
      print('%s DIFF' % tag)

    for name, lhs, rhs in diff_tuples:
      print('  %s %s != %s' % (name, _ShortDisplay(lhs), _ShortDisplay(rhs))) 
Example #16
Source File: font.py    From scraper-fourone-jobs with GNU General Public License v2.0 6 votes vote down vote up
def read(cls, fonturl: str) -> WOFFContent:
        """
        取得 WOFF 格式的 Font 檔案資訊
        Args:
            fonturl (str): 字型來源網址
        Returns:
            WOFFContent: 解析讀取後的內容
        """
        resp: Response = requests.get(fonturl)
        font = TTFont(io.BytesIO(resp.content))
        xmlname = cls.named_xml(fonturl)
        font.saveXML(xmlname)
        # 把 List 轉換成字典形式
        orders: List[str] = font.getGlyphOrder()
        glyphs: Dict[str, str] = {
            str(idx).zfill(2): orders[idx]
            for idx in range(len(orders))
        }
        charmap = font.getBestCmap()
        woff = WOFFContent(glyphs, charmap)
        return woff 
Example #17
Source File: gftools-add-font.py    From gftools with Apache License 2.0 6 votes vote down vote up
def _AxisInfo(fontfile):
  """Gets variable axes info.

  Args:
    fontfile: Font file to look at for variation info

  Returns:
    Variable axes info
  """
  with contextlib.closing(ttLib.TTFont(fontfile)) as font:
    if 'fvar' not in font:
      return frozenset()
    else:
      fvar = font['fvar']
      axis_info = [
          (a.axisTag, a.minValue, a.maxValue) for a in fvar.axes
      ]
      return tuple(sorted(axis_info)) 
Example #18
Source File: fontutils.py    From crnn.pytorch with Apache License 2.0 6 votes vote down vote up
def get_font_chars(font_path):
    font = TTFont(font_path, fontNumber=0)
    glyph_names = font.getGlyphNames()
    char_list = []
    for idx, glyph in enumerate(glyph_names):
        if glyph[0] == '.':  # 跳过'.notdef', '.null'
            continue
        if glyph == 'union':
            continue
        if glyph[:3] == 'uni':
            glyph = glyph.replace('uni', '\\u')
        if glyph[:2] == 'uF':
            glyph = glyph.replace('uF', '\\u')
        if glyph == '\\uversal':
            continue

        char = to_unicode(glyph)
        char_list.append(char)
    return char_list 
Example #19
Source File: gftools-fix-vendorid.py    From gftools with Apache License 2.0 5 votes vote down vote up
def main():
  # set up a basic logging config
  # to include timestamps
  # log_format = '%(asctime)s %(levelname)-8s %(message)s'
  global font
  log_format = '%(levelname)-8s %(message)s  '
  logger = logging.getLogger()
  handler = logging.StreamHandler()
  formatter = logging.Formatter(log_format)
  handler.setFormatter(formatter)
  logger.addHandler(handler)
  args = parser.parse_args()

  # ------------------------------------------------------
  logging.debug("Checking each file is a ttf")
  fonts_to_check = []
  for arg_filepath in sorted(args.arg_filepaths):
    # use glob.glob to accept *.ttf
    for fullpath in glob.glob(arg_filepath):
      file_path, file_name = os.path.split(fullpath)
      if file_name.endswith(".ttf"):
        fonts_to_check.append(fullpath)
      else:
        logging.warning("Skipping '{}' as it does not seem "
                        "to be valid TrueType font file.".format(file_name))
  fonts_to_check.sort()

  if fonts_to_check == []:
    logging.error("None of the fonts are valid TrueType files!")

 # ------------------------------------------------------
  for font_file in fonts_to_check:
    font = ttLib.TTFont(font_file)
    logging.info("OK: {} opened with fontTools".format(font_file))

    # ----------------------------------------------------
    vid = font['OS/2'].achVendID
    print("[{}]: {}".format(vid, font_file)) 
Example #20
Source File: __init__.py    From compreffor with Apache License 2.0 5 votes vote down vote up
def decompress(ttFont, **kwargs):
    """ Use the FontTools Subsetter to desubroutinize the font's CFF table.
    Any keyword arguments are passed on as options to the Subsetter.
    Skip if the font contains no subroutines.
    """
    if not has_subrs(ttFont):
        log.debug('No subroutines found; skip decompress')
        return

    from fontTools import subset

    # The FontTools subsetter modifies many tables by default; here
    # we only want to desubroutinize, so we run the subsetter on a
    # temporary copy and extract the resulting CFF table from it
    make_temp = kwargs.pop('make_temp', True)
    if make_temp:
        from io import BytesIO
        from fontTools.ttLib import TTFont, newTable

        stream = BytesIO()
        ttFont.save(stream, reorderTables=None)
        stream.flush()
        stream.seek(0)
        tmpfont = TTFont(stream)
    else:
        tmpfont = ttFont  # run subsetter on the original font

    options = subset.Options(**kwargs)
    options.desubroutinize = True
    options.notdef_outline = True
    subsetter = subset.Subsetter(options=options)
    subsetter.populate(glyphs=tmpfont.getGlyphOrder())
    subsetter.subset(tmpfont)

    if make_temp:
        # copy modified CFF table to original font
        data = tmpfont['CFF '].compile(tmpfont)
        table = newTable('CFF ')
        table.decompile(data, ttFont)
        ttFont['CFF '] = table
        tmpfont.close() 
Example #21
Source File: ttxCompiler.py    From fontgoggles with Apache License 2.0 5 votes vote down vote up
def compileTTXToPath(ttxPath, ttPath):
    font = TTFont()
    font.importXML(ttxPath)
    font.save(ttPath, reorderTables=False) 
Example #22
Source File: dsFont.py    From fontgoggles with Apache License 2.0 5 votes vote down vote up
def _getUnicodesAndAnchors(self, sourcePath):
        f = io.BytesIO(self._sourceFontData[sourcePath])
        ttFont = TTFont(f, lazy=True)
        unicodes = defaultdict(list)
        for code, gn in ttFont.getBestCmap().items():
            unicodes[gn].append(code)
        anchors = pickle.loads(ttFont["FGAx"].data)
        return unicodes, anchors


# From FreeType: 
Example #23
Source File: ftFont.py    From fontgoggles with Apache License 2.0 5 votes vote down vote up
def __init__(self, fontData, *, fontNumber=0, ttFont=None):
        if ttFont is None:
            stream = io.BytesIO(fontData)
            ttFont = TTFont(stream, fontNumber=fontNumber, lazy=True)
        self._ttFont = ttFont
        stream = io.BytesIO(fontData)
        self._ftFace = freetype.Face(stream, index=fontNumber)
        try:
            self._ftFace.set_char_size(self._ftFace.units_per_EM)
        except freetype.FT_Exception as e:
            logging.warning("FreeType error, possibly with unsupported pixel font: %s", e) 
Example #24
Source File: util.py    From compreffor with Apache License 2.0 5 votes vote down vote up
def check_call_depth(compressed_file):
    """Runs `check_cff_call_depth` on a file"""

    f = ttLib.TTFont(compressed_file)

    return check_cff_call_depth(f["CFF "].cff) 
Example #25
Source File: FontRemapProcessors.py    From ReadableWebProxy with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def load_fonts():
	fonts = []

	fontdir = os.path.join(os.path.dirname(__file__), "fonts")
	for font_name in tqdm.tqdm(os.listdir(fontdir)):
		if font_name.endswith(".woff"):
			with open(os.path.join(fontdir, font_name), "rb") as fp:
				font = TTFont(fp)
				fonts.append((font, font_name))

	return fonts 
Example #26
Source File: __init__.py    From compreffor with Apache License 2.0 5 votes vote down vote up
def compress(ttFont, method_python=False, **options):
    """ Subroutinize TTFont instance in-place using the C++ Compreffor.
    If 'method_python' is True, use the slower, pure-Python Compreffor.
    If the font already contains subroutines, it is first decompressed.
    """
    if has_subrs(ttFont):
        log.warning(
            "There are subroutines in font; must decompress it first")
        decompress(ttFont)
    if method_python:
        pyCompressor.compreff(ttFont, **options)
    else:
        cxxCompressor.compreff(ttFont, **options) 
Example #27
Source File: subr_grapher.py    From compreffor with Apache License 2.0 5 votes vote down vote up
def get_cff(filename):
    if os.path.splitext(filename)[1] == '.cff':
        res = cffLib.CFFFontSet()
        res.decompile(open(filename), None)
        return res
    else:
        return TTFont(filename)['CFF '].cff 
Example #28
Source File: hbShape.py    From fontgoggles with Apache License 2.0 5 votes vote down vote up
def __init__(self, fontData, *, fontNumber=0,
                 getGlyphNameFromCodePoint=None,
                 getHorizontalAdvance=None,
                 getVerticalAdvance=None,
                 getVerticalOrigin=None,
                 ttFont=None):
        self._fontData = fontData
        self._fontNumber = fontNumber
        self.face = hb.Face(fontData, fontNumber)
        self.font = hb.Font(self.face)

        if ttFont is None:
            f = io.BytesIO(self._fontData)
            ttFont = TTFont(f, fontNumber=self._fontNumber, lazy=True)
        self._ttFont = ttFont
        self.glyphOrder = ttFont.getGlyphOrder()

        if getGlyphNameFromCodePoint is None and getHorizontalAdvance is not None:
            def _getGlyphNameFromCodePoint(cmap, codePoint):
                return cmap.get(codePoint)
            getGlyphNameFromCodePoint = functools.partial(_getGlyphNameFromCodePoint, self._ttFont.getBestCmap())

        if getGlyphNameFromCodePoint is not None:
            assert getHorizontalAdvance is not None

        self.getGlyphNameFromCodePoint = getGlyphNameFromCodePoint
        self.getHorizontalAdvance = getHorizontalAdvance
        self.getVerticalAdvance = getVerticalAdvance
        self.getVerticalOrigin = getVerticalOrigin

        if getGlyphNameFromCodePoint is not None and getHorizontalAdvance is not None:
            self._funcs = hb.FontFuncs.create()
            self._funcs.set_nominal_glyph_func(_getGlyphIDFunc, self)
            self._funcs.set_glyph_h_advance_func(_getHorizontalAdvanceFunc, self)
            if getVerticalAdvance is not None:
                self._funcs.set_glyph_v_advance_func(_getVerticalAdvanceFunc, self)
            if getVerticalOrigin is not None:
                self._funcs.set_glyph_v_origin_func(_getVerticalOriginFunc, self)
        else:
            self._funcs = None 
Example #29
Source File: pyCompressor.py    From compreffor with Apache License 2.0 5 votes vote down vote up
def compreff(font, **options):
    """ Main function that compresses `font`, a TTFont object, in place. """
    Compreffor(font, **options).compress() 
Example #30
Source File: true_type_font.py    From pdf-annotate with MIT License 5 votes vote down vote up
def __init__(self, path, font_name, font_size=None):
        self.ttfPath = path
        self._ttfFont = TTFont(self.ttfPath)
        # Subsetted fonts have 6 random letters prepended to their names
        # See section 9.6.4 - Font Subsets of the PDF 1.7 Spec
        self.fontName = 'RXMLFT+' + font_name

        self.metrics = self._calculate(self._ttfFont)
        self._glyph_set = self._ttfFont.getGlyphSet()
        self._font_size = font_size