Esempio n. 1
0
def main():
    filepath = sys.argv[1]
    tt = TTFont(filepath)
    buildStatTable(tt, AXES)
    update_fvar(tt)
    tt.save(filepath)
    print(f"Added STAT table to {filepath}")
Esempio n. 2
0
def test_updatetNameTable_axis_order(varfont):
    axes = [
        dict(
            tag="wght",
            name="Weight",
            values=[
                dict(value=400, name="Regular"),
            ],
        ),
        dict(
            tag="wdth",
            name="Width",
            values=[
                dict(value=75, name="Condensed"),
            ],
        ),
    ]
    nametable = varfont["name"]
    buildStatTable(varfont, axes)
    instancer.names.updateNameTable(varfont, {"wdth": 75, "wght": 400})
    assert nametable.getName(17, 3, 1, 0x409).toUnicode() == "Regular Condensed"

    # Swap the axes so the names get swapped
    axes[0], axes[1] = axes[1], axes[0]

    buildStatTable(varfont, axes)
    instancer.names.updateNameTable(varfont, {"wdth": 75, "wght": 400})
    assert nametable.getName(17, 3, 1, 0x409).toUnicode() == "Condensed Regular"
Esempio n. 3
0
def build_stat(roman_font, italic_font=None):
    roman_wght_axis = dict(
        tag="wght",
        name="Weight",
        values=build_axis_values(roman_font),
    )
    roman_axes = [roman_wght_axis]
    if italic_font:
        # We need to create a new Italic axis in the Roman font
        roman_axes.append(
            dict(tag="ital",
                 name="Italic",
                 values=[
                     dict(
                         name="Roman",
                         flags=2,
                         value=0.0,
                         linkedValue=1.0,
                     )
                 ]))
        italic_wght_axis = dict(
            tag="wght",
            name="Weight",
            values=build_axis_values(italic_font),
        )
        italic_axes = [italic_wght_axis]
        italic_axes.append(
            dict(tag="ital",
                 name="Italic",
                 values=[dict(
                     name="Italic",
                     value=1.0,
                 )]))
        buildStatTable(italic_font, italic_axes)
    buildStatTable(roman_font, roman_axes)
Esempio n. 4
0
def main():
    font = TTFont(sys.argv[1])

    # Drop VOLT table
    if "TSIV" in font:
        del font["TSIV"]

    # Add STAT table
    os2 = font["OS/2"]
    italic = bool(os2.fsSelection & (1 << 0))

    fvar = font["fvar"]
    axes = [dict(tag=a.axisTag, name=a.axisNameID) for a in fvar.axes]

    if italic:
        value = dict(value=italic, name="Italic")
    else:
        value = dict(value=italic, name="Roman", flags=0x0002, linkedValue=1)
    axes.append(dict(tag="ital", name="Italic", values=[value]))

    buildStatTable(font, axes)

    # Prune name table
    names = [n for n in font["name"].names if n.platformID == 3]

    # Drop Regular from Roman font names
    if not italic:
        for name in names:
            if name.nameID in (3, 6):
                name.string = str(name).replace("-Regular", "")
            if name.nameID == 4:
                name.string = str(name).replace(" Regular", "")

    font["name"].names = names
    font["OS/2"].usMaxContext = maxCtxFont(font)

    font["DSIG"] = DSIG = newTable("DSIG")
    DSIG.ulVersion = 1
    DSIG.usFlag = 0
    DSIG.usNumSigs = 0
    DSIG.signatureRecords = []

    if "glyf" in font and "prep" not in font:
        # Google Fonts “smart dropout control”
        font["prep"] = prep = newTable("prep")
        prep.program = ttProgram.Program()
        prep.program.fromAssembly(
            ["PUSHW[]", "511", "SCANCTRL[]", "PUSHB[]", "4", "SCANTYPE[]"]
        )

    if "MVAR" in font:
        del font["MVAR"]

    font.save(sys.argv[1])
Esempio n. 5
0
def main():
    # process upright files
    filepath = CAS_UPRIGHT
    tt = TTFont(filepath)
    buildStatTable(tt, UPRIGHT_AXES)
    tt.save(filepath)
    print(f"[STAT TABLE] Added STAT table to {filepath}")

    # process italics files
    filepath = CAS_ITALIC
    tt = TTFont(filepath)
    buildStatTable(tt, ITALIC_AXES)
    tt.save(filepath)
    print(f"[STAT TABLE] Added STAT table to {filepath}")
