コード例 #1
0
    def fromwalker(cls, w, **kwArgs):
        """
        Creates and returns a TTSimpleGlyph object from the specified walker.
        
        >>> _testingValues[1] == TTSimpleGlyph.frombytes(_testingValues[1].binaryString())
        True
        
        >>> _testingValues[2] == TTSimpleGlyph.frombytes(_testingValues[2].binaryString())
        True
        """
        
        numContours = w.unpack("H")
        assert numContours != 0xFFFF, "Composite glyph passed to simple glyph walker!"
        b = ttbounds.TTBounds.fromwalker(w, **kwArgs)

        if numContours == 0 and b == ttbounds.TTBounds():  # special case
            b = None

        if numContours:
            endPoints = w.group("H", numContours)

        h = w.chunk(w.unpack("H"))
        
        if numContours:
            kwArgs.pop('endPoints', None)
            c = ttcontours.TTContours.fromwalker(w, endPoints=endPoints, **kwArgs)
        else:
            c = ttcontours.TTContours()
        
        return cls(b, c, h)
コード例 #2
0
    def fromscaleroutline(cls, outl, **kwArgs):
        """
        Constructs and returns a TTSimpleglyph using the specified outline
        data. The outline data must conform to the ScalerInterface outline
        format (see ScalerInterface.getOutline() for details).
        
        Accepts kwArg 'hints', which will be stored as hintBytes if present.
        """

        ctrs = []
        ctr = None

        ird = lambda x: int(round(x))
        TTP = ttpoint.TTPoint
        n = len(outl) - 1
        
        hintBytes = kwArgs.get('hints') or ''

        for i, pt in enumerate(outl):
            last = (i == n) or (i < n and outl[i+1].kind == 'move')

            if pt.kind == 'move':
                if ctr:
                    ctrs.append(ctr)
                npt = TTP(ird(pt.x), ird(pt.y), onCurve=True)
                ctr = ttcontour.TTContour()
                ctr.append(npt)

            if pt.kind == 'line':
                npt = TTP(ird(pt.x), ird(pt.y), onCurve=True)
                if last and npt.x == ctr[0].x and npt.y == ctr[0].y:
                    pass  # explicit contour close; don't add
                else:
                    ctr.append(npt)

            if pt.kind == 'quad':
                offpt = TTP(
                  ird(pt.offCurvePoint.x),
                  ird(pt.offCurvePoint.y),
                  onCurve=False)

                onpt = TTP(
                  ird(pt.onCurvePoint.x),
                  ird(pt.onCurvePoint.y),
                  onCurve=True)

                ctr.append(offpt)

                if last and onpt.x == ctr[0].x and onpt.y == ctr[0].y:
                    pass  # explicit contour close; don't add.
                else:
                    ctr.append(onpt)

        if ctr:
            ctrs.append(ctr)

        return cls(
          bounds=ttbounds.TTBounds.fromcontours(ctrs),
          contours=ttcontours.TTContours(ctrs),
          hintBytes=hintBytes)
コード例 #3
0
    def _makeTestContours():
        from fontio3.glyf import ttcontour, ttcontours, ttpoint

        P = ttpoint.TTPoint
        C = ttcontour.TTContour

        return ttcontours.TTContours([
            C([P(100, 100),
               P(100, 1100),
               P(1900, 1100),
               P(1900, 100)]),  # 0
            C([P(200, 200),
               P(1400, 200),
               P(1400, 1000),
               P(200, 1000)]),  # 1
            C([P(1500, 200),
               P(1800, 200),
               P(1800, 1000),
               P(1500, 1000)]),  # 2
            C([P(300, 300),
               P(300, 900),
               P(1000, 900),
               P(1000, 300)]),  # 3
            C([P(1100, 300),
               P(1100, 900),
               P(1300, 900),
               P(1300, 300)]),  # 4
            C([P(400, 400), P(500, 400),
               P(500, 500), P(400, 500)]),  # 5
            C([P(1550, 700),
               P(1550, 900),
               P(1650, 900),
               P(1650, 700)]),  # 6
            C([P(1650, 300),
               P(1650, 500),
               P(1750, 500),
               P(1750, 300)]),  # 7
            C([P(2000, 500),
               P(2000, 600),
               P(2100, 600),
               P(2100, 500)])
        ])  # 8
コード例 #4
0
 def fromcompositeglyph(cls, compositeGlyph, **kwArgs):
     """
     Constructs and returns a TTSimpleGlyph using the specified composite
     glyph as a "template." The kwArgs must contain an editor.
     """
     
     try:
         v = list(compositeGlyph.pieceIterator(**kwArgs))
     except:
         v = None
     
     if v is None:
         return cls()
     
     vx = [c.transformed(m) for obj, m in v for c in obj]
     
     return cls(
       bounds = ttbounds.TTBounds.fromcontours(vx),
       contours = ttcontours.TTContours(vx),
       hintBytes = compositeGlyph.hintBytes)
