Exemplo n.º 1
0
    def setupTable_post(self):
        """
        Make the post table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["post"] = post = newTable("post")
        font = self.ufo
        post.formatType = 3.0
        # italic angle
        italicAngle = getAttrWithFallback(font.info, "italicAngle")
        post.italicAngle = italicAngle
        # underline
        underlinePosition = getAttrWithFallback(font.info, "postscriptUnderlinePosition")
        if underlinePosition is None:
            underlinePosition = 0
        post.underlinePosition = _roundInt(underlinePosition)
        underlineThickness = getAttrWithFallback(font.info, "postscriptUnderlineThickness")
        if underlineThickness is None:
            underlineThickness = 0
        post.underlineThickness = _roundInt(underlineThickness)
        # determine if the font has a fixed width
        widths = set([glyph.width for glyph in self.allGlyphs.values()])
        post.isFixedPitch = getAttrWithFallback(font.info, "postscriptIsFixedPitch")
        # misc
        post.minMemType42 = 0
        post.maxMemType42 = 0
        post.minMemType1 = 0
        post.maxMemType1 = 0
Exemplo n.º 2
0
    def test_caret_slope(self):
        info = TestInfoObject()

        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRise"), 1)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRun"), 0)

        info.italicAngle = -12
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRise"), 1000)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRun"), 213)

        info.italicAngle = 12
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRise"), 1000)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRun"), -213)

        info.openTypeHheaCaretSlopeRise = 2048
        self.assertFalse(hasattr(info, "openTypeHheaCaretSlopeRun"))
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRise"), 2048)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRun"), -435)

        del info.openTypeHheaCaretSlopeRise
        info.openTypeHheaCaretSlopeRun = 200
        self.assertFalse(hasattr(info, "openTypeHheaCaretSlopeRise"))
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRise"), -941)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaCaretSlopeRun"), 200)
    def setupTable_post(self):
        """
        Make the post table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["post"] = post = newTable("post")
        font = self.ufo
        post.formatType = 3.0
        # italic angle
        italicAngle = getAttrWithFallback(font.info, "italicAngle")
        post.italicAngle = italicAngle
        # underline
        underlinePosition = getAttrWithFallback(font.info,
                                                "postscriptUnderlinePosition")
        post.underlinePosition = _roundInt(underlinePosition)
        underlineThickness = getAttrWithFallback(
            font.info, "postscriptUnderlineThickness")
        post.underlineThickness = _roundInt(underlineThickness)
        # determine if the font has a fixed width
        widths = set([glyph.width for glyph in self.allGlyphs.values()])
        post.isFixedPitch = getAttrWithFallback(font.info,
                                                "postscriptIsFixedPitch")
        # misc
        post.minMemType42 = 0
        post.maxMemType42 = 0
        post.minMemType1 = 0
        post.maxMemType1 = 0
Exemplo n.º 4
0
 def test_empty_info_2048(self, InfoClass):
     info = InfoClass()
     info.unitsPerEm = 2048
     assert getAttrWithFallback(info, "unitsPerEm") == 2048
     assert getAttrWithFallback(info, "ascender") == 1638
     assert getAttrWithFallback(info, "capHeight") == 1434
     assert getAttrWithFallback(info, "xHeight") == 1024
     assert getAttrWithFallback(info, "descender") == -410
Exemplo n.º 5
0
 def test_head_created(self, info):
     os.environ["SOURCE_DATE_EPOCH"] = "1514485183"
     try:
         assert (getAttrWithFallback(
             info, "openTypeHeadCreated") == "2017/12/28 18:19:43")
     finally:
         del os.environ["SOURCE_DATE_EPOCH"]
     assert getAttrWithFallback(
         info, "openTypeHeadCreated") != "2017/12/28 18:19:43"
Exemplo n.º 6
0
    def test_head_created(self):
        info = TestInfoObject()

        os.environ["SOURCE_DATE_EPOCH"] = '1514485183'
        try:
            self.assertEqual(getAttrWithFallback(info, "openTypeHeadCreated"),
                             '2017/12/28 18:19:43')
        finally:
            del os.environ["SOURCE_DATE_EPOCH"]
        self.assertNotEqual(getAttrWithFallback(info, "openTypeHeadCreated"),
                            '2017/12/28 18:19:43')
Exemplo n.º 7
0
 def get_origin_height(self, font, origin):
     if origin is self.Origin.BASELINE:
         return 0
     elif origin is self.Origin.CAP_HEIGHT:
         return getAttrWithFallback(font.info, "capHeight")
     elif origin is self.Origin.HALF_CAP_HEIGHT:
         return otRound(getAttrWithFallback(font.info, "capHeight") / 2)
     elif origin is self.Origin.X_HEIGHT:
         return getAttrWithFallback(font.info, "xHeight")
     elif origin is self.Origin.HALF_X_HEIGHT:
         return otRound(getAttrWithFallback(font.info, "xHeight") / 2)
     else:
         raise AssertionError(origin)
Exemplo n.º 8
0
    def test_redundant_metadata(self, info):
        assert getAttrWithFallback(info, "openTypeNameVersion") == "Version 0.000"

        info.versionMinor = 1
        info.versionMajor = 1
        assert getAttrWithFallback(info, "openTypeNameVersion") == "Version 1.001"

        assert (
            getAttrWithFallback(info, "openTypeNameUniqueID")
            == "1.001;NONE;FamilyName-StyleName"
        )

        assert getAttrWithFallback(info, "postscriptSlantAngle") == 0
Exemplo n.º 9
0
    def test_redundant_metadata(self):
        info = TestInfoObject()

        self.assertEqual(getAttrWithFallback(info, "openTypeNameVersion"),
                         "Version 0.000")
        info.versionMinor = 1
        info.versionMajor = 1
        self.assertEqual(getAttrWithFallback(info, "openTypeNameVersion"),
                         "Version 1.001")

        self.assertEqual(getAttrWithFallback(info, "openTypeNameUniqueID"),
                         "Version 1.001;NONE;Family Name Style Name Regular")

        self.assertEqual(getAttrWithFallback(info, "postscriptSlantAngle"), 0)
        self.assertEqual(getAttrWithFallback(info, "postscriptWeightName"),
                         "Normal")
Exemplo n.º 10
0
    def makeMissingRequiredGlyphs(self):
        """
        Add .notdef to the font if it is not present.

        **This should not be called externally.** Subclasses
        may override this method to handle the glyph creation
        in a different way if desired.
        """
        glyphs = {}
        font = self.ufo
        unitsPerEm = _roundInt(getAttrWithFallback(font.info, "unitsPerEm"))
        ascender = _roundInt(getAttrWithFallback(font.info, "ascender"))
        descender = _roundInt(getAttrWithFallback(font.info, "descender"))
        defaultWidth = _roundInt(unitsPerEm * 0.5)
        if ".notdef" not in self.ufo:
            glyphs[".notdef"] = StubGlyph(name=".notdef", width=defaultWidth, unitsPerEm=unitsPerEm, ascender=ascender, descender=descender)
        return glyphs
Exemplo n.º 11
0
 def test_with_blue_zones(self):
     info = TestInfoObject()
     info.postscriptBlueValues = [
         -13, 0, 470, 483, 534, 547, 556, 569, 654, 667, 677, 690, 738, 758
     ]
     info.postscriptOtherBlues = [-255, -245]
     postscriptBlueScale = getAttrWithFallback(info, "postscriptBlueScale")
     self.assertEqual(postscriptBlueScale, 0.0375)
Exemplo n.º 12
0
    def makeMissingRequiredGlyphs(self):
        """
        Add .notdef to the font if it is not present.

        **This should not be called externally.** Subclasses
        may override this method to handle the glyph creation
        in a different way if desired.
        """
        glyphs = {}
        font = self.ufo
        unitsPerEm = _roundInt(getAttrWithFallback(font.info, "unitsPerEm"))
        ascender = _roundInt(getAttrWithFallback(font.info, "ascender"))
        descender = _roundInt(getAttrWithFallback(font.info, "descender"))
        defaultWidth = _roundInt(unitsPerEm * 0.5)
        if ".notdef" not in self.ufo:
            glyphs[".notdef"] = StubGlyph(name=".notdef", width=defaultWidth, unitsPerEm=unitsPerEm, ascender=ascender, descender=descender)
        return glyphs
Exemplo n.º 13
0
    def set_context(self, font, glyphSet):
        ctx = super(CubicToQuadraticFilter, self).set_context(font, glyphSet)

        relativeError = self.options.conversionError or DEFAULT_MAX_ERR
        ctx.absoluteError = relativeError * getAttrWithFallback(
            font.info, "unitsPerEm")

        ctx.stats = {}

        return ctx
