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)
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 )
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
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