Esempio n. 1
0
 def compile( self, font, steps = 3 ):
     """Compile the glyph to a set of poly-line outlines"""
     self.contours = self.calculateContours( font )
     self.outlines = [
         decomposeOutline(contour,steps)
         for contour in self.contours
     ]
     self.width = glyphquery.width( font, self.glyphName )
     self.height = glyphquery.lineHeight( font )
Esempio n. 2
0
    def _generalMetadata( self ):
        """Load general meta-data for this font (called via withFont)

        Guess the appropriate encoding, query line height,
        and character height.
        """
        try:
            self.encoding = describe.guessEncoding( self.font, self.encoding )
            self.lineHeight = glyphquery.lineHeight( self.font )
            self.charHeight = glyphquery.charHeight( self.font )
        except Exception:
            log.error( """Unable to load TrueType font from %r""", self.filename)
            raise
Esempio n. 3
0
def text(pos=(0,0), text="", font=None, height=1.0, align='left', spacing=0.03, rotate=0.0,
         scale=1.0, xscale=1.0, yscale=1.0, thickness=None, vertical_spacing=None,
         info=False):
    # If info == True, the caller wants the additional info such as upper-left, etc.
    # In this case we return an instance of the class text_info, with the Polygon as
    # an attribute, text_info.Polygon. The main client of this extra info is the text object.
    if thickness is not None:
        raise AttributeError("Thickness is not allowed in a text shape.")
    if scale != 1.0: xscale = yscale = scale
    lines = text.split('\n')
    while lines[-1] == '\n': # strip off trailing newlines
        lines = lines[:-1]
    if font is None:
        font = "serif"
    font = describe.openFont(findFont(font))
    
    try:
        fonth = glyphquery.charHeight(font)
    except:
        fonth = 1000
    if fonth == 0: fonth = 1000
    
    try:
        desc = glyphquery.charDescent(font) # charDescent may not be present
        fontheight = fonth+desc
        fontscale = 1./fontheight
        descent = fontscale*desc
    except:
        descent = -0.3*height # approximate value
        fontheight = 0.7*fonth
        fontscale = 1.3/fontheight
        
    if vertical_spacing is None:
        vertical_spacing = height*fontscale*glyphquery.lineHeight(font)

    excludef_list = [("ITCEdscr")]
    excludec_list = [("FRSCRIPT", "A"), ("jokerman", "O"),
                    ("vivaldii", "O"), ("vivaldii", "Q"),
                    ("vivaldii", "R")]
    
    ptext = [] 
    widths = []
    width = 0.0
    starts = []
    start = 0.0

    for line in range(len(lines)):
        ptext.append(Polygon())
        bb = 0
        
        for newchar in lines[line]:
            if newchar == " ":
                try:
                    if a:
                        bx = a.boundingBox()
                        bba = bx[1]-bx[0]
                        bba = min(bba, 700)
                        bb += bba
                except:
                    pass
                continue
            n = glyphquery.glyphName(font, newchar)

            if n == ".notdef":
                print("The character '"+newchar+"' is not supported in the font "+font)
                continue
            
            g = glyph.Glyph(n)
            c = g.calculateContours(font)
            contours = []

            for contour in c:
                contours.append(glyph.decomposeOutline(contour))
                if len(contours[-1]) == 0: contours.pop()

            for contour in contours:
                pp = 0
                for i in range(len(contour)-1):
                    if (contour[i][0] == contour[i+1][0]) and (contour[i][1] == contour[i+1][1]):
                        contour.pop(i)
                        pp += 1
                        if i+pp >= len(contour)-1: break

            def lenctr(contour):
                totlen = 0
                for j in range(len(contour)-1):
                    totlen += (vis.vector(contour[j])-vis.vector(contour[j+1])).mag
                return totlen

            lc = len(contours)
            
            if lc >= 4:
                mli = 0
                maxl = 0
                lengths = []
                for i in range(len(contours)):
                    totlen = lenctr(contours[i])
                    lengths.append((totlen,i))
                    if totlen > maxl:
                        mli = i
                        maxl = totlen

                lengths.sort()
                lengths.reverse()
                ocontours = []
                for ll in lengths:
                    ocontours.append(contours[ll[1]])
                contours = ocontours

                indxf = -1
                indxc = -1
                if (mli > 0 and newchar != "%"):
                    try: indxf = excludef_list.index(self.font)
                    except: pass
                    if indxf == -1:
                        try: indxc = excludec_list.index((self.font, newchar))
                        except: pass
                    if (indxf == -1 and indxc == -1):
                        maxc = contours.pop(mli)
                        contours.insert(0, maxc)
                               
            a = Polygon(contours[0])
            for i in range(1,len(contours)):
                b = Polygon(contours[i])
                if a.covers(b): a = a - b
                elif b.covers(a): a = b - a
                else: a = a + b

            a.shift(bb - a.boundingBox()[0] ,0)
           
            ptext[line] += a
            
            bx = ptext[line].boundingBox()
            bb = bx[1] - bx[0] + spacing*fontheight

        newwidth = fontscale*height*(ptext[line].boundingBox()[1]-ptext[line].boundingBox()[0])
        widths.append(newwidth)
        if newwidth > width: width = newwidth
        
        ptext[line].scale(xscale*fontscale*height, yscale*fontscale*height, 0, 0)
        
    for line in range(len(lines)):
        if align == 'left':
            ptext[line].shift(-width/2,-line*vertical_spacing)
        elif align == 'right':
            ptext[line].shift(width/2-widths[line],-line*vertical_spacing)
        else:
            ptext[line].shift(-widths[line]/2,-line*vertical_spacing)
        ptext[line].shift(pos[0], pos[1])
        if rotate != 0.0: ptext[line].rotate(rotate)
        if line == 0:
            shape = ptext[0]
            upper_left = vis.vector(ptext[line].boundingBox()[0],ptext[line].boundingBox()[3],0)
            upper_right = vis.vector(ptext[line].boundingBox()[1],ptext[line].boundingBox()[3],0)
            lower_left = vis.vector(ptext[line].boundingBox()[0],ptext[line].boundingBox()[2],0)
            lower_right = vis.vector(ptext[line].boundingBox()[1],ptext[line].boundingBox()[2],0)
        else:
            shape += ptext[line]
            xleft = ptext[line].boundingBox()[0]
            xright = ptext[line].boundingBox()[1]
            y = ptext[line].boundingBox()[2]
            if xleft < upper_left.x:
                upper_left.x = xleft
            if xright > upper_right.x:
                upper_right.x = xright
            lower_left = vis.vector(upper_left.x,ptext[line].boundingBox()[2],0)
            lower_right = vis.vector(upper_right.x,ptext[line].boundingBox()[2],0)

    dy = vis.vector(0,(upper_left.y-lower_left.y)/2-height,0)
    shape.shift(0,dy.y)
    if not info: return shape

    info = text_info()
    info.Polygon = shape
    info.upper_left = upper_left+dy
    info.upper_right = upper_right+dy
    info.lower_left = lower_left+dy
    info.lower_right = lower_right+dy
    if align == 'left':
        x = 0
    elif align == 'right':
        x = -width
    elif align == 'center':
        x = -0.5*width
    info.start = vis.vector(x,0,0)+dy
    info.starts = []
    for line in range(len(lines)):
        if align == 'left':
            x = 0
        elif align == 'right':
            x = -widths[line]
        elif align == 'center':
            x = -0.5*widths[line]
        info.starts.append(vis.vector(x,line*vertical_spacing,0)+dy)
    
    info.width = width
    info.widths = widths
    info.descent = descent
    info.vertical_spacing = vertical_spacing
    info.align = align
    info.height = height
    
    return info