Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash on kern table #138

Merged
merged 2 commits into from
Apr 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 55 additions & 33 deletions src/diffenator2/jfont.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
from __future__ import annotations

import json
from copy import deepcopy as copy

from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._n_a_m_e import table__n_a_m_e
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r
from fontTools.ttLib.tables.S_T_A_T_ import table_S_T_A_T_
from fontTools.ttLib.tables._c_m_a_p import table__c_m_a_p
from fontTools.ttLib.tables._g_l_y_f import Glyph
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r
from fontTools.ttLib.tables._g_l_y_f import (
flagOnCurve,
flagOverlapSimple,
flagCubic,
ARG_1_AND_2_ARE_WORDS,
ARGS_ARE_XY_VALUES,
ROUND_XY_TO_GRID,
WE_HAVE_A_SCALE,
NON_OVERLAPPING,
MORE_COMPONENTS,
WE_HAVE_AN_X_AND_Y_SCALE,
WE_HAVE_A_TWO_BY_TWO,
WE_HAVE_INSTRUCTIONS,
USE_MY_METRICS,
NON_OVERLAPPING,
OVERLAP_COMPOUND,
ROUND_XY_TO_GRID,
SCALED_COMPONENT_OFFSET,
UNSCALED_COMPONENT_OFFSET,
USE_MY_METRICS,
WE_HAVE_A_SCALE,
WE_HAVE_A_TWO_BY_TWO,
WE_HAVE_AN_X_AND_Y_SCALE,
WE_HAVE_INSTRUCTIONS,
Glyph,
flagCubic,
flagOnCurve,
flagOverlapSimple,
)
from fontTools.ttLib.tables._k_e_r_n import table__k_e_r_n
from fontTools.ttLib.tables._n_a_m_e import table__n_a_m_e
from fontTools.ttLib.tables.S_T_A_T_ import table_S_T_A_T_

class_defs = {
1: "Base Glyph",
Expand All @@ -48,7 +51,7 @@ def serialise_fvar_table(obj, root):
"minValue": a.minValue,
"maxValue": a.maxValue,
"defaultValue": a.defaultValue,
"axisName": nametbl.getName(a.axisNameID, 3, 1, 0x409).toUnicode()
"axisName": nametbl.getName(a.axisNameID, 3, 1, 0x409).toUnicode(),
# TODO get axis Name Value (will need ttFont obj)
}
for a in obj.axes
Expand All @@ -57,10 +60,11 @@ def serialise_fvar_table(obj, root):
instances = {
nametbl.getName(i.subfamilyNameID, 3, 1, 0x409).toUnicode(): {
"coordinates": i.coordinates,
"postscriptName": None if i.postscriptNameID in (None, 0xFFFF) else \
nametbl.getName(
i.postscriptNameID, 3, 1, 0x409
).toUnicode(),
"postscriptName": (
None
if i.postscriptNameID in (None, 0xFFFF)
else nametbl.getName(i.postscriptNameID, 3, 1, 0x409).toUnicode()
),
"flags": i.flags,
}
for i in obj.instances
Expand Down Expand Up @@ -98,6 +102,12 @@ def serialise_cmap(obj):
return {f"0x{hex(k)[2:].zfill(4).upper()}": v for k, v in obj.getBestCmap().items()}


def serialise_kern(obj):
return [
{"/".join(k): v for k, v in table.kernTable.items()} for table in obj.kernTables
]


def bit_list(bits, cast_list):
res = []
for bit, name in cast_list:
Expand All @@ -107,12 +117,11 @@ def bit_list(bits, cast_list):


def serialise_component(compo):
from fontTools.misc.fixedTools import (
fixedToFloat as fi2fl,
floatToFixed as fl2fi,
floatToFixedToStr as fl2str,
strToFixedToFloat as str2fl,
)
from fontTools.misc.fixedTools import fixedToFloat as fi2fl
from fontTools.misc.fixedTools import floatToFixed as fl2fi
from fontTools.misc.fixedTools import floatToFixedToStr as fl2str
from fontTools.misc.fixedTools import strToFixedToFloat as str2fl

attrs = {"glyphName": compo.glyphName}
if not hasattr(compo, "firstPt"):
attrs["x"] = compo.x
Expand Down Expand Up @@ -145,17 +154,23 @@ def serialise_component(compo):
(USE_MY_METRICS, "USE_MY_METRICS"),
(OVERLAP_COMPOUND, "OVERLAP_COMPOUND"),
(SCALED_COMPONENT_OFFSET, "SCALED_COMPONENT_OFFSET"),
(UNSCALED_COMPONENT_OFFSET, "UNSCALED_COMPONENT_OFFSET")
(UNSCALED_COMPONENT_OFFSET, "UNSCALED_COMPONENT_OFFSET"),
]
attrs["flags"] = bit_list(compo.flags, compo_bit_list)
return attrs


def serialise_glyph(obj, root):
if obj.isComposite():
return {f"Component {i}: {c.glyphName}": serialise_component(c) for i, c in enumerate(obj.components)}
return {
f"Component {i}: {c.glyphName}": serialise_component(c)
for i, c in enumerate(obj.components)
}
elif obj.isVarComposite():
return {f"Component {i}: {c.glyphName}": serialise_component(c) for i, c in enumerate(obj.components)}
return {
f"Component {i}: {c.glyphName}": serialise_component(c)
for i, c in enumerate(obj.components)
}
else:
last = 0
contours = {}
Expand Down Expand Up @@ -189,7 +204,7 @@ def TTJ(ttFont):
return _TTJ(ttFont, root)


def _TTJ(obj, root=None,depth=1):
def _TTJ(obj, root=None, depth=1):
"""Convert a TTFont to Basic python types"""
if isinstance(obj, (float, int, str, bool)):
return obj
Expand All @@ -205,20 +220,27 @@ def _TTJ(obj, root=None,depth=1):

elif isinstance(obj, table__c_m_a_p):
return serialise_cmap(obj)


elif isinstance(obj, table__k_e_r_n):
return serialise_kern(obj)

elif isinstance(obj, Glyph):
return serialise_glyph(obj, root)

elif isinstance(obj, TTFont):
if depth > 1:
return None
return {k: _TTJ(obj[k], root) for k in obj.keys() if k not in ["loca", "GPOS", "GSUB", "GVAR"]}
return {
k: _TTJ(obj[k], root)
for k in obj.keys()
if k not in ["loca", "GPOS", "GSUB", "GVAR"]
}
elif isinstance(obj, dict):
return {k: _TTJ(v, root) for k, v in obj.items()}
elif isinstance(obj, (list, tuple, set)):
return [_TTJ(i, root) for i in obj]
elif hasattr(obj, "__dict__"):
return {k: _TTJ(getattr(obj, k), root, depth=depth+1) for k in vars(obj)}
return {k: _TTJ(getattr(obj, k), root, depth=depth + 1) for k in vars(obj)}
return obj


Expand Down Expand Up @@ -293,7 +315,7 @@ def clean(self, obj):
return res

def render(self):
return f'<script>var fontdiff = {json.dumps(self.diff)};</script>'
return f"<script>var fontdiff = {json.dumps(self.diff)};</script>"

def summary(self):
raise NotImplementedError()
Expand Down
Loading