Beispiel #1
0
    def fromValidatedFontWorkerSource(cls, fws, **kwArgs):
        """
        Creates and returns a new GDEF from the specified FontWorker Source
        code with extensive validation via the logging module (the client
        should have done a logging.basicConfig call prior to calling this
        method, unless a logger is passed in via the 'logger' keyword
        argument).

        >>> _test_FW_fws.goto(1) # go back to first line
        >>> logger = utilities.makeDoctestLogger('test_FW')
        >>> fvfws = GDEF.fromValidatedFontWorkerSource
        >>> gdef = fvfws(_test_FW_fws, namer=_test_FW_namer,
        ...   logger=logger, editor=None)
        >>> gdef.pprint()
        Version:
          Major version: 1
          Minor version: 3
        Glyph Classes:
          Base glyph: 5
          Ligature glyph: 7
          Mark glyph: 11
        Attachment Points:
          5: [23]
          7: [29, 31]
          11: [37, 41, 43]
        Ligature Caret Points:
          5:
            CaretValue #1:
              Simple caret value in FUnits: 42
          7:
            CaretValue #1:
              Simple caret value in FUnits: 50
            CaretValue #2:
              Simple caret value in FUnits: 55
          11:
            CaretValue #1:
              Simple caret value in FUnits: 12
            CaretValue #2:
              Simple caret value in FUnits: 17
            CaretValue #3:
              Simple caret value in FUnits: 37
        Mark Classes:
          Mark class 8: 5
          Mark class 10: 7
          Mark class 12: 11
        Mark Sets:
          Mark Glyph Set 0: 5, 7
          Mark Glyph Set 1: 5
          Mark Glyph Set 2: 11
        >>> gdef2 = fvfws(_test_FW_fws2, namer=_test_FW_namer,
        ...   logger=logger, editor=None)
        test_FW.GDEF.classDef - WARNING - line 8 -- glyph 'w' not found
        test_FW.GDEF.attachlist - WARNING - line 13 -- missing attachment points
        test_FW.GDEF.attachlist - WARNING - line 16 -- glyph 'x' not found
        test_FW.GDEF.ligcaret - ERROR - line 21 -- mismatch between caret count (2);and number of carets actually listed (3); discarding.
        test_FW.GDEF.ligcaret - ERROR - line 23 -- mismatch between caret count (3);and number of carets actually listed (2); discarding.
        test_FW.GDEF.ligcaret - WARNING - line 24 -- glyph 'y' not found
        test_FW.GDEF.classDef - WARNING - line 31 -- incorrect number of tokens, expected 2, found 1
        test_FW.GDEF.classDef - WARNING - line 32 -- glyph 'z' not found
        test_FW.GDEF.markset - WARNING - line 40 -- glyph 'asdfjkl' not found
        test_FW.GDEF.markset - WARNING - MarkFilterSet 1 will be renumbered to 0
        test_FW.GDEF.markset - WARNING - MarkFilterSet 99 will be renumbered to 1
        >>> gdef2.pprint()
        Version:
          Major version: 1
          Minor version: 3
        Glyph Classes:
          Base glyph: 5
          Ligature glyph: 7
          Mark glyph: 11
        Attachment Points:
          5: [23]
          11: [37, 41, 43]
        Ligature Caret Points:
          5:
            CaretValue #1:
              Simple caret value in FUnits: 42
        Mark Classes:
          Mark class 1: 5
          Mark class 2: 7
        Mark Sets:
          Mark Glyph Set 0: 5, 11
          Mark Glyph Set 1: 5, 7
        """

        editor = kwArgs['editor']
        namer = kwArgs['namer']

        logger = kwArgs.pop('logger', None)

        if logger is None:
            logger = logging.getLogger().getChild('GDEF')
        else:
            logger = logger.getChild('GDEF')

        # create empty versions of these tables for now,
        # replace them with full versions later if the data is available
        glyphClasses = glyphclass.GlyphClassTable()
        attachments = attachlist.AttachListTable()
        ligCarets = ligcaret.LigCaretTable()
        markClasses = markclass.MarkClassTable()
        markSets = markset.MarkSetTable()

        firstLine = 'FontDame GDEF table'
        line = next(fws)
        if line != firstLine:
            logger.error((
              'V0958',
              (firstLine,),
              "Expected '%s' in first line."))
            return None

        for line in fws:
            if len(line) != 0:
                if line.lower() == 'class definition begin':
                    glyphClasses = \
                        glyphclass.GlyphClassTable.fromValidatedFontWorkerSource(
                          fws, namer=namer, logger=logger)
                elif line.lower() == 'attachment list begin':
                    attachments = \
                        attachlist.AttachListTable.fromValidatedFontWorkerSource(
                          fws, namer=namer, logger=logger)
                elif line.lower() == 'carets begin':
                    ligCarets = \
                        ligcaret.LigCaretTable.fromValidatedFontWorkerSource(
                          fws, namer=namer, logger=logger, editor=editor)
                elif line.lower() == 'mark attachment class definition begin':
                    markClasses = \
                        markclass.MarkClassTable.fromValidatedFontWorkerSource(
                          fws, namer=namer, logger=logger)
                elif line.lower() == 'markfilter set definition begin':
                    markSets = \
                        markset.MarkSetTable.fromValidatedFontWorkerSource(
                          fws, namer=namer, logger=logger)
                else:
                    logger.warning((
                      'V0960',
                      (fws.lineNumber, line),
                      'line %d -- unexpected token: \'%s\''))

        return cls(
            attachments=attachments,
            glyphClasses=glyphClasses,
            ligCarets=ligCarets,
            markClasses=markClasses,
            markSets=markSets)
