Example #1
0
def DISABLED_test_check_glyphnames_max_length():
  """ Check that glyph names do not exceed max length. """
  from fontbakery.profiles.universal import com_google_fonts_check_glyphnames_max_length as check
  import defcon
  import ufo2ft

  # TTF
  test_font = defcon.Font(TEST_FILE("test.ufo"))
  test_ttf = ufo2ft.compileTTF(test_font)
  status, _ = list(check(test_ttf))[-1]
  assert status == PASS

  test_glyph = defcon.Glyph()
  test_glyph.unicode = 0x1234
  test_glyph.name = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
  test_font.insertGlyph(test_glyph)

  test_ttf = ufo2ft.compileTTF(test_font, useProductionNames=False)
  status, _ = list(check(test_ttf))[-1]
  assert status == FAIL

  test_ttf = ufo2ft.compileTTF(test_font, useProductionNames=True)
  status, _ = list(check(test_ttf))[-1]
  assert status == PASS

  # Upgrade to post format 3.0 and roundtrip data to update TTF object.
  test_ttf["post"].formatType = 3.0
  test_file = io.BytesIO()
  test_ttf.save(test_file)
  test_ttf = TTFont(test_file)
  status, message = list(check(test_ttf))[-1]
  assert status == PASS
  assert "format 3.0" in message

  del test_font, test_ttf, test_file  # Prevent copypasta errors.

  # CFF
  test_font = defcon.Font(TEST_FILE("test.ufo"))
  test_otf = ufo2ft.compileOTF(test_font)
  status, _ = list(check(test_otf))[-1]
  assert status == PASS

  test_font.insertGlyph(test_glyph)

  test_otf = ufo2ft.compileOTF(test_font, useProductionNames=False)
  status, _ = list(check(test_otf))[-1]
  assert status == FAIL

  test_otf = ufo2ft.compileOTF(test_font, useProductionNames=True)
  status, _ = list(check(test_otf))[-1]
  assert status == PASS
Example #2
0
    def save_otf(self, ufo, is_instance=False, mti_feafiles=None,
                 kern_writer=KernFeatureWriter):
        """Build OTF from UFO."""

        otf_path = self._output_path(ufo, 'otf', is_instance)
        otf = compileOTF(ufo, kernWriter=kern_writer)
        otf.save(otf_path)
Example #3
0
def build(args):
    ufo = merge(args)

    setInfo(ufo.info, args.version)
    buildExtraGlyphs(ufo)
    removeOverlap(ufo)

    if args.out_file.endswith(".ttf"):
        otf = compileTTF(ufo)
    else:
        otf = compileOTF(ufo)

    otf = subsetGlyphs(otf, ufo)

    return otf
def generate_and_write_autohinted_instance(
    instantiator: instantiator.Instantiator,
    instance_descriptor: fontTools.designspaceLib.InstanceDescriptor,
    output_dir: Path,
    psautohint: str,
):
    # 3. Generate instance UFO.
    instance = instantiator.generate_instance(instance_descriptor)
    file_stem = f"{instance.info.familyName}-{instance.info.styleName}".replace(" ", "")

    # 3.5. Optionally write instance UFO to disk, for debugging.
    # instance.save(output_dir / f"{file_stem}.ufo", overwrite=True)

    # 4. Compile and write instance OTF to disk.
    instance_font = ufo2ft.compileOTF(instance, removeOverlaps=True, inplace=True)
    output_path = output_dir / f"{file_stem}.otf"
    instance_font.save(output_path)

    # 5. Run psautohint on it.
    subprocess.run([psautohint, str(output_path)])
Example #5
0
    def save_otf(self, ufo, is_instance=False, kern_writer=KernFeatureWriter):
        """Build OTF from UFO."""

        otf_path = self._output_path(ufo, 'otf', is_instance)
        otf = compileOTF(ufo, kernWriter=kern_writer)
        otf.save(otf_path)
