Esempio n. 1
0
def test_bez(unhinted, hinted):
    unhinted_base = os.path.splitext(unhinted)[0]
    hinted_base = os.path.splitext(hinted)[0]

    bez_font = open_font(unhinted_base + ".bez")
    otf_font = open_font(unhinted_base + ".otf")
    ufo_font = open_font(unhinted_base + ".ufo")
    hinted_bez_font = open_font(hinted_base + ".bez")
    hinted_otf_font = open_font(hinted_base + ".otf")

    bez_info = get_font_info(bez_font, unhinted_base + ".bez")
    otf_info = get_font_info(otf_font, unhinted_base + ".otf")
    ufo_info = get_font_info(ufo_font, unhinted_base + ".ufo")
    assert otf_info == bez_info == ufo_info

    names = sorted(otf_font.getGlyphList())
    assert all(
        sorted(f.getGlyphList()) == names for f in
        [bez_font, otf_font, ufo_font, hinted_bez_font, hinted_otf_font])
    for name in names:
        if name == ".notdef":
            continue
        bez_glyph = get_glyph(bez_font, name)
        otf_glyph = get_glyph(otf_font, name)
        ufo_glyph = get_glyph(ufo_font, name)
        assert otf_glyph == bez_glyph == ufo_glyph

        hinted_bez_glyph = get_glyph(hinted_bez_font, name)
        hinted_otf_glyph = get_glyph(hinted_otf_font, name)
        assert hinted_otf_glyph == hinted_bez_glyph

        result = hint_bez_glyph(bez_info, bez_glyph)
        assert normalize_glyph(result, name) == hinted_bez_glyph
Esempio n. 2
0
def build(instance, opts):
    font = instance.parent
    source = font.masters[0]

    fea, marks = makeFeatures(instance, source)

    glyphOrder = []
    advanceWidths = {}
    characterMap = {}
    charStrings = {}

    source.blueValues = []
    source.otherBlues = []

    for zone in sorted(source.alignmentZones):
        pos = zone.position
        size = zone.size
        vals = sorted((pos, pos + size))
        if pos == 0 or size >= 0:
            source.blueValues.extend(vals)
        else:
            source.otherBlues.extend(vals)

    fontinfo = f"""
        FontName {instance.fontName}
        OrigEmSqUnits {font.upm}
        DominantV {source.verticalStems}
        DominantH {source.horizontalStems}
        BaselineOvershoot {source.blueValues[0]}
        BaselineYCoord {source.blueValues[1]}
        LcHeight {source.blueValues[2]}
        LcOvershoot {source.blueValues[3] - source.blueValues[2]}
        CapHeight {source.blueValues[4]}
        CapOvershoot {source.blueValues[5] - source.blueValues[4]}
        AscenderHeight {source.blueValues[6]}
        AscenderOvershoot {source.blueValues[7] - source.blueValues[6]}
        Baseline5 {source.otherBlues[1]}
        Baseline5Overshoot {source.otherBlues[0] - source.otherBlues[1]}

        FlexOK true
        BlueFuzz 1
    """

    layerSet = {g.name: g.layers[source.id] for g in font.glyphs}
    for glyph in font.glyphs:
        if not glyph.export:
            continue
        name = glyph.name

        glyphOrder.append(name)
        for code in glyph.unicodes:
            characterMap[int(code, 16)] = name

        layer = glyph.layers[source.id]
        width = 0 if name in marks else layer.width

        # Draw glyph and remove overlaps.
        path = Path()
        layer.draw(DecomposePathPen(path, layerSet=layerSet))
        path.simplify(fix_winding=True, keep_starting_points=True)

        # Autohint.
        pen = BezPen(None, True)
        path.draw(pen)
        bez = "\n".join(["% " + name, "sc", *pen.bez, "ed", ""])
        hinted = hint_bez_glyph(fontinfo, bez)
        program = [width] + convertBezToT2(hinted)

        # Build CharString.
        charStrings[name] = T2CharString(program=program)
        advanceWidths[name] = width

    # Make sure .notdef is glyph index 0.
    glyphOrder.pop(glyphOrder.index(".notdef"))
    glyphOrder.insert(0, ".notdef")

    version = float(opts.version)
    vendor = font.customParameters["vendorID"]
    names = {
        "copyright": font.copyright,
        "familyName": instance.familyName,
        "styleName": instance.name,
        "uniqueFontIdentifier": f"{version:.03f};{vendor};{instance.fontName}",
        "fullName": instance.fullName,
        "version": f"Version {version:.03f}",
        "psName": instance.fontName,
        "manufacturer": font.manufacturer,
        "designer": font.designer,
        "description": font.customParameters["description"],
        "vendorURL": font.manufacturerURL,
        "designerURL": font.designerURL,
        "licenseDescription": font.customParameters["license"],
        "licenseInfoURL": font.customParameters["licenseURL"],
        "sampleText": font.customParameters["sampleText"],
    }

    date = int(font.date.timestamp()) - epoch_diff
    fb = FontBuilder(font.upm, isTTF=False)
    fb.updateHead(fontRevision=version, created=date, modified=date)
    fb.setupGlyphOrder(glyphOrder)
    fb.setupCharacterMap(characterMap)
    fb.setupNameTable(names, mac=False)
    fb.setupHorizontalHeader(
        ascent=source.ascender,
        descent=source.descender,
        lineGap=source.customParameters["typoLineGap"],
    )

    privateDict = {
        "BlueValues": source.blueValues,
        "OtherBlues": source.otherBlues,
        "StemSnapH": source.horizontalStems,
        "StemSnapV": source.verticalStems,
        "StdHW": source.horizontalStems[0],
        "StdVW": source.verticalStems[0],
    }

    fontInfo = {
        "FullName": names["fullName"],
        "Notice": names["copyright"].replace("©", "\(c\)"),
        "version": f"{version:07.03f}",
        "Weight": instance.name,
    }
    fb.setupCFF(names["psName"], fontInfo, charStrings, privateDict)

    metrics = {}
    for i, (name, width) in enumerate(advanceWidths.items()):
        bounds = charStrings[name].calcBounds(None) or [0]
        metrics[name] = (width, bounds[0])
    fb.setupHorizontalMetrics(metrics)

    codePages = [
        CODEPAGE_RANGES[v] for v in font.customParameters["codePageRanges"]
    ]
    fb.setupOS2(
        version=4,
        sTypoAscender=source.ascender,
        sTypoDescender=source.descender,
        sTypoLineGap=source.customParameters["typoLineGap"],
        usWinAscent=source.ascender,
        usWinDescent=-source.descender,
        sxHeight=source.xHeight,
        sCapHeight=source.capHeight,
        achVendID=vendor,
        fsType=calcBits(font.customParameters["fsType"], 0, 16),
        fsSelection=calcFsSelection(instance),
        ulUnicodeRange1=calcBits(font.customParameters["unicodeRanges"], 0,
                                 32),
        ulCodePageRange1=calcBits(codePages, 0, 32),
    )

    ut = int(source.customParameters["underlineThickness"])
    up = int(source.customParameters["underlinePosition"])
    fb.setupPost(underlineThickness=ut, underlinePosition=up + ut // 2)

    meta = newTable("meta")
    meta.data = {"dlng": "Arab", "slng": "Arab"}
    fb.font["meta"] = meta

    fb.addOpenTypeFeatures(fea)

    return fb.font