コード例 #5
0
    def fromvalidatedwalker(cls, w, **kwArgs):
        """
        Like fromwalker(), this method returns a new TTSimpleGlyph. However, it
        also does 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).
        
        >>> logger = utilities.makeDoctestLogger('test')
        >>> s = _testingValues[2].binaryString()
        >>> TTSimpleGlyph.fromvalidatedbytes(s, logger=logger).pprint()
        test.ttsimpleglyph - DEBUG - Walker has 44 remaining bytes.
        test.ttsimpleglyph.ttbounds - DEBUG - Walker has 42 remaining bytes.
        test.ttsimpleglyph.ttcontours - DEBUG - Walker has 26 remaining bytes.
        Bounds:
          Minimum X: 620
          Minimum Y: 610
          Maximum X: 980
          Maximum Y: 1090
        Contours:
          Contour 0:
            Point 0: (620, 610), on-curve
            Point 1: (620, 1090), on-curve
            Point 2: (980, 1090), on-curve
            Point 3: (980, 610), on-curve
          Contour 1:
            Point 0: (750, 750), on-curve
            Point 1: (850, 700), off-curve
            Point 2: (950, 750), on-curve
            Point 3: (850, 1000), on-curve
        Hints:
          0000 (0x000000): SVTCA[y]
          0001 (0x000001): SVTCA[x]
        
        >>> fvb = TTSimpleGlyph.fromvalidatedbytes
        >>> obj = fvb(s[:-1], logger=logger)
        test.ttsimpleglyph - DEBUG - Walker has 43 remaining bytes.
        test.ttsimpleglyph.ttbounds - DEBUG - Walker has 41 remaining bytes.
        test.ttsimpleglyph.ttcontours - DEBUG - Walker has 25 remaining bytes.
        test.ttsimpleglyph.ttcontours - ERROR - Insufficient bytes for y-delta.

        >>> _testingValues[1] == fvb(_testingValues[1].binaryString(), logger=logger)
        test.ttsimpleglyph - DEBUG - Walker has 14 remaining bytes.
        test.ttsimpleglyph.ttbounds - DEBUG - Walker has 12 remaining bytes.
        True
        """
        
        logger = kwArgs.pop('logger', None)
        
        if logger is None:
            logger = logging.getLogger().getChild('ttsimpleglyph')
        else:
            logger = logger.getChild('ttsimpleglyph')
        
        logger.debug((
          'V0001',
          (w.length(),),
          "Walker has %d remaining bytes."))
        
        if w.length() < 2:
            logger.error(('V0004', (), "Insufficient bytes."))
            return None
        
        numContours = w.unpack("H")
        
        if numContours == 0xFFFF:
            logger.error((
              'V0002',
              (),
              "Composite glyph passed to TTSimpleGlyph."))
            
            return None
        
        b = ttbounds.TTBounds.fromvalidatedwalker(w, logger=logger, **kwArgs)
        
        if b is None:
            return None
        
        if numContours == 0 and b == ttbounds.TTBounds():  # special-case
            b = None

        if numContours:
            if w.length() < 2 * numContours:
                logger.error(('V0187', (), "Insufficient bytes for endPoints."))
                return None
        
            endPoints = w.group("H", numContours)
        
            if sorted(set(endPoints)) != list(endPoints):
                logger.error((
                  'V0987',
                  (),
                  "Endpoints have duplicates or are out-of-order."))
            
                return None
        
        if w.length() < 2:
            logger.error(('V0188', (), "Insufficient bytes for hint length."))
            return None
        
        hintLength = w.unpack("H")
        
        if hintLength:
            if w.length() < hintLength:
                logger.error(('V0189', (), "Insufficient bytes for hints."))
                return None
            
            h = w.chunk(hintLength)
        
        else:
            h = b''
        
        if numContours:
            kwArgs.pop('endPoints', None)
            
            c = ttcontours.TTContours.fromvalidatedwalker(
              w,
              endPoints = endPoints,
              logger = logger,
              **kwArgs)
            
            if c is None:
                c = ttcontours.TTContours()
        
        else:
            c = ttcontours.TTContours()
        
        if w.length():
            pad = w.rest()
            
            if len(pad) > 3:
                logger.error(('V1007', (), "More than 3 pad bytes following glyph data."))
            
            if any(pad):
                logger.error(('V1008', (), "Non-zero pad bytes following glyph data."))

        return cls(b, c, h)