Example #6
0
    def save_otfs(self,
                  ufos,
                  ttf=False,
                  is_instance=False,
                  interpolatable=False,
                  use_afdko=False,
                  autohint=None,
                  subset=None,
                  use_production_names=None,
                  subroutinize=False,
                  interpolate_layout_from=None,
                  interpolate_layout_dir=None,
                  output_path=None,
                  output_dir=None,
                  kern_writer_class=None,
                  mark_writer_class=None,
                  inplace=True):
        """Build OpenType binaries from UFOs.

        Args:
            ufos: Font objects to compile.
            ttf: If True, build fonts with TrueType outlines and .ttf extension.
            is_instance: If output fonts are instances, for generating paths.
            interpolatable: If output is interpolatable, for generating paths.
            use_afdko: If True, use AFDKO to compile feature source.
            autohint: Parameters to provide to ttfautohint. If not provided, the
                autohinting step is skipped.
            subset: Whether to subset the output according to data in the UFOs.
                If not provided, also determined by flags in the UFOs.
            use_production_names: Whether to use production glyph names in the
                output. If not provided, determined by flags in the UFOs.
            subroutinize: If True, subroutinize CFF outlines in output.
            interpolate_layout_from: A designspace path to give varLib for
                interpolating layout tables to use in output.
            interpolate_layout_dir: Directory containing the compiled master
                fonts to use for interpolating binary layout tables.
            output_path: output font file path. Only works when the input
                'ufos' list contains a single font.
            output_dir: directory where to save output files. Mutually
                exclusive with 'output_path' argument.
            kern_writer_class: Class overriding ufo2ft's KernFeatureWriter.
            mark_writer_class: Class overriding ufo2ft's MarkFeatureWriter.
        """
        assert not (output_path and output_dir), "mutually exclusive args"

        if output_path is not None and len(ufos) > 1:
            raise ValueError("output_path requires a single input")

        ext = 'ttf' if ttf else 'otf'
        fea_compiler = FDKFeatureCompiler if use_afdko else FeatureCompiler

        if kern_writer_class is not None:
            logger.info("Using %r", kern_writer_class.__module__)
        if mark_writer_class is not None:
            logger.info("Using %r", mark_writer_class.__module__)

        if interpolate_layout_from is not None:
            if interpolate_layout_dir is None:
                interpolate_layout_dir = self._output_dir(
                    ext, is_instance=False, interpolatable=interpolatable)
            finder = partial(_varLib_finder,
                             directory=interpolate_layout_dir,
                             ext=ext)

        do_autohint = ttf and autohint is not None
        for ufo in ufos:
            name = self._font_name(ufo)
            logger.info('Saving %s for %s' % (ext.upper(), name))

            if use_production_names is None:
                use_production_names = not ufo.lib.get(
                    GLYPHS_PREFIX + "Don't use Production Names")
            compiler_options = dict(
                featureCompilerClass=fea_compiler,
                kernWriterClass=kern_writer_class,
                markWriterClass=mark_writer_class,
                glyphOrder=ufo.lib.get(PUBLIC_PREFIX + 'glyphOrder'),
                useProductionNames=use_production_names,
                inplace=True,  # avoid extra copy
            )
            if ttf:
                font = compileTTF(ufo, convertCubics=False, **compiler_options)
            else:
                font = compileOTF(ufo,
                                  optimizeCFF=subroutinize,
                                  **compiler_options)

            if interpolate_layout_from is not None:
                master_locations, instance_locations = self._designspace_locations(
                    interpolate_layout_from)
                loc = instance_locations[_normpath(ufo.path)]
                gpos_src = interpolate_layout(interpolate_layout_from,
                                              loc,
                                              finder,
                                              mapped=True)
                font['GPOS'] = gpos_src['GPOS']
                gsub_src = TTFont(
                    finder(self._closest_location(master_locations, loc)))
                if 'GDEF' in gsub_src:
                    font['GDEF'] = gsub_src['GDEF']
                if 'GSUB' in gsub_src:
                    font['GSUB'] = gsub_src['GSUB']

            if do_autohint:
                # if we are autohinting, we save the unhinted font to a
                # temporary path, and the hinted one to the final destination
                fd, otf_path = tempfile.mkstemp("." + ext)
                os.close(fd)
            elif output_path is None:
                otf_path = self._output_path(ufo,
                                             ext,
                                             is_instance,
                                             interpolatable,
                                             output_dir=output_dir)
            else:
                otf_path = output_path
            font.save(otf_path)

            if subset is None:
                export_key = GLYPHS_PREFIX + 'Glyphs.Export'
                subset = ((GLYPHS_PREFIX + 'Keep Glyphs') in ufo.lib or any(
                    glyph.lib.get(export_key, True) is False for glyph in ufo))
            if subset:
                self.subset_otf_from_ufo(otf_path, ufo)

            if not do_autohint:
                continue

            if output_path is not None:
                hinted_otf_path = output_path
            else:
                hinted_otf_path = self._output_path(ufo,
                                                    ext,
                                                    is_instance,
                                                    interpolatable,
                                                    autohinted=True,
                                                    output_dir=output_dir)
            try:
                ttfautohint(otf_path, hinted_otf_path, args=autohint)
            except TTFAError:
                # copy unhinted font to destination before re-raising error
                shutil.copyfile(otf_path, hinted_otf_path)
                raise
            finally:
                # must clean up temp file
                os.remove(otf_path)