Exemplo n.º 14
0
    def setupTable_head(self):
        """
        Make the head table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """

        self.otf["head"] = head = newTable("head")
        font = self.ufo
        head.checkSumAdjustment = 0
        head.tableVersion = 1.0
        head.magicNumber = 0x5F0F3CF5

        # version numbers
        # limit minor version to 3 digits as recommended in OpenType spec:
        # https://www.microsoft.com/typography/otspec/recom.htm
        versionMajor = getAttrWithFallback(font.info, "versionMajor")
        versionMinor = getAttrWithFallback(font.info, "versionMinor")
        fullFontRevision = float("%d.%03d" % (versionMajor, versionMinor))
        head.fontRevision = round(fullFontRevision, 3)
        if head.fontRevision != fullFontRevision:
            print("Minor version in %s has too many digits and won't fit into "
                "the head table's fontRevision field; rounded to %s." %
                (fullFontRevision, head.fontRevision))

        # upm
        head.unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")

        # times
        head.created = dateStringToTimeValue(getAttrWithFallback(font.info, "openTypeHeadCreated")) - mac_epoch_diff
        head.modified = dateStringToTimeValue(dateStringForNow()) - mac_epoch_diff

        # bounding box
        xMin, yMin, xMax, yMax = self.fontBoundingBox
        head.xMin = xMin
        head.yMin = yMin
        head.xMax = xMax
        head.yMax = yMax

        # style mapping
        styleMapStyleName = getAttrWithFallback(font.info, "styleMapStyleName")
        macStyle = []
        if styleMapStyleName == "bold":
            macStyle = [0]
        elif styleMapStyleName == "bold italic":
            macStyle = [0, 1]
        elif styleMapStyleName == "italic":
            macStyle = [1]
        head.macStyle = intListToNum(macStyle, 0, 16)

        # misc
        head.flags = intListToNum(getAttrWithFallback(font.info, "openTypeHeadFlags"), 0, 16)
        head.lowestRecPPEM = _roundInt(getAttrWithFallback(font.info, "openTypeHeadLowestRecPPEM"))
        head.fontDirectionHint = 2
        head.indexToLocFormat = 0
        head.glyphDataFormat = 0
Exemplo n.º 15
0
    def setupTable_head(self):
        """
        Make the head table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """

        self.otf["head"] = head = newTable("head")
        font = self.ufo
        head.checkSumAdjustment = 0
        head.tableVersion = 1.0
        head.magicNumber = 0x5F0F3CF5

        # version numbers
        # limit minor version to 3 digits as recommended in OpenType spec:
        # https://www.microsoft.com/typography/otspec/recom.htm
        versionMajor = getAttrWithFallback(font.info, "versionMajor")
        versionMinor = getAttrWithFallback(font.info, "versionMinor")
        fullFontRevision = float("%d.%03d" % (versionMajor, versionMinor))
        head.fontRevision = round(fullFontRevision, 3)
        if head.fontRevision != fullFontRevision:
            print("Minor version in %s has too many digits and won't fit into "
                "the head table's fontRevision field; rounded to %s." %
                (fullFontRevision, head.fontRevision))

        # upm
        head.unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")

        # times
        head.created = dateStringToTimeValue(getAttrWithFallback(font.info, "openTypeHeadCreated")) - mac_epoch_diff
        head.modified = dateStringToTimeValue(dateStringForNow()) - mac_epoch_diff

        # bounding box
        xMin, yMin, xMax, yMax = self.fontBoundingBox
        head.xMin = xMin
        head.yMin = yMin
        head.xMax = xMax
        head.yMax = yMax

        # style mapping
        styleMapStyleName = getAttrWithFallback(font.info, "styleMapStyleName")
        macStyle = []
        if styleMapStyleName == "bold":
            macStyle = [0]
        elif styleMapStyleName == "bold italic":
            macStyle = [0, 1]
        elif styleMapStyleName == "italic":
            macStyle = [1]
        head.macStyle = intListToNum(macStyle, 0, 16)

        # misc
        head.flags = intListToNum(getAttrWithFallback(font.info, "openTypeHeadFlags"), 0, 16)
        head.lowestRecPPEM = _roundInt(getAttrWithFallback(font.info, "openTypeHeadLowestRecPPEM"))
        head.fontDirectionHint = 2
        head.indexToLocFormat = 0
        head.glyphDataFormat = 0
Exemplo n.º 16
0
 def test_empty_info(self, InfoClass):
     info = InfoClass()
     assert getAttrWithFallback(info, "familyName") == "New Font"
     assert getAttrWithFallback(info, "styleName") == "Regular"
     assert getAttrWithFallback(info, "unitsPerEm") == 1000
     assert getAttrWithFallback(info, "ascender") == 800
     assert getAttrWithFallback(info, "capHeight") == 700
     assert getAttrWithFallback(info, "xHeight") == 500
     assert getAttrWithFallback(info, "descender") == -200
Exemplo n.º 17
0
    def makeMissingRequiredGlyphs(font, glyphSet):
        """
        Add .notdef to the glyph set if it is not present.

        **This should not be called externally.** Subclasses
        may override this method to handle the glyph creation
        in a different way if desired.
        """
        if ".notdef" in glyphSet:
            return

        unitsPerEm = round(getAttrWithFallback(font.info, "unitsPerEm"))
        ascender = round(getAttrWithFallback(font.info, "ascender"))
        descender = round(getAttrWithFallback(font.info, "descender"))
        defaultWidth = round(unitsPerEm * 0.5)
        glyphSet[".notdef"] = StubGlyph(name=".notdef",
                                        width=defaultWidth,
                                        unitsPerEm=unitsPerEm,
                                        ascender=ascender,
                                        descender=descender)
Exemplo n.º 18
0
    def test_redundant_metadata(self):
        info = TestInfoObject()

        self.assertEqual(
            getAttrWithFallback(info, "openTypeNameVersion"),
            "Version 0.000")
        info.versionMinor = 1
        info.versionMajor = 1
        self.assertEqual(
            getAttrWithFallback(info, "openTypeNameVersion"),
            "Version 1.001")

        self.assertEqual(
            getAttrWithFallback(info, "openTypeNameUniqueID"),
            "Version 1.001;NONE;Family Name Style Name Regular")

        self.assertEqual(getAttrWithFallback(info, "postscriptSlantAngle"), 0)
        self.assertEqual(
            getAttrWithFallback(info, "postscriptWeightName"),
            "Normal")
Exemplo n.º 19
0
    def test_caret_slope(self, info):
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRise") == 1
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRun") == 0

        info.italicAngle = -12
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRise") == 1000
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRun") == 213

        info.italicAngle = 12
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRise") == 1000
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRun") == -213

        info.openTypeHheaCaretSlopeRise = 2048
        assert info.openTypeHheaCaretSlopeRun is None
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRise") == 2048
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRun") == -435

        info.openTypeHheaCaretSlopeRise = None
        info.openTypeHheaCaretSlopeRun = 200
        assert info.openTypeHheaCaretSlopeRise is None
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRise") == -941
        assert getAttrWithFallback(info, "openTypeHheaCaretSlopeRun") == 200
Exemplo n.º 20
0
    def test_vertical_metrics(self, info):
        assert getAttrWithFallback(info, "openTypeHheaAscender") == 950
        assert getAttrWithFallback(info, "openTypeHheaDescender") == -250

        assert getAttrWithFallback(info, "openTypeOS2TypoAscender") == 650
        assert getAttrWithFallback(info, "openTypeOS2TypoDescender") == -250
        assert getAttrWithFallback(info, "openTypeOS2WinAscent") == 950
        assert getAttrWithFallback(info, "openTypeOS2WinDescent") == 250