Esempio n. 6
0
def main():
    # process upright files
    filepath = UPRIGHT_SRC
    tt = TTFont(filepath)
    buildStatTable(tt, UPRIGHT_AXES)
    update_fvar(tt)
    tt.save(filepath)
    print(f"[STAT TABLE] Added STAT table to {filepath}")

    # process italics files
    filepath = ITALIC_SRC
    tt = TTFont(filepath)
    buildStatTable(tt, ITALIC_AXES)
    update_fvar(tt)
    tt.save(filepath)
    print(f"[STAT TABLE] Added STAT table to {filepath}")
def main():
    filepath = sys.argv[1]
    tt = TTFont(filepath)

    # remove & replace last item in AXES to work for italic font
    if "Italic" in filepath:
        AXES.pop()
        AXES.append(
            dict(
                tag="ital",
                name="Italic",
                ordering=4,
                values=[
                    dict(nominalValue=1, name="Italic"),
                ],
            ))

    buildStatTable(tt, AXES)
    update_fvar(tt)
    tt.save(filepath)
    print(f"Added STAT table to {filepath}")
def main():
    filepath = VR_UPRIGHT
    tt = TTFont(filepath)
    buildStatTable(tt, UPRIGHT_AXES)
    tt.save(filepath)
    print(f"[STAT TABLE] Added STAT table to {filepath}")
Esempio n. 9
0
def gen_stat_tables_from_config(stat, varfonts, has_italic=None):
    """
    Generate a stat table for each font in a family from a Python configuration.

    Args:
        stat: either a dictionary or list as described below
        varfonts: a list of variable TTFont instances
        has_italic: a boolean indicating whether the family contains an italic.
            If not provided, the stylename of the font files are inspected to
            determine if any of them contain the word ``Italic``.

    The ``stat`` parameter should normally be a list of axis dictionaries in the
    format used by ``buildStatTable``. This list should *not* contain an entry
    for the ``ital`` axis, as this entry will be generated as appropriate for
    each font if ``has_italic`` is True.

    For example::

        varfonts = [
            "Source-Regular-VF[wdth].ttf",
            "Source-Italic-VF[wdth].ttf"
        ]
        stat = [
                { "tag":"wdth", "name": "Width", "values": [ ... ] }
        ]

    Alternately, to allow different STAT table entries for each font, the ``stat``
    parameter may be a dictionary, whose keys are source IDs (usually source
    filenames) corresponding to the appropriate entry in the ``varfonts``
    dictionary and whose values are the list of axis dictionaries for the font.
    Note that in this case, the axes list is passed to ``buildStatTable`` with
    no further manipulation, meaning that if you want an ``ital`` axis, you
    should specify it manually as part of the dictionary.

    For example::

        stat = {
            "Font[wght].ttf": [
                { "tag":"wdth", "name": "Width", "values": [ ... ] },
                { "tag":"ital", "name": "Italic", "values": [ ... ] }
            ],
            "Font-Italic[wght].ttf": [
                { "tag":"wdth", "name": "Width", "values": [ ... ] },
                { "tag":"ital", "name": "Italic", "values": [ ... ] }
            ]
        }
    """
    assert all("fvar" in f for f in varfonts)
    # Check we have no italic
    if isinstance(stat, list):
        if has_italic is None:
            has_italic = any(font_is_italic(f) for f in varfonts)
        if has_italic:
            for ax in stat:
                if ax["name"] == "ital":
                    raise ValueError("ital axis should not appear in stat config")
            ital_stat_for_roman = {
                "name": "Italic", "tag": "ital",
                "values": [dict(value=0, name="Roman", flags=0x2, linkedValue=1)]
            }
            ital_stat_for_italic = {
                "name": "Italic", "tag": "ital",
                "values": [dict(value=1, name="Italic")]
            }

            stat.append({})  # We will switch this entry between Roman and Italic

    for ttFont in varfonts:
        filename = os.path.basename(ttFont.reader.file.name)
        if isinstance(stat, dict):
            if filename not in stat:
                raise ValueError("Filename %s not found in stat dictionary" % filename)
            this_stat = stat[filename]
        else:
            if has_italic:
                if font_is_italic(ttFont):
                    stat[-1] = ital_stat_for_italic
                else:
                    stat[-1] = ital_stat_for_roman
            this_stat = stat
        buildStatTable(ttFont, this_stat)
