fonttools / fontbakery

🧁 A font quality assurance tool for everyone
https://fontbakery.readthedocs.io
Apache License 2.0
537 stars 99 forks source link

Parameter for all fonts split by family and style? #1904

Open madig opened 6 years ago

madig commented 6 years ago

I want users to be able to run a spec-checker on an entire directory which may contain several styles of an entire family, e.g. Sans and Serif with their Display variants in uprights and italics. Some checks are only meaningful if they look at a specific family and style -- e.g. italics may have a few more glyphs, so a glyph set checker needs to check it seperately from the uprights.

I currently take all fonts and split them into families and styles in the test, which also means that the test and yields have to more verbose so people see what family is being complained about, the test is skipped if there's just one family/style passed in, etc. Is there a more elegant way, e.g. def check_something(ufo_fonts_by_family_and_style) where the checkrunner splits the fonts beforehand and then invokes the test with each set?

graphicore commented 6 years ago

No, not yet. I was thinking about/started experimenting with this kind of thing, but I didn't finish it. I guess it was tricky to do ;-) I'll give it another round, it's an interesting problem.

madig commented 6 years ago
def fonts_by_family_and_style(
    ufo_fonts: List[defcon.Font]
) -> Iterable[Tuple[List[defcon.Font], Text]]:
    """Yield lists of UFOs seperated by family and style."""
    font_dict: Dict[Text, List[defcon.Font]] = {}

    for font in ufo_fonts:
        # Seperate italics from the uprights -- they might be composed
        # differently in some places.
        if "italic" in font.info.styleName.lower():
            family_name = font.info.familyName + " (Italics)"
        else:
            family_name = font.info.familyName

        if not font_dict.get(family_name):
            font_dict[family_name] = []

        font_dict[family_name].append(font)

    for family, fonts in font_dict.items():
        yield fonts, family
@check(id="com.daltonmaag/check/something")
def check_something(ufo_fonts):
    """something"""
    from damacheck.util import fonts_by_family_and_style

    for fonts, family in fonts_by_family_and_style(ufo_fonts):
        if len(fonts) == 1:
            yield SKIP, f"Only one font in family ({[font.path for font in fonts]}), skipping check."
            continue

        [...]
madig commented 6 years ago

Hm. Couldn't this be written like this:

def ttFonts_split_by_family_and_style(ttFonts):  # condition
    return ...

def check_something(ttFonts_split_by_family_and_style):
    ...
graphicore commented 6 years ago

Oh, of course. But didn't you mean (I was thinking about/I'd like) to get rid if the for fonts, family in fonts_by_family_and_style within the check and let that be done by dependency injection, calling the check repeatedly for each item in fonts_by_family_and_style


@condition
def ttFonts_split_by_family_and_style(ttFonts):
    return [(fonts, family), (fonts, family), (fonts, family)), ...]

# some configuration to make ttFonts_split_by_family_and_style an iterarg 
# "ttFonts_by_family_and_style"

def check_something(ttFonts_by_family_and_style):
 """something"""
    from damacheck.util import fonts_by_family_and_style_check

    fonts, family = ttFonts_by_family_and_style

    if len(fonts) == 1:
            yield SKIP, f"Only one font in family ({[font.path for font in fonts]}), skipping check."
            continue