Exemplo n.º 21
0
    def setupTable_hhea(self):
        """
        Make the hhea table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["hhea"] = hhea = newTable("hhea")
        font = self.ufo
        hhea.tableVersion = 0x00010000
        # vertical metrics
        hhea.ascent = _roundInt(getAttrWithFallback(font.info, "openTypeHheaAscender"))
        hhea.descent = _roundInt(getAttrWithFallback(font.info, "openTypeHheaDescender"))
        hhea.lineGap = _roundInt(getAttrWithFallback(font.info, "openTypeHheaLineGap"))
        # horizontal metrics
        widths = []
        lefts = []
        rights = []
        extents = []
        for glyph in self.allGlyphs.values():
            left = glyph.leftMargin
            right = glyph.rightMargin
            if left is None:
                left = 0
            if right is None:
                right = 0
            widths.append(glyph.width)
            lefts.append(left)
            rights.append(right)
            # robofab
            if hasattr(glyph, "box"):
                bounds = glyph.box
            # others
            else:
                bounds = glyph.bounds
            if bounds is not None:
                xMin, yMin, xMax, yMax = bounds
            else:
                xMin = 0
                xMax = 0
            extent = left + (xMax - xMin) # equation from spec for calculating xMaxExtent: Max(lsb + (xMax - xMin))
            extents.append(extent)
        hhea.advanceWidthMax = _roundInt(max(widths))
        hhea.minLeftSideBearing = _roundInt(min(lefts))
        hhea.minRightSideBearing = _roundInt(min(rights))
        hhea.xMaxExtent = _roundInt(max(extents))
        # misc
        hhea.caretSlopeRise = getAttrWithFallback(font.info, "openTypeHheaCaretSlopeRise")
        hhea.caretSlopeRun = getAttrWithFallback(font.info, "openTypeHheaCaretSlopeRun")
        hhea.caretOffset = _roundInt(getAttrWithFallback(font.info, "openTypeHheaCaretOffset"))
        hhea.reserved0 = 0
        hhea.reserved1 = 0
        hhea.reserved2 = 0
        hhea.reserved3 = 0
        hhea.metricDataFormat = 0
        # glyph count
        hhea.numberOfHMetrics = len(self.allGlyphs)
Exemplo n.º 22
0
    def setupTable_hhea(self):
        """
        Make the hhea table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["hhea"] = hhea = newTable("hhea")
        font = self.ufo
        hhea.tableVersion = 1.0
        # vertical metrics
        hhea.ascent = _roundInt(getAttrWithFallback(font.info, "openTypeHheaAscender"))
        hhea.descent = _roundInt(getAttrWithFallback(font.info, "openTypeHheaDescender"))
        hhea.lineGap = _roundInt(getAttrWithFallback(font.info, "openTypeHheaLineGap"))
        # horizontal metrics
        widths = []
        lefts = []
        rights = []
        extents = []
        for glyph in self.allGlyphs.values():
            left = glyph.leftMargin
            right = glyph.rightMargin
            if left is None:
                left = 0
            if right is None:
                right = 0
            widths.append(glyph.width)
            lefts.append(left)
            rights.append(right)
            # robofab
            if hasattr(glyph, "box"):
                bounds = glyph.box
            # others
            else:
                bounds = glyph.bounds
            if bounds is not None:
                xMin, yMin, xMax, yMax = bounds
            else:
                xMin = 0
                xMax = 0
            extent = left + (xMax - xMin) # equation from spec for calculating xMaxExtent: Max(lsb + (xMax - xMin))
            extents.append(extent)
        hhea.advanceWidthMax = _roundInt(max(widths))
        hhea.minLeftSideBearing = _roundInt(min(lefts))
        hhea.minRightSideBearing = _roundInt(min(rights))
        hhea.xMaxExtent = _roundInt(max(extents))
        # misc
        hhea.caretSlopeRise = getAttrWithFallback(font.info, "openTypeHheaCaretSlopeRise")
        hhea.caretSlopeRun = getAttrWithFallback(font.info, "openTypeHheaCaretSlopeRun")
        hhea.caretOffset = _roundInt(getAttrWithFallback(font.info, "openTypeHheaCaretOffset"))
        hhea.reserved0 = 0
        hhea.reserved1 = 0
        hhea.reserved2 = 0
        hhea.reserved3 = 0
        hhea.metricDataFormat = 0
        # glyph count
        hhea.numberOfHMetrics = len(self.allGlyphs)
Exemplo n.º 23
0
 def __init__(self,
              font,
              glyphOrder=None,
              convertCubics=True,
              cubicConversionError=None):
     super(OutlineTTFCompiler, self).__init__(font, glyphOrder)
     if convertCubics:
         unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")
         if cubicConversionError is None:
             from cu2qu.ufo import DEFAULT_MAX_ERR
             cubicConversionError = DEFAULT_MAX_ERR
         cubicConversionError *= unitsPerEm
     self.convertCubics = convertCubics
     self.cubicConversionError = cubicConversionError
Exemplo n.º 24
0
    def __init__(
        self,
        ufos,
        inplace=False,
        flattenComponents=False,
        conversionError=None,
        reverseDirection=True,
        rememberCurveType=True,
        layerNames=None,
        skipExportGlyphs=None,
        filters=None,
    ):
        from cu2qu.ufo import DEFAULT_MAX_ERR

        self.ufos = ufos
        self.inplace = inplace
        self.flattenComponents = flattenComponents

        if layerNames is None:
            layerNames = [None] * len(ufos)
        assert len(ufos) == len(layerNames)
        self.layerNames = layerNames

        self.glyphSets = [
            _GlyphSet.from_layer(
                ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs
            )
            for ufo, layerName in zip(ufos, layerNames)
        ]
        self._conversionErrors = [
            (conversionError or DEFAULT_MAX_ERR)
            * getAttrWithFallback(ufo.info, "unitsPerEm")
            for ufo in ufos
        ]
        self._reverseDirection = reverseDirection
        self._rememberCurveType = rememberCurveType

        self.preFilters, self.postFilters = [], []
        if filters is None:
            for ufo in ufos:
                pre, post = loadFilters(ufo)
                self.preFilters.append(pre)
                self.postFilters.append(post)
        else:
            pre = [f for f in filters if f.pre]
            post = [f for f in filters if not f.pre]
            for _ in ufos:
                self.preFilters.append(pre)
                self.postFilters.append(post)
Exemplo n.º 25
0
    def setupTable_vhea(self):
        """
        Make the vhea table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["vhea"] = vhea = newTable("vhea")
        font = self.ufo
        head = self.otf["head"]
        # vhea.tableVersion = 0x00011000
        # see https://github.com/behdad/fonttools/issues/540
        vhea.tableVersion = 1.0625
        # horizontal metrics
        vhea.ascent = _roundInt(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoAscender"))
        vhea.descent = _roundInt(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoDescender"))
        vhea.lineGap = _roundInt(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoLineGap"))
        # vertical metrics
        heights = []
        tops = []
        bottoms = []
        for glyph in self.allGlyphs.values():
            top = glyph.topMargin
            bottom = glyph.rightMargin
            if top is None:
                top = 0
            if bottom is None:
                bottom = 0
            heights.append(glyph.height)
            tops.append(top)
            bottoms.append(bottom)
        vhea.advanceHeightMax = _roundInt(max(heights))
        vhea.minTopSideBearing = _roundInt(max(tops))
        vhea.minBottomSideBearing = _roundInt(max(bottoms))
        vhea.yMaxExtent = _roundInt(vhea.minTopSideBearing -
                                    (head.yMax - head.yMin))
        # misc
        vhea.caretSlopeRise = getAttrWithFallback(
            font.info, "openTypeVheaCaretSlopeRise")
        vhea.caretSlopeRun = getAttrWithFallback(font.info,
                                                 "openTypeVheaCaretSlopeRun")
        vhea.caretOffset = getAttrWithFallback(font.info,
                                               "openTypeVheaCaretOffset")
        vhea.reserved0 = 0
        vhea.reserved1 = 0
        vhea.reserved2 = 0
        vhea.reserved3 = 0
        vhea.reserved4 = 0
        vhea.metricDataFormat = 0
        # glyph count
        vhea.numberOfVMetrics = len(self.allGlyphs)
Exemplo n.º 26
0
    def setupTable_hhea(self):
        """
        Make the hhea table. This assumes that the hmtx table was made first.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["hhea"] = hhea = newTable("hhea")
        hmtx = self.otf["hmtx"]
        font = self.ufo
        hhea.tableVersion = 0x00010000
        # vertical metrics
        hhea.ascent = round(
            getAttrWithFallback(font.info, "openTypeHheaAscender"))
        hhea.descent = round(
            getAttrWithFallback(font.info, "openTypeHheaDescender"))
        hhea.lineGap = round(
            getAttrWithFallback(font.info, "openTypeHheaLineGap"))
        # horizontal metrics
        widths = []
        lefts = []
        rights = []
        extents = []
        for glyphName in self.allGlyphs:
            width, left = hmtx[glyphName]
            widths.append(width)
            bounds = self.glyphBoundingBoxes[glyphName]
            if bounds is None:
                continue
            right = width - left - (bounds.xMax - bounds.xMin)
            lefts.append(left)
            rights.append(right)
            # equation from the hhea spec for calculating xMaxExtent:
            #   Max(lsb + (xMax - xMin))
            extent = left + (bounds.xMax - bounds.xMin)
            extents.append(extent)
        hhea.advanceWidthMax = max(widths)
        hhea.minLeftSideBearing = min(lefts)
        hhea.minRightSideBearing = min(rights)
        hhea.xMaxExtent = max(extents)
        # misc
        hhea.caretSlopeRise = getAttrWithFallback(
            font.info, "openTypeHheaCaretSlopeRise")
        hhea.caretSlopeRun = getAttrWithFallback(font.info,
                                                 "openTypeHheaCaretSlopeRun")
        hhea.caretOffset = round(
            getAttrWithFallback(font.info, "openTypeHheaCaretOffset"))
        hhea.reserved0 = 0
        hhea.reserved1 = 0
        hhea.reserved2 = 0
        hhea.reserved3 = 0
        hhea.metricDataFormat = 0
        # glyph count
        hhea.numberOfHMetrics = len(self.allGlyphs)