Esempio n. 10
0
def gen_stat_tables(
    ttFonts, axis_order, elided_axis_values=None, axis_reg=axis_registry
):
    """
    Generate a stat table for each font in a family using the Google Fonts
    Axis Registry.

    Args:
        ttFonts: an iterable containing ttFont instances
        axis_order: a list containing the axis order
        elided_axis_values: a dict containing axes and their values to elide
        e.g {"wght": [400], "wdth": [100]}
        axis_reg: Google Fonts axis registry
    """
    # Heuristic:
    # 1. Gen a STAT table for each font using their fvar tables only
    # 2. Collect all the axes which exist in every font's family name and
    #    and style name
    # 3. Add further Axis Records to each font's stat table for the axes we
    #    found in step 2. Only add them if the stat table doesn't contain them
    #    already.
    # 4. Add an AxisValue to each of the Axes Records we added in step 3.
    #    For each axis in each font, do the following:
    #      a. If a font's name table contains the axis and it is not in the
    #         fvar, we will create a new Axis Value using the axis registry
    #         fallbacks.
    #      b. If a font's name table doesn't contain the axis, we will create a
    #         new Axis Value based the default values found in the axis registry
    #
    #         Example:
    #
    #            Test Case:
    #            Axes in family names: ["wdth", "wght", "ital"]
    #            Font StyleName = "Condensed Bold"
    #            Axes in font fvar = ["wght"]
    #
    #            a result:
    #            axisValue = {"name": "Condensed", "value": 75.0}
    #            "Condensed" exists in our axis registry as a fallback in the
    #            wdth axis
    #
    #            b result:
    #            AxisValue = {"name": "Roman", "value": 0.0, flags=0x2}
    #            Since there isn't an ital token in the Font family name or
    #            style name, the AxisValue will be based on the default values
    #            for the axis in our axis registry
    #
    # 4. For each stat table, update Axis Values which should be linked
    # 5. For each stat table, update Axis Values which should be elided based
    #    on the user arg elided_axis_values (optional)
    # 6. For each stat table, sort axes based on the arg axis_order
    # 7. Use fontTools to build each stat table for each font
    validate_family_fvar_tables(ttFonts)
    stat_tables = [_gen_stat_from_fvar(f) for f in ttFonts]
    axes_in_family_name_records = _axes_in_family_name_records(ttFonts)
    stat_tables = [
        _append_non_fvar_axes_to_stat(ttFont, stat, axes_in_family_name_records)
        for ttFont, stat in zip(ttFonts, stat_tables)
    ]
    seen_axis_values = _seen_axis_values(stat_tables)
    stat_tables = [
        _add_linked_axis_values_to_stat(s, seen_axis_values) for s in stat_tables
    ]
    if elided_axis_values:
        stat_tables = [
            _add_elided_axis_values_to_stat(s, elided_axis_values) for s in stat_tables
        ]

    # TODO make axis_order an optional arg. We can only do this once we
    # have established an axis order in the axis registry
    validate_axis_order(axis_order, set(seen_axis_values.keys()))
    assert len(stat_tables) == len(ttFonts)
    axis_order = [a for a in axis_order if a in seen_axis_values.keys()]
    for stat_table, ttFont in zip(stat_tables, ttFonts):
        stat_table = [stat_table[axis] for axis in axis_order]
        _update_fvar_nametable_records(ttFont, stat_table)
        buildStatTable(ttFont, stat_table)
Esempio n. 11
0
import sys
from fontTools.otlLib.builder import buildStatTable
from fontTools.ttLib import TTFont
from make_designspace import (wghts, ESHPs, EGRDs)

path = sys.argv[1]
font = TTFont(path)

wght_axis = dict(
    tag="wght",
    name="Weight",
    values=[dict(value=v, name=n) for v, _, n in wghts if n is not None]
)

shape_axis = dict(
    tag="ESHP",
    name="Element Shape",
    values=[dict(value=v, name=n) for v, _, n in ESHPs if n is not None]
)

grid_axis = dict(
    tag="EGRD",
    name="Element Grid",
    values=[dict(value=v, name=n) for v, _, n in EGRDs if n is not None]
)

buildStatTable(font, [wght_axis, shape_axis, grid_axis], elidedFallbackName=2)