Example #7
0
def TTFontFactory(font, useProductionNames=False, optimizeCff=False):
    otf = compileOTF(
        font, useProductionNames=useProductionNames, optimizeCff=optimizeCff)
    return otf
Example #8
0
 def test_TestFont_CFF(self):
     self.expectTTX(compileOTF(loadUFO("TestFont.ufo")), "TestFont-CFF.ttx")
Example #9
0
 def test_optimizeCFF_specialize(self, testufo, cff_version, expected_ttx):
     otf = compileOTF(testufo, optimizeCFF=1, cffVersion=cff_version)
     expectTTX(otf, expected_ttx)
Example #10
0
 def test_TestFont_CFF(self, testufo):
     otf = compileOTF(testufo)
     expectTTX(otf, "TestFont-CFF.ttx")
Example #11
0
 def test_removeOverlaps_CFF(self, testufo):
     otf = compileOTF(testufo, removeOverlaps=True)
     expectTTX(otf, "TestFont-NoOverlaps-CFF.ttx")
Example #12
0
 def test_optimizeCFF_specialize(self, testufo):
     otf = compileOTF(testufo, optimizeCFF=1)
     expectTTX(otf, "TestFont-Specialized-CFF.ttx")
Example #13
0
 def testTestFont(self):
     # We have specific unit tests for CFF vs TrueType output, but we run
     # an integration test here to make sure things work end-to-end.
     # No need to test both formats for every single test case.
     self.expectTTX(compileTTF(loadUFO("TestFont.ufo")), "TestFont.ttx")
     self.expectTTX(compileOTF(loadUFO("TestFont.ufo")), "TestFont-CFF.ttx")
Example #14
0
import extractor
import defcon
# from fontTools.ttLib import TTFont
from ufo2ft import compileOTF

ufo = defcon.Font()

# Take the font generated by FL5 from the VFB and extract it to UFO
extractor.extractUFO("data/ibm_plex/IBM Plex Serif-Text-FL.otf", ufo)

# Save the extracted UFO
ufo.save("data/ibm_plex/IBM Plex Serif-Text-FL_extracted.otf.ufo")
ufo = defcon.Font("data/ibm_plex/IBM Plex Serif-Text-FL_extracted.otf.ufo")

# Build a new TTF from the extracted UFO
ttf = compileOTF(ufo)
ttf.save("data/ibm_plex/IBM Plex Serif-Text-ufo2ft.otf")

# Force recompilation by closing and reopening the font; not needed
# ttf.close()
# ttf = TTFont("data/ibm_plex/IBM Plex Serif-Text-ufo2ft.ttf")

# Also save TTX dump
ttf.saveXML("data/ibm_plex/IBM Plex Serif-Text-ufo2ft.otf.ttx")
ttf.saveXML("data/ibm_plex/IBM Plex Serif-Text-FL.otf.ttx")

# ufo = defcon.Font()
# extractor.extractUFO("data/font_a/font-normal-fl.ttf", ufo)
# ufo.save("data/font_a/font-normal-fl_extracted.ufo")
# ufo = defcon.Font("data/font_a/font-normal-fl_extracted.ufo")
# ttf = compileTTF(ufo)
Example #15
0
 def test_removeOverlaps_CFF(self):
     self.expectTTX(
         compileOTF(loadUFO("TestFont.ufo"), removeOverlaps=True),
         "TestFont-NoOverlaps-CFF.ttx")
Example #16
0
from defcon import Font
from ufo2ft import compileOTF

ufo = Font('removeOverlaps_error.ufo')
ufo.info.xHeight = 300
ufo.info.capHeight = 700

otf = compileOTF(ufo, removeOverlaps=True)
otf.save('removeOverlaps_error.otf')
Example #17
0
 def test_optimizeCFF_subroutinize(self, testufo):
     otf = compileOTF(testufo, optimizeCFF=2)
     expectTTX(otf, "TestFont-CFF.ttx")