Exemplo n.º 27
0
    def setupTable_vhea(self):
        """
        Make the vhea table. This assumes that the head and vmtx tables were
        made first.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["vhea"] = vhea = newTable("vhea")
        font = self.ufo
        head = self.otf["head"]
        vmtx = self.otf["vmtx"]
        vhea.tableVersion = 0x00011000
        # horizontal metrics
        vhea.ascent = round(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoAscender"))
        vhea.descent = round(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoDescender"))
        vhea.lineGap = round(
            getAttrWithFallback(font.info, "openTypeVheaVertTypoLineGap"))
        # vertical metrics
        heights = []
        tops = []
        bottoms = []
        for glyphName in self.allGlyphs:
            height, top = vmtx[glyphName]
            heights.append(height)
            bounds = self.glyphBoundingBoxes[glyphName]
            if bounds is None:
                continue
            bottom = height - top - (bounds.yMax - bounds.yMin)
            tops.append(top)
            bottoms.append(bottom)
        vhea.advanceHeightMax = max(heights)
        vhea.minTopSideBearing = max(tops)
        vhea.minBottomSideBearing = max(bottoms)
        vhea.yMaxExtent = vhea.minTopSideBearing - (head.yMax - head.yMin)
        # misc
        vhea.caretSlopeRise = getAttrWithFallback(
            font.info, "openTypeVheaCaretSlopeRise")
        vhea.caretSlopeRun = getAttrWithFallback(font.info,
                                                 "openTypeVheaCaretSlopeRun")
        vhea.caretOffset = getAttrWithFallback(font.info,
                                               "openTypeVheaCaretOffset")
        vhea.reserved0 = 0
        vhea.reserved1 = 0
        vhea.reserved2 = 0
        vhea.reserved3 = 0
        vhea.reserved4 = 0
        vhea.metricDataFormat = 0
        # glyph count
        vhea.numberOfVMetrics = len(self.allGlyphs)
Exemplo n.º 28
0
    def getCharStringForGlyph(self, glyph, private, globalSubrs):
        """
        Get a Type2CharString for the *glyph*

        **This should not be called externally.** Subclasses
        may override this method to handle the charstring creation
        in a different way if desired.
        """
        width = glyph.width
        # subtract the nominal width
        postscriptNominalWidthX = getAttrWithFallback(self.ufo.info, "postscriptNominalWidthX")
        if postscriptNominalWidthX:
            width = width - postscriptNominalWidthX
        # round
        width = _roundInt(width)
        pen = T2CharStringPen(width, self.allGlyphs)
        glyph.draw(pen)
        charString = pen.getCharString(private, globalSubrs)
        return charString
Exemplo n.º 29
0
    def getCharStringForGlyph(self, glyph, private, globalSubrs):
        """
        Get a Type2CharString for the *glyph*

        **This should not be called externally.** Subclasses
        may override this method to handle the charstring creation
        in a different way if desired.
        """
        width = glyph.width
        # subtract the nominal width
        postscriptNominalWidthX = getAttrWithFallback(self.ufo.info, "postscriptNominalWidthX")
        if postscriptNominalWidthX:
            width = width - postscriptNominalWidthX
        # round
        width = _roundInt(width)
        pen = T2CharStringPen(width, self.allGlyphs)
        glyph.draw(pen)
        charString = pen.getCharString(private, globalSubrs)
        return charString
Exemplo n.º 30
0
 def test_with_blue_zones(self, info):
     info.postscriptBlueValues = [
         -13,
         0,
         470,
         483,
         534,
         547,
         556,
         569,
         654,
         667,
         677,
         690,
         738,
         758,
     ]
     info.postscriptOtherBlues = [-255, -245]
     postscriptBlueScale = getAttrWithFallback(info, "postscriptBlueScale")
     assert postscriptBlueScale == 0.0375
Exemplo n.º 31
0
    def setupTable_vhea(self):
        """
        Make the vhea table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["vhea"] = vhea = newTable("vhea")
        font = self.ufo
        head = self.otf["head"]
        # vhea.tableVersion = 0x00011000
        # see https://github.com/behdad/fonttools/issues/540
        vhea.tableVersion = 1.0625
        # horizontal metrics
        vhea.ascent = _roundInt(getAttrWithFallback(font.info, "openTypeVheaVertTypoAscender"))
        vhea.descent = _roundInt(getAttrWithFallback(font.info, "openTypeVheaVertTypoDescender"))
        vhea.lineGap = _roundInt(getAttrWithFallback(font.info, "openTypeVheaVertTypoLineGap"))
        # vertical metrics
        heights = []
        tops = []
        bottoms = []
        for glyph in self.allGlyphs.values():
            top = glyph.topMargin
            bottom = glyph.rightMargin
            if top is None:
                top = 0
            if bottom is None:
                bottom = 0
            heights.append(glyph.height)
            tops.append(top)
            bottoms.append(bottom)
        vhea.advanceHeightMax = _roundInt(max(heights))
        vhea.minTopSideBearing = _roundInt(max(tops))
        vhea.minBottomSideBearing = _roundInt(max(bottoms))
        vhea.yMaxExtent = _roundInt(vhea.minTopSideBearing - (head.yMax - head.yMin))
        # misc
        vhea.caretSlopeRise = getAttrWithFallback(font.info, "openTypeVheaCaretSlopeRise")
        vhea.caretSlopeRun = getAttrWithFallback(font.info, "openTypeVheaCaretSlopeRun")
        vhea.caretOffset = getAttrWithFallback(font.info, "openTypeVheaCaretOffset")
        vhea.reserved0 = 0
        vhea.reserved1 = 0
        vhea.reserved2 = 0
        vhea.reserved3 = 0
        vhea.reserved4 = 0
        vhea.metricDataFormat = 0
        # glyph count
        vhea.numberOfVMetrics = len(self.allGlyphs)
Exemplo n.º 32
0
    def test_vertical_metrics(self):
        info = TestInfoObject()

        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaAscender"), 950)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeHheaDescender"), -250)

        self.assertEqual(
            getAttrWithFallback(info, "openTypeOS2TypoAscender"), 950)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeOS2TypoDescender"), -250)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeOS2WinAscent"), 950)
        self.assertEqual(
            getAttrWithFallback(info, "openTypeOS2WinDescent"), 250)
Exemplo n.º 33
0
    def test_vertical_metrics(self):
        info = TestInfoObject()

        self.assertEqual(getAttrWithFallback(info, "openTypeHheaAscender"),
                         950)
        self.assertEqual(getAttrWithFallback(info, "openTypeHheaDescender"),
                         -250)

        self.assertEqual(getAttrWithFallback(info, "openTypeOS2TypoAscender"),
                         650)
        self.assertEqual(getAttrWithFallback(info, "openTypeOS2TypoDescender"),
                         -250)
        self.assertEqual(getAttrWithFallback(info, "openTypeOS2WinAscent"),
                         950)
        self.assertEqual(getAttrWithFallback(info, "openTypeOS2WinDescent"),
                         250)
Exemplo n.º 34
0
    def test_family_and_style_names(self):
        info = TestInfoObject()

        self.assertEqual(getAttrWithFallback(info, "familyName"),
                         "Family Name")
        self.assertEqual(getAttrWithFallback(info, "styleName"), "Style Name")

        self.assertEqual(getAttrWithFallback(info, "styleMapFamilyName"),
                         "Family Name Style Name")
        info.styleMapFamilyName = "Style Map Family Name"
        self.assertEqual(getAttrWithFallback(info, "styleMapFamilyName"),
                         "Style Map Family Name")

        self.assertEqual(
            getAttrWithFallback(info, "openTypeNamePreferredFamilyName"),
            "Family Name")
        self.assertEqual(
            getAttrWithFallback(info, "openTypeNamePreferredSubfamilyName"),
            "Style Name")
        self.assertEqual(
            getAttrWithFallback(info, "openTypeNameCompatibleFullName"),
            "Style Map Family Name")
Exemplo n.º 35
0
    def test_family_and_style_names(self):
        info = TestInfoObject()

        self.assertEqual(getAttrWithFallback(info, "familyName"), "Family Name")
        self.assertEqual(getAttrWithFallback(info, "styleName"), "Style Name")

        self.assertEqual(
            getAttrWithFallback(info, "styleMapFamilyName"),
            "Family Name Style Name")
        info.styleMapFamilyName = "Style Map Family Name"
        self.assertEqual(
            getAttrWithFallback(info, "styleMapFamilyName"),
            "Style Map Family Name")

        self.assertEqual(
            getAttrWithFallback(info, "openTypeNamePreferredFamilyName"),
            "Family Name")
        self.assertEqual(
            getAttrWithFallback(info, "openTypeNamePreferredSubfamilyName"),
            "Style Name")
        self.assertEqual(
            getAttrWithFallback(info, "openTypeNameCompatibleFullName"),
            "Style Map Family Name")