Beispiel #2
0
    def frommtxxtables(cls, editor, **kwArgs):
        """
        Returns a GDEF object initialized via the MTxx (and other) tables in
        the specified editor.
        """

        if editor is None:
            return cls()

        hm = editor.get(b'hmtx')

        if not hm:
            return cls()

        sf = editor.get(b'MTsf', {})
        # when there's a MTxx table for marksets, add that here

        glyphClasses = glyphclass.GlyphClassTable()
        attachments = attachlist.AttachListTable()
        ligCarets = ligcaret.LigCaretTable()
        markClasses = markclass.MarkClassTable()
        markSets = markset.MarkSetTable()
        excluded = frozenset([0xFFFF, 0xFFFE])

        for glyphIndex, mtapRecord in editor.get(b'MTap', {}).items():
            # glyph class
            glyphClass = mtapRecord.glyphClass

            if glyphClass:
                glyphClasses[glyphIndex] = glyphClass

            # attachments
            anchor = mtapRecord.anchorData

            t1 = (
              () if anchor is None
              else tuple(anchor.pointGenerator(excludeFFFx=True)))

            conn = mtapRecord.connectionData

            if conn is None:
                t2 = ()

            else:
                it = conn.pointGenerator()

                t2 = tuple(
                  c.pointIndex
                  for c in it
                  if c.pointIndex not in excluded)

            if t1 or t2:
                attachments[glyphIndex] = attachlist.AttachPointTable(t1 + t2)

            # lig carets
            if glyphClass == 2:  # ligature
                caretValues = mtapRecord.caretValuesFromMetrics(
                  hm[glyphIndex][0])

                if caretValues:
                    ligCarets[glyphIndex] = ligcaret.LigGlyphTable(caretValues)

            # marks
            elif glyphClass == 3 and sf:  # mark
                markClass = sf[glyphIndex].originalClassIndex

                markClasses[glyphIndex] = (
                  0 if markClass == 0xFFFF
                  else markClass + 1)

        return cls(
          attachments=attachments,
          glyphClasses=glyphClasses,
          ligCarets=ligCarets,
          markClasses=markClasses,
          markSets=markSets)