font.save(path)
print("Added STAT table to %s" % path)
Esempio n. 12
0
widthDict = dict(
    tag="wdth",
    name="Width",
    values=[
        dict(nominalValue=60, name="Condensed", rangeMinValue=60, rangeMaxValue=70),
        dict(nominalValue=80, name="SemiCondensed", rangeMinValue=70, rangeMaxValue=90),
        dict(nominalValue=100, name="Normal", flags=0x2, rangeMinValue=90, rangeMaxValue=100),
    ]
)

format2RomanAxes = [
    weightDict, widthDict,
    dict(
        tag="ital",
        name="Italic",
        values=[dict(value=0, name="Roman", linkedValue=1, flags=0x2)]
    )
]

ttfont = ttLib.TTFont(inRomanFont)
builder.buildStatTable(ttfont,format2RomanAxes)
# ttfont['name'].setName("JuniusVFRoman", 25, 1, 0, 0)
ttfont['name'].setName("JuniusVFRoman", 25, 3, 1, 0x409)
for inst in ttfont['fvar'].instances:
    subfamilyName = ttfont['name'].getName(
        inst.subfamilyNameID,3,1,0x409).toUnicode().replace(" ","")
    inst.postscriptNameID = ttfont['name'].addName("JuniusVFRoman" + "-" + subfamilyName,
                                                   platforms=((3,1,0x409),))
ttfont['name'].removeNames(platformID=1)
ttfont.save(outRomanFont)
Esempio n. 13
0
        2, 3, 1, 1033).toUnicode() else "Roman"
    ps_family_name = f"{family_name.replace(' ', '')}{font_style}"
    nametable.setName(ps_family_name, 25, 3, 1, 1033)

    for instance in fvar.instances:
        instance_style = nametable.getName(instance.subfamilyNameID, 3, 1,
                                           1033).toUnicode()
        instance_style = instance_style.replace("Italic",
                                                "").strip().replace(" ", "")
        if instance_style == "":
            instance_style = "Regular"
        ps_name = f"{ps_family_name}-{instance_style}"
        instance.postscriptNameID = _addName(nametable, ps_name, 256)


buildStatTable(ttFont, axes)
updateFvar(ttFont)

statTable = ttFont['STAT'].table

## Testing STAT version change
# statTable.Version = 0x00010001
# statTable.Version = 0x00010002

ttFont.save(file)

print()
print()
print(basename(file).upper())
print('Added STAT Table version %s.' % (statTable.Version))
Esempio n. 14
0
def rebuildStatTable(font, designspace):
  #
  # Changing this code? See discussion at https://github.com/rsms/inter/issues/308
  #
  if not 'fvar' in font:
    raise Exception('missing fvar table in font')
  axes = [dict(tag=a.axisTag, name=a.axisNameID) for a in font['fvar'].axes]

  # isMultiAxis is true when compiling the multi-axis VF,
  # false when compiling e.g. Inter-roman.var.ttf
  isMultiAxis = False
  if len(axes) > 1:
    isMultiAxis = True

  axisTagToName = dict()
  for axis in designspace.axes:
    axisTagToName[axis.tag] = axis.name

  weightAxisName = axisTagToName['wght']
  slantAxisName = axisTagToName.get('slnt', 'Slant')
  regularWeightValueEntry = None

  weightValues = []
  slantValues = []
  extremeSlantValue = 0
  for instance in designspace.instances:
    weightValue = instance.location[weightAxisName]
    slantValue = instance.location.get(slantAxisName, 0)
    if slantValue != 0:
      # slanted (we only make one entry: "Italic")
      if isMultiAxis and weightValue == 400:
        extremeSlantValue = slantValue
        slantValues.append({
          'name': instance.styleName,
          'value': slantValue,
        })
    else:
      # upright
      v = {
        'name': instance.styleName,
        'value': weightValue,
      }
      if weightValue == 400:
        v['flags'] = OT_ELIDABLE_AXIS_VALUE_NAME
        v['linkedValue'] = 700  # style link to "Bold"
        regularWeightValueEntry = v
      weightValues.append(v)

  # "Regular" entry for the slant axis, linked with the "Italic" entry
  if isMultiAxis:
    slantValues.append({
      'name': regularWeightValueEntry['name'],
      'value': 0,
      'flags': OT_ELIDABLE_AXIS_VALUE_NAME,
      'linkedValue': extremeSlantValue,
    })

  for a in axes:
    tag = a['tag']
    if tag == 'wght':
      a['values'] = weightValues
    elif tag == 'slnt' and len(slantValues) > 0:
      a['values'] = slantValues

  buildStatTable(font, axes)