Exemplo n.º 36
0
    def setupTable_name(self):
        """
        Make the name table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """

        font = self.ufo

        familyName = getAttrWithFallback(font.info, "styleMapFamilyName")
        styleName = getAttrWithFallback(font.info, "styleMapStyleName").title()

        # If name ID 2 is "Regular", it can be omitted from name ID 4
        fullName = familyName
        if styleName != "Regular":
            fullName += " %s" % styleName

        nameVals = {
            "0": getAttrWithFallback(font.info, "copyright"),
            "1": familyName,
            "2": styleName,
            "3": getAttrWithFallback(font.info, "openTypeNameUniqueID"),
            "4": fullName,
            "5": getAttrWithFallback(font.info, "openTypeNameVersion"),
            "6": getAttrWithFallback(font.info, "postscriptFontName"),
            "7": getAttrWithFallback(font.info, "trademark"),
            "8": getAttrWithFallback(font.info, "openTypeNameManufacturer"),
            "9": getAttrWithFallback(font.info, "openTypeNameDesigner"),
            "10": getAttrWithFallback(font.info, "openTypeNameDescription"),
            "11": getAttrWithFallback(font.info,
                                      "openTypeNameManufacturerURL"),
            "12": getAttrWithFallback(font.info, "openTypeNameDesignerURL"),
            "13": getAttrWithFallback(font.info, "openTypeNameLicense"),
            "14": getAttrWithFallback(font.info, "openTypeNameLicenseURL")
        }

        # don't add typographic names if they are the same as the legacy ones
        typographicFamilyName = getAttrWithFallback(
            font.info, "openTypeNamePreferredFamilyName")
        typographicSubfamilyName = getAttrWithFallback(
            font.info, "openTypeNamePreferredSubfamilyName")
        if nameVals["1"] != typographicFamilyName:
            nameVals["16"] = typographicFamilyName
        if nameVals["2"] != typographicSubfamilyName:
            nameVals["17"] = typographicSubfamilyName

        self.otf["name"] = name = newTable("name")
        name.names = []
        for nameId in sorted(nameVals.keys()):
            nameVal = nameVals[nameId]
            if not nameVal:
                continue
            nameIdVal = int(nameId)
            if nameIdVal == 6:
                # postscript font name
                nameVal = normalizeStringForPostscript(nameVal)
            rec = NameRecord()
            rec.platformID = 3
            rec.platEncID = 10 if _isNonBMP(nameVal) else 1
            rec.langID = 0x409
            rec.nameID = nameIdVal
            rec.string = nameVal.encode(rec.getEncoding())
            name.names.append(rec)
Exemplo n.º 37
0
    def setupTable_name(self):
        """
        Make the name table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """

        font = self.ufo

        familyName = getAttrWithFallback(font.info, "styleMapFamilyName")
        styleName = getAttrWithFallback(font.info, "styleMapStyleName").title()

        # If name ID 2 is "Regular", it can be omitted from name ID 4
        fullName = familyName
        if styleName != "Regular":
            fullName += " %s" % styleName

        nameVals = {
            "0": getAttrWithFallback(font.info, "copyright"),
            "1": familyName,
            "2": styleName,
            "3": getAttrWithFallback(font.info, "openTypeNameUniqueID"),
            "4": fullName,
            "5": getAttrWithFallback(font.info, "openTypeNameVersion"),
            "6": getAttrWithFallback(font.info, "postscriptFontName"),
            "7": getAttrWithFallback(font.info, "trademark"),
            "8": getAttrWithFallback(font.info, "openTypeNameManufacturer"),
            "9": getAttrWithFallback(font.info, "openTypeNameDesigner"),
            "11": getAttrWithFallback(font.info, "openTypeNameManufacturerURL"),
            "12": getAttrWithFallback(font.info, "openTypeNameDesignerURL"),
            "13": getAttrWithFallback(font.info, "openTypeNameLicense"),
            "14": getAttrWithFallback(font.info, "openTypeNameLicenseURL")}

        # don't add typographic names if they are the same as the legacy ones
        typographicFamilyName = getAttrWithFallback(font.info,
            "openTypeNamePreferredFamilyName")
        typographicSubfamilyName = getAttrWithFallback(font.info,
            "openTypeNamePreferredSubfamilyName")
        if nameVals["1"] != typographicFamilyName:
            nameVals["16"] = typographicFamilyName
        if nameVals["2"] != typographicSubfamilyName:
            nameVals["17"] = typographicSubfamilyName

        self.otf["name"] = name = newTable("name")
        name.names = []
        for nameId in sorted(nameVals.keys()):
            nameVal = nameVals[nameId]
            if not nameVal:
                continue
            nameIdVal = int(nameId)
            if nameIdVal == 6:
                # postscript font name
                nameVal = normalizeStringForPostscript(nameVal)
            rec = NameRecord()
            rec.platformID = 3
            rec.platEncID = 10 if _isNonBMP(nameVal) else 1
            rec.langID = 0x409
            rec.nameID = nameIdVal
            rec.string = nameVal.encode(rec.getEncoding())
            name.names.append(rec)
Exemplo n.º 38
0
 def test_without_blue_zones(self):
     info = TestInfoObject()
     postscriptBlueScale = getAttrWithFallback(info, "postscriptBlueScale")
     self.assertEqual(postscriptBlueScale, 0.039625)