Example #18
0
    def save_otfs(self,
                  ufos,
                  ttf=False,
                  is_instance=False,
                  interpolatable=False,
                  use_afdko=False,
                  autohint=None,
                  subset=None,
                  use_production_names=None,
                  subroutinize=False,
                  interpolate_layout_from=None,
                  kern_writer_class=None,
                  mark_writer_class=None):
        """Build OpenType binaries from UFOs.

        Args:
            ufos: Font objects to compile.
            ttf: If True, build fonts with TrueType outlines and .ttf extension.
            is_instance: If output fonts are instances, for generating paths.
            interpolatable: If output is interpolatable, for generating paths.
            use_afdko: If True, use AFDKO to compile feature source.
            autohint: Parameters to provide to ttfautohint. If not provided, the
                autohinting step is skipped.
            subset: Whether to subset the output according to data in the UFOs.
                If not provided, also determined by flags in the UFOs.
            use_production_names: Whether to use production glyph names in the
                output. If not provided, determined by flags in the UFOs.
            subroutinize: If True, subroutinize CFF outlines in output.
            interpolate_layout_from: A designspace path to give varLib for
                interpolating layout tables to use in output.
            kern_writer_class: Class overriding ufo2ft's KernFeatureWriter.
            mark_writer_class: Class overriding ufo2ft's MarkFeatureWriter.
        """

        ext = 'ttf' if ttf else 'otf'
        fea_compiler = FDKFeatureCompiler if use_afdko else FeatureCompiler

        if kern_writer_class is None:
            kern_writer_class = KernFeatureWriter
        else:
            logger.info("Using %r", kern_writer_class.__module__)

        if mark_writer_class is None:
            mark_writer_class = MarkFeatureWriter
        else:
            logger.info("Using %r", mark_writer_class.__module__)

        if interpolate_layout_from is not None:
            master_locations, instance_locations = self._designspace_locations(
                interpolate_layout_from)
            ufod = self._output_dir('ufo', False, interpolatable)
            otfd = self._output_dir(ext, False, interpolatable)
            finder = lambda s: s.replace(ufod, otfd).replace('.ufo', '.' + ext)

        for ufo in ufos:
            name = self._font_name(ufo)
            logger.info('Saving %s for %s' % (ext.upper(), name))

            otf_path = self._output_path(ufo, ext, is_instance, interpolatable)
            if use_production_names is None:
                use_production_names = not ufo.lib.get(
                    GLYPHS_PREFIX + "Don't use Production Names")
            compiler_options = dict(featureCompilerClass=fea_compiler,
                                    kernWriterClass=kern_writer_class,
                                    markWriterClass=mark_writer_class,
                                    glyphOrder=ufo.lib.get(PUBLIC_PREFIX +
                                                           'glyphOrder'),
                                    useProductionNames=use_production_names)
            if ttf:
                font = compileTTF(ufo, convertCubics=False, **compiler_options)
            else:
                font = compileOTF(ufo,
                                  optimizeCFF=subroutinize,
                                  **compiler_options)

            if interpolate_layout_from is not None:
                loc = instance_locations[ufo.path]
                gpos_src = interpolate_layout(interpolate_layout_from,
                                              loc,
                                              finder,
                                              mapped=True)
                font['GPOS'] = gpos_src['GPOS']
                gsub_src = TTFont(
                    finder(self._closest_location(master_locations, loc)))
                font['GDEF'] = gsub_src['GDEF']
                font['GSUB'] = gsub_src['GSUB']

            font.save(otf_path)

            if subset is None:
                export_key = GLYPHS_PREFIX + 'Glyphs.Export'
                subset = ((GLYPHS_PREFIX + 'Keep Glyphs') in ufo.lib or any(
                    glyph.lib.get(export_key, True) is False for glyph in ufo))
            if subset:
                self.subset_otf_from_ufo(otf_path, ufo)

            if ttf and autohint is not None:
                hinted_otf_path = self._output_path(ufo,
                                                    ext,
                                                    is_instance,
                                                    interpolatable,
                                                    autohinted=True)
                ttfautohint(otf_path, hinted_otf_path, args=autohint)
Example #19
0
 def test_removeOverlaps_CFF_pathops(self, testufo):
     otf = compileOTF(testufo,
                      removeOverlaps=True,
                      overlapsBackend="pathops")
     expectTTX(otf, "TestFont-NoOverlaps-CFF-pathops.ttx")
Example #20
0
def TTFontFactory(font):
    otf = compileOTF(font)
    return otf
Example #21
0
 def test_optimizeCFF_none(self, testufo):
     otf = compileOTF(testufo, optimizeCFF=0)
     expectTTX(otf, "TestFont-NoOptimize-CFF.ttx")