Exemplo n.º 39
0
    def setupTable_OS2(self):
        """
        Make the OS/2 table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["OS/2"] = os2 = newTable("OS/2")
        font = self.ufo
        os2.version = 0x0004
        # average glyph width
        widths = [glyph.width for glyph in self.allGlyphs.values() if glyph.width > 0]
        os2.xAvgCharWidth = _roundInt(sum(widths) / len(widths))
        # weight and width classes
        os2.usWeightClass = getAttrWithFallback(font.info, "openTypeOS2WeightClass")
        os2.usWidthClass = getAttrWithFallback(font.info, "openTypeOS2WidthClass")
        # embedding
        os2.fsType = intListToNum(getAttrWithFallback(font.info, "openTypeOS2Type"), 0, 16)
        # subscript
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXSize")
        if v is None:
            v = 0
        os2.ySubscriptXSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYSize")
        if v is None:
            v = 0
        os2.ySubscriptYSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXOffset")
        if v is None:
            v = 0
        os2.ySubscriptXOffset = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYOffset")
        if v is None:
            v = 0
        os2.ySubscriptYOffset = _roundInt(v)
        # superscript
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXSize")
        if v is None:
            v = 0
        os2.ySuperscriptXSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYSize")
        if v is None:
            v = 0
        os2.ySuperscriptYSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXOffset")
        if v is None:
            v = 0
        os2.ySuperscriptXOffset = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYOffset")
        if v is None:
            v = 0
        os2.ySuperscriptYOffset = _roundInt(v)
        # strikeout
        v = getAttrWithFallback(font.info, "openTypeOS2StrikeoutSize")
        if v is None:
            v = 0
        os2.yStrikeoutSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2StrikeoutPosition")
        if v is None:
            v = 0
        os2.yStrikeoutPosition = _roundInt(v)
        # family class
        ibmFontClass, ibmFontSubclass = getAttrWithFallback(
            font.info, "openTypeOS2FamilyClass")
        os2.sFamilyClass = (ibmFontClass << 8) + ibmFontSubclass
        # panose
        data = getAttrWithFallback(font.info, "openTypeOS2Panose")
        panose = Panose()
        panose.bFamilyType = data[0]
        panose.bSerifStyle = data[1]
        panose.bWeight = data[2]
        panose.bProportion = data[3]
        panose.bContrast = data[4]
        panose.bStrokeVariation = data[5]
        panose.bArmStyle = data[6]
        panose.bLetterForm = data[7]
        panose.bMidline = data[8]
        panose.bXHeight = data[9]
        os2.panose = panose
        # Unicode ranges
        uniRanges = getAttrWithFallback(font.info, "openTypeOS2UnicodeRanges")
        os2.ulUnicodeRange1 = intListToNum(uniRanges, 0, 32)
        os2.ulUnicodeRange2 = intListToNum(uniRanges, 32, 32)
        os2.ulUnicodeRange3 = intListToNum(uniRanges, 64, 32)
        os2.ulUnicodeRange4 = intListToNum(uniRanges, 96, 32)
        # codepage ranges
        codepageRanges = getAttrWithFallback(font.info, "openTypeOS2CodePageRanges")
        os2.ulCodePageRange1 = intListToNum(codepageRanges, 0, 32)
        os2.ulCodePageRange2 = intListToNum(codepageRanges, 32, 32)
        # vendor id
        os2.achVendID = tounicode(
            getAttrWithFallback(font.info, "openTypeOS2VendorID"),
            encoding="ascii", errors="ignore")
        # vertical metrics
        os2.sxHeight = _roundInt(getAttrWithFallback(font.info, "xHeight"))
        os2.sCapHeight = _roundInt(getAttrWithFallback(font.info, "capHeight"))
        os2.sTypoAscender = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoAscender"))
        os2.sTypoDescender = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoDescender"))
        os2.sTypoLineGap = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoLineGap"))
        os2.usWinAscent = _roundInt(getAttrWithFallback(font.info, "openTypeOS2WinAscent"))
        os2.usWinDescent = _roundInt(getAttrWithFallback(font.info, "openTypeOS2WinDescent"))
        # style mapping
        selection = list(getAttrWithFallback(font.info, "openTypeOS2Selection"))
        styleMapStyleName = getAttrWithFallback(font.info, "styleMapStyleName")
        if styleMapStyleName == "regular":
            selection.append(6)
        elif styleMapStyleName == "bold":
            selection.append(5)
        elif styleMapStyleName == "italic":
            selection.append(0)
        elif styleMapStyleName == "bold italic":
            selection += [0, 5]
        os2.fsSelection = intListToNum(selection, 0, 16)
        # characetr indexes
        unicodes = [i for i in self.unicodeToGlyphNameMapping.keys() if i is not None]
        if unicodes:
            minIndex = min(unicodes)
            maxIndex = max(unicodes)
        else:
            # the font may have *no* unicode values
            # (it really happens!) so there needs
            # to be a fallback. use space for this.
            minIndex = 0x0020
            maxIndex = 0x0020
        if maxIndex > 0xFFFF:
            # the spec says that 0xFFFF should be used
            # as the max if the max exceeds 0xFFFF
            maxIndex = 0xFFFF
        os2.fsFirstCharIndex = minIndex
        os2.fsLastCharIndex = maxIndex
        os2.usBreakChar = 32
        os2.usDefaultChar = 0
        # maximum contextual lookup length
        os2.usMaxContex = 0
Exemplo n.º 40
0
    def setupTable_name(self):
        """
        Make the name table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """

        font = self.ufo
        self.otf["name"] = name = newTable("name")
        name.names = []

        # Set name records from font.info.openTypeNameRecords
        for nameRecord in getAttrWithFallback(
                font.info, "openTypeNameRecords"):
            nameId = nameRecord["nameID"]
            platformId = nameRecord["platformID"]
            platEncId = nameRecord["encodingID"]
            langId = nameRecord["languageID"]
            # on Python 2, plistLib (used by ufoLib) returns unicode strings
            # only when plist data contain non-ascii characters, and returns
            # ascii-encoded bytes when it can. On the other hand, fontTools's
            # name table `setName` method wants unicode strings, so we must
            # decode them first
            nameVal = tounicode(nameRecord["string"], encoding='ascii')
            name.setName(nameVal, nameId, platformId, platEncId, langId)

        # Build name records
        familyName = getAttrWithFallback(font.info, "styleMapFamilyName")
        styleName = getAttrWithFallback(font.info, "styleMapStyleName").title()

        # If name ID 2 is "Regular", it can be omitted from name ID 4
        fullName = familyName
        if styleName != "Regular":
            fullName += " %s" % styleName

        nameVals = {
            0: getAttrWithFallback(font.info, "copyright"),
            1: familyName,
            2: styleName,
            3: getAttrWithFallback(font.info, "openTypeNameUniqueID"),
            4: fullName,
            5: getAttrWithFallback(font.info, "openTypeNameVersion"),
            6: getAttrWithFallback(font.info, "postscriptFontName"),
            7: getAttrWithFallback(font.info, "trademark"),
            8: getAttrWithFallback(font.info, "openTypeNameManufacturer"),
            9: getAttrWithFallback(font.info, "openTypeNameDesigner"),
            10: getAttrWithFallback(font.info, "openTypeNameDescription"),
            11: getAttrWithFallback(font.info, "openTypeNameManufacturerURL"),
            12: getAttrWithFallback(font.info, "openTypeNameDesignerURL"),
            13: getAttrWithFallback(font.info, "openTypeNameLicense"),
            14: getAttrWithFallback(font.info, "openTypeNameLicenseURL"),
            16: getAttrWithFallback(
                font.info, "openTypeNamePreferredFamilyName"),
            17: getAttrWithFallback(
                font.info, "openTypeNamePreferredSubfamilyName"),
        }

        # don't add typographic names if they are the same as the legacy ones
        if nameVals[1] == nameVals[16]:
            del nameVals[16]
        if nameVals[2] == nameVals[17]:
            del nameVals[17]
        # postscript font name
        if nameVals[6]:
            nameVals[6] = normalizeStringForPostscript(nameVals[6])

        for nameId in sorted(nameVals.keys()):
            nameVal = nameVals[nameId]
            if not nameVal:
                continue
            nameVal = tounicode(nameVal, encoding='ascii')
            platformId = 3
            platEncId = 10 if _isNonBMP(nameVal) else 1
            langId = 0x409
            # Set built name record if not set yet
            if name.getName(nameId, platformId, platEncId, langId):
                continue
            name.setName(nameVal, nameId, platformId, platEncId, langId)
Exemplo n.º 41
0
    def setupTable_CFF(self):
        """Make the CFF table."""

        self.otf["CFF "] = cff = newTable("CFF ")
        cff = cff.cff
        # set up the basics
        cff.major = 1
        cff.minor = 0
        cff.hdrSize = 4
        cff.offSize = 4
        cff.fontNames = []
        strings = IndexedStrings()
        cff.strings = strings
        private = PrivateDict(strings=strings)
        private.rawDict.update(private.defaults)
        globalSubrs = GlobalSubrsIndex(private=private)
        topDict = TopDict(GlobalSubrs=globalSubrs, strings=strings)
        topDict.Private = private
        charStrings = topDict.CharStrings = CharStrings(
            file=None,
            charset=None,
            globalSubrs=globalSubrs,
            private=private,
            fdSelect=None,
            fdArray=None)
        charStrings.charStringsAreIndexed = True
        topDict.charset = []
        charStringsIndex = charStrings.charStringsIndex = SubrsIndex(
            private=private, globalSubrs=globalSubrs)
        cff.topDictIndex = topDictIndex = TopDictIndex()
        topDictIndex.append(topDict)
        topDictIndex.strings = strings
        cff.GlobalSubrs = globalSubrs
        # populate naming data
        info = self.ufo.info
        psName = getAttrWithFallback(info, "postscriptFontName")
        cff.fontNames.append(psName)
        topDict = cff.topDictIndex[0]
        topDict.version = "%d.%d" % (getAttrWithFallback(
            info, "versionMajor"), getAttrWithFallback(info, "versionMinor"))
        trademark = getAttrWithFallback(info, "trademark")
        if trademark:
            trademark = normalizeStringForPostscript(
                trademark.replace("\u00A9", "Copyright"))
        if trademark != self.ufo.info.trademark:
            self.log.append(
                "[Warning] The trademark was normalized for storage in the CFF table and consequently some characters were dropped: '%s'"
                % trademark)
        if trademark is None:
            trademark = ""
        topDict.Notice = trademark
        copyright = getAttrWithFallback(info, "copyright")
        if copyright:
            copyright = normalizeStringForPostscript(
                copyright.replace("\u00A9", "Copyright"))
        if copyright != self.ufo.info.copyright:
            self.log.append(
                "[Warning] The copyright was normalized for storage in the CFF table and consequently some characters were dropped: '%s'"
                % copyright)
        if copyright is None:
            copyright = ""
        topDict.Copyright = copyright
        topDict.FullName = getAttrWithFallback(info, "postscriptFullName")
        topDict.FamilyName = getAttrWithFallback(
            info, "openTypeNamePreferredFamilyName")
        topDict.Weight = getAttrWithFallback(info, "postscriptWeightName")
        topDict.FontName = psName
        # populate various numbers
        topDict.isFixedPitch = getAttrWithFallback(info,
                                                   "postscriptIsFixedPitch")
        topDict.ItalicAngle = getAttrWithFallback(info, "italicAngle")
        underlinePosition = getAttrWithFallback(info,
                                                "postscriptUnderlinePosition")
        topDict.UnderlinePosition = _roundInt(underlinePosition)
        underlineThickness = getAttrWithFallback(
            info, "postscriptUnderlineThickness")
        topDict.UnderlineThickness = _roundInt(underlineThickness)
        # populate font matrix
        unitsPerEm = _roundInt(getAttrWithFallback(info, "unitsPerEm"))
        topDict.FontMatrix = [1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0]
        # populate the width values
        defaultWidthX = _roundInt(
            getAttrWithFallback(info, "postscriptDefaultWidthX"))
        if defaultWidthX:
            private.rawDict["defaultWidthX"] = defaultWidthX
        nominalWidthX = _roundInt(
            getAttrWithFallback(info, "postscriptNominalWidthX"))
        if nominalWidthX:
            private.rawDict["nominalWidthX"] = nominalWidthX
        # populate hint data
        blueFuzz = _roundInt(getAttrWithFallback(info, "postscriptBlueFuzz"))
        blueShift = _roundInt(getAttrWithFallback(info, "postscriptBlueShift"))
        blueScale = getAttrWithFallback(info, "postscriptBlueScale")
        forceBold = getAttrWithFallback(info, "postscriptForceBold")
        blueValues = getAttrWithFallback(info, "postscriptBlueValues")
        if isinstance(blueValues, list):
            blueValues = [_roundInt(i) for i in blueValues]
        otherBlues = getAttrWithFallback(info, "postscriptOtherBlues")
        if isinstance(otherBlues, list):
            otherBlues = [_roundInt(i) for i in otherBlues]
        familyBlues = getAttrWithFallback(info, "postscriptFamilyBlues")
        if isinstance(familyBlues, list):
            familyBlues = [_roundInt(i) for i in familyBlues]
        familyOtherBlues = getAttrWithFallback(info,
                                               "postscriptFamilyOtherBlues")
        if isinstance(familyOtherBlues, list):
            familyOtherBlues = [_roundInt(i) for i in familyOtherBlues]
        stemSnapH = getAttrWithFallback(info, "postscriptStemSnapH")
        if isinstance(stemSnapH, list):
            stemSnapH = [_roundInt(i) for i in stemSnapH]
        stemSnapV = getAttrWithFallback(info, "postscriptStemSnapV")
        if isinstance(stemSnapV, list):
            stemSnapV = [_roundInt(i) for i in stemSnapV]
        # only write the blues data if some blues are defined.
        if (blueValues or otherBlues):
            private.rawDict["BlueFuzz"] = blueFuzz
            private.rawDict["BlueShift"] = blueShift
            private.rawDict["BlueScale"] = blueScale
            private.rawDict["ForceBold"] = forceBold
            private.rawDict["BlueValues"] = blueValues
            private.rawDict["OtherBlues"] = otherBlues
            private.rawDict["FamilyBlues"] = familyBlues
            private.rawDict["FamilyOtherBlues"] = familyOtherBlues
        # only write the stems if both are defined.
        if (stemSnapH and stemSnapV):
            private.rawDict["StemSnapH"] = stemSnapH
            private.rawDict["StdHW"] = stemSnapH[0]
            private.rawDict["StemSnapV"] = stemSnapV
            private.rawDict["StdVW"] = stemSnapV[0]
        # populate glyphs
        for glyphName in self.glyphOrder:
            glyph = self.allGlyphs[glyphName]
            unicodes = glyph.unicodes
            charString = self.getCharStringForGlyph(glyph, private,
                                                    globalSubrs)
            # add to the font
            if glyphName in charStrings:
                # XXX a glyph already has this name. should we choke?
                glyphID = charStrings.charStrings[glyphName]
                charStringsIndex.items[glyphID] = charString
            else:
                charStringsIndex.append(charString)
                glyphID = len(topDict.charset)
                charStrings.charStrings[glyphName] = glyphID
                topDict.charset.append(glyphName)
        topDict.FontBBox = self.fontBoundingBox
        # write the glyph order
        self.otf.setGlyphOrder(self.glyphOrder)
Exemplo n.º 42
0
    def setupTable_CFF(self):
        """Make the CFF table."""

        self.otf["CFF "] = cff = newTable("CFF ")
        cff = cff.cff
        # set up the basics
        cff.major = 1
        cff.minor = 0
        cff.hdrSize = 4
        cff.offSize = 4
        cff.fontNames = []
        strings = IndexedStrings()
        cff.strings = strings
        private = PrivateDict(strings=strings)
        private.rawDict.update(private.defaults)
        globalSubrs = GlobalSubrsIndex(private=private)
        topDict = TopDict(GlobalSubrs=globalSubrs, strings=strings)
        topDict.Private = private
        charStrings = topDict.CharStrings = CharStrings(file=None, charset=None,
            globalSubrs=globalSubrs, private=private, fdSelect=None, fdArray=None)
        charStrings.charStringsAreIndexed = True
        topDict.charset = []
        charStringsIndex = charStrings.charStringsIndex = SubrsIndex(private=private, globalSubrs=globalSubrs)
        cff.topDictIndex = topDictIndex = TopDictIndex()
        topDictIndex.append(topDict)
        topDictIndex.strings = strings
        cff.GlobalSubrs = globalSubrs
        # populate naming data
        info = self.ufo.info
        psName = getAttrWithFallback(info, "postscriptFontName")
        cff.fontNames.append(psName)
        topDict = cff.topDictIndex[0]
        topDict.version = "%d.%d" % (getAttrWithFallback(info, "versionMajor"), getAttrWithFallback(info, "versionMinor"))
        trademark = getAttrWithFallback(info, "trademark")
        if trademark:
            trademark = normalizeStringForPostscript(trademark.replace("\u00A9", "Copyright"))
        if trademark != self.ufo.info.trademark:
            self.log.append("[Warning] The trademark was normalized for storage in the CFF table and consequently some characters were dropped: '%s'" % trademark)
        if trademark is None:
            trademark = ""
        topDict.Notice = trademark
        copyright = getAttrWithFallback(info, "copyright")
        if copyright:
            copyright = normalizeStringForPostscript(copyright.replace("\u00A9", "Copyright"))
        if copyright != self.ufo.info.copyright:
            self.log.append("[Warning] The copyright was normalized for storage in the CFF table and consequently some characters were dropped: '%s'" % copyright)
        if copyright is None:
            copyright = ""
        topDict.Copyright = copyright
        topDict.FullName = getAttrWithFallback(info, "postscriptFullName")
        topDict.FamilyName = getAttrWithFallback(info, "openTypeNamePreferredFamilyName")
        topDict.Weight = getAttrWithFallback(info, "postscriptWeightName")
        topDict.FontName = getAttrWithFallback(info, "postscriptFontName")
        # populate various numbers
        topDict.isFixedPitch = getAttrWithFallback(info, "postscriptIsFixedPitch")
        topDict.ItalicAngle = getAttrWithFallback(info, "italicAngle")
        underlinePosition = getAttrWithFallback(info, "postscriptUnderlinePosition")
        if underlinePosition is None:
            underlinePosition = 0
        topDict.UnderlinePosition = _roundInt(underlinePosition)
        underlineThickness = getAttrWithFallback(info, "postscriptUnderlineThickness")
        if underlineThickness is None:
            underlineThickness = 0
        topDict.UnderlineThickness = _roundInt(underlineThickness)
        # populate font matrix
        unitsPerEm = _roundInt(getAttrWithFallback(info, "unitsPerEm"))
        topDict.FontMatrix = [1.0 / unitsPerEm, 0, 0, 1.0 / unitsPerEm, 0, 0]
        # populate the width values
        defaultWidthX = _roundInt(getAttrWithFallback(info, "postscriptDefaultWidthX"))
        if defaultWidthX:
            private.rawDict["defaultWidthX"] = defaultWidthX
        nominalWidthX = _roundInt(getAttrWithFallback(info, "postscriptNominalWidthX"))
        if nominalWidthX:
            private.rawDict["nominalWidthX"] = nominalWidthX
        # populate hint data
        blueFuzz = _roundInt(getAttrWithFallback(info, "postscriptBlueFuzz"))
        blueShift = _roundInt(getAttrWithFallback(info, "postscriptBlueShift"))
        blueScale = getAttrWithFallback(info, "postscriptBlueScale")
        forceBold = getAttrWithFallback(info, "postscriptForceBold")
        blueValues = getAttrWithFallback(info, "postscriptBlueValues")
        if isinstance(blueValues, list):
            blueValues = [_roundInt(i) for i in blueValues]
        otherBlues = getAttrWithFallback(info, "postscriptOtherBlues")
        if isinstance(otherBlues, list):
            otherBlues = [_roundInt(i) for i in otherBlues]
        familyBlues = getAttrWithFallback(info, "postscriptFamilyBlues")
        if isinstance(familyBlues, list):
            familyBlues = [_roundInt(i) for i in familyBlues]
        familyOtherBlues = getAttrWithFallback(info, "postscriptFamilyOtherBlues")
        if isinstance(familyOtherBlues, list):
            familyOtherBlues = [_roundInt(i) for i in familyOtherBlues]
        stemSnapH = getAttrWithFallback(info, "postscriptStemSnapH")
        if isinstance(stemSnapH, list):
            stemSnapH = [_roundInt(i) for i in stemSnapH]
        stemSnapV = getAttrWithFallback(info, "postscriptStemSnapV")
        if isinstance(stemSnapV, list):
            stemSnapV = [_roundInt(i) for i in stemSnapV]
        # only write the blues data if some blues are defined.
        if (blueValues or otherBlues):
            private.rawDict["BlueFuzz"] = blueFuzz
            private.rawDict["BlueShift"] = blueShift
            private.rawDict["BlueScale"] = blueScale
            private.rawDict["ForceBold"] = forceBold
            private.rawDict["BlueValues"] = blueValues
            private.rawDict["OtherBlues"] = otherBlues
            private.rawDict["FamilyBlues"] = familyBlues
            private.rawDict["FamilyOtherBlues"] = familyOtherBlues
        # only write the stems if both are defined.
        if (stemSnapH and stemSnapV):
            private.rawDict["StemSnapH"] = stemSnapH
            private.rawDict["StdHW"] = stemSnapH[0]
            private.rawDict["StemSnapV"] = stemSnapV
            private.rawDict["StdVW"] = stemSnapV[0]
        # populate glyphs
        for glyphName in self.glyphOrder:
            glyph = self.allGlyphs[glyphName]
            unicodes = glyph.unicodes
            charString = self.getCharStringForGlyph(glyph, private, globalSubrs)
            # add to the font
            if glyphName in charStrings:
                # XXX a glyph already has this name. should we choke?
                glyphID = charStrings.charStrings[glyphName]
                charStringsIndex.items[glyphID] = charString
            else:
                charStringsIndex.append(charString)
                glyphID = len(topDict.charset)
                charStrings.charStrings[glyphName] = glyphID
                topDict.charset.append(glyphName)
        topDict.FontBBox = self.fontBoundingBox
        # write the glyph order
        self.otf.setGlyphOrder(self.glyphOrder)
Exemplo n.º 43
0
    def setupTable_OS2(self):
        """
        Make the OS/2 table.

        **This should not be called externally.** Subclasses
        may override or supplement this method to handle the
        table creation in a different way if desired.
        """
        self.otf["OS/2"] = os2 = newTable("OS/2")
        font = self.ufo
        os2.version = 0x0004
        # average glyph width
        widths = [
            glyph.width for glyph in self.allGlyphs.values() if glyph.width > 0
        ]
        os2.xAvgCharWidth = _roundInt(sum(widths) / len(widths))
        # weight and width classes
        os2.usWeightClass = getAttrWithFallback(font.info,
                                                "openTypeOS2WeightClass")
        os2.usWidthClass = getAttrWithFallback(font.info,
                                               "openTypeOS2WidthClass")
        # embedding
        os2.fsType = intListToNum(
            getAttrWithFallback(font.info, "openTypeOS2Type"), 0, 16)

        # subscript, superscript, strikeout values, taken from AFDKO:
        # FDK/Tools/Programs/makeotf/makeotf_lib/source/hotconv/hot.c
        unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")
        italicAngle = getAttrWithFallback(font.info, "italicAngle")
        xHeight = getAttrWithFallback(font.info, "xHeight")

        def adjustOffset(offset, angle):
            """Adjust Y offset based on italic angle, to get X offset."""
            return offset * math.tan(math.radians(-angle)) if angle else 0

        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXSize")
        if v is None:
            v = unitsPerEm * 0.65
        os2.ySubscriptXSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYSize")
        if v is None:
            v = unitsPerEm * 0.6
        os2.ySubscriptYSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYOffset")
        if v is None:
            v = unitsPerEm * 0.075
        os2.ySubscriptYOffset = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXOffset")
        if v is None:
            v = adjustOffset(-os2.ySubscriptYOffset, italicAngle)
        os2.ySubscriptXOffset = _roundInt(v)

        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXSize")
        if v is None:
            v = os2.ySubscriptXSize
        os2.ySuperscriptXSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYSize")
        if v is None:
            v = os2.ySubscriptYSize
        os2.ySuperscriptYSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYOffset")
        if v is None:
            v = unitsPerEm * 0.35
        os2.ySuperscriptYOffset = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXOffset")
        if v is None:
            v = adjustOffset(os2.ySuperscriptYOffset, italicAngle)
        os2.ySuperscriptXOffset = _roundInt(v)

        v = getAttrWithFallback(font.info, "openTypeOS2StrikeoutSize")
        if v is None:
            v = getAttrWithFallback(font.info, "postscriptUnderlineThickness")
        os2.yStrikeoutSize = _roundInt(v)
        v = getAttrWithFallback(font.info, "openTypeOS2StrikeoutPosition")
        if v is None:
            v = xHeight * 0.6 if xHeight else unitsPerEm * 0.22
        os2.yStrikeoutPosition = _roundInt(v)

        # family class
        ibmFontClass, ibmFontSubclass = getAttrWithFallback(
            font.info, "openTypeOS2FamilyClass")
        os2.sFamilyClass = (ibmFontClass << 8) + ibmFontSubclass
        # panose
        data = getAttrWithFallback(font.info, "openTypeOS2Panose")
        panose = Panose()
        panose.bFamilyType = data[0]
        panose.bSerifStyle = data[1]
        panose.bWeight = data[2]
        panose.bProportion = data[3]
        panose.bContrast = data[4]
        panose.bStrokeVariation = data[5]
        panose.bArmStyle = data[6]
        panose.bLetterForm = data[7]
        panose.bMidline = data[8]
        panose.bXHeight = data[9]
        os2.panose = panose
        # Unicode ranges
        uniRanges = getAttrWithFallback(font.info, "openTypeOS2UnicodeRanges")
        os2.ulUnicodeRange1 = intListToNum(uniRanges, 0, 32)
        os2.ulUnicodeRange2 = intListToNum(uniRanges, 32, 32)
        os2.ulUnicodeRange3 = intListToNum(uniRanges, 64, 32)
        os2.ulUnicodeRange4 = intListToNum(uniRanges, 96, 32)
        # codepage ranges
        codepageRanges = getAttrWithFallback(font.info,
                                             "openTypeOS2CodePageRanges")
        os2.ulCodePageRange1 = intListToNum(codepageRanges, 0, 32)
        os2.ulCodePageRange2 = intListToNum(codepageRanges, 32, 32)
        # vendor id
        os2.achVendID = tounicode(getAttrWithFallback(font.info,
                                                      "openTypeOS2VendorID"),
                                  encoding="ascii",
                                  errors="ignore")
        # vertical metrics
        os2.sxHeight = _roundInt(getAttrWithFallback(font.info, "xHeight"))
        os2.sCapHeight = _roundInt(getAttrWithFallback(font.info, "capHeight"))
        os2.sTypoAscender = _roundInt(
            getAttrWithFallback(font.info, "openTypeOS2TypoAscender"))
        os2.sTypoDescender = _roundInt(
            getAttrWithFallback(font.info, "openTypeOS2TypoDescender"))
        os2.sTypoLineGap = _roundInt(
            getAttrWithFallback(font.info, "openTypeOS2TypoLineGap"))
        os2.usWinAscent = _roundInt(
            getAttrWithFallback(font.info, "openTypeOS2WinAscent"))
        os2.usWinDescent = _roundInt(
            getAttrWithFallback(font.info, "openTypeOS2WinDescent"))
        # style mapping
        selection = list(getAttrWithFallback(font.info,
                                             "openTypeOS2Selection"))
        styleMapStyleName = getAttrWithFallback(font.info, "styleMapStyleName")
        if styleMapStyleName == "regular":
            selection.append(6)
        elif styleMapStyleName == "bold":
            selection.append(5)
        elif styleMapStyleName == "italic":
            selection.append(0)
        elif styleMapStyleName == "bold italic":
            selection += [0, 5]
        os2.fsSelection = intListToNum(selection, 0, 16)
        # characetr indexes
        unicodes = [
            i for i in self.unicodeToGlyphNameMapping.keys() if i is not None
        ]
        if unicodes:
            minIndex = min(unicodes)
            maxIndex = max(unicodes)
        else:
            # the font may have *no* unicode values (it really happens!) so
            # there needs to be a fallback. use 0xFFFF, as AFDKO does:
            # FDK/Tools/Programs/makeotf/makeotf_lib/source/hotconv/map.c
            minIndex = 0xFFFF
            maxIndex = 0xFFFF
        if maxIndex > 0xFFFF:
            # the spec says that 0xFFFF should be used
            # as the max if the max exceeds 0xFFFF
            maxIndex = 0xFFFF
        os2.fsFirstCharIndex = minIndex
        os2.fsLastCharIndex = maxIndex
        os2.usBreakChar = 32
        os2.usDefaultChar = 0
        # maximum contextual lookup length
        os2.usMaxContex = 0