Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/python
      2 
      3 import harfbuzz, optparse, sys
      4 from fontconfig import fcPattern
      5 
      6 usage = '''usage: %prog [options] codepoints
      7     Generates output of glyphs and positions. Each entry is of the form:
      8         glyphid>cluster@(offsetx,offsety)+(advancex,advancey)
      9 
     10     codepoints is a space separated list of hex values of Unicode codepoints'''
     11 p = optparse.OptionParser(usage=usage)
     12 p.add_option('-s', '--size', default=32, type="int", help="point size")
     13 p.add_option('-l', '--lang', help="language code")
     14 p.add_option('-c', '--script', help="script code")
     15 p.add_option('-F', '--feature', action='append', help="define a feature key=val")
     16 p.add_option('-f', '--font', help='Font to use to render glyphs. My be a font file', default="verdana")
     17 p.add_option('-b', '--bold', help='Choose bold fonts', action='store_true')
     18 p.add_option('-i', '--italic', help='Choose italic fonts', action='store_true')
     19 p.add_option('-d', '--debug', action='store_true', help="Output trace info")
     20 p.add_option('--nogui', action='store_true', help="Don't display a gui")
     21 (opts, args) = p.parse_args()
     22 
     23 if opts.font.lower().endswith(".ttf") :
     24     fpat = ":file="
     25 else :
     26     fpat = ""
     27 fpat += opts.font + ":weight="
     28 fpat += "bold" if opts.bold else "medium"
     29 fpat += ":slant="
     30 fpat += "italic" if opts.italic else "roman"
     31 pat = fcPattern(fpat)
     32 fname = pat.getString("file", 0)
     33 family = pat.getString("family", 0)
     34 print "Processing: " + fname
     35 if opts.font.lower().endswith(".ttf") and opts.font != fname :
     36     print "Failed to find font in fontconfig. Exiting"
     37     sys.exit(1)
     38 
     39 ft = harfbuzz.ft(fname, opts.size)
     40 text = "".join(unichr(int(c, 16)) for c in args)
     41 bytes = text.encode('utf_8')
     42 buffer = harfbuzz.buffer(bytes, len(text))
     43 if (opts.lang or opts.script) : buffer.set_scriptlang(opts.script if opts.script else "", opts.lang if opts.lang else "")
     44 features = {}
     45 if opts.feature :
     46     for f in opts.feature :
     47         k, v = f.split("=")
     48         features[k] = v
     49 ft.shape(buffer, features = features)
     50 res = buffer.get_info(64)       # scale for 26.6
     51 print res
     52 
     53 if not opts.nogui :
     54     try:
     55         import gtk
     56         import gobject
     57         import cairo
     58         from gtk import gdk
     59     except :
     60         raise SystemExit
     61     import pygtk
     62 
     63     if gtk.pygtk_version < (2, 8) :
     64         print "PyGtk 2.8 or later required"
     65         raise SystemExit
     66 
     67     class GlyphsWindow (gtk.Widget) :
     68         def __init__(self, fontname, bold, italic, size, glyphs) :
     69             gtk.Widget.__init__(self)
     70             self.fontname = fontname
     71             self.size = size
     72             self.glyphs = glyphs
     73             self.bold = bold
     74             self.italic = italic
     75 
     76         def do_realize(self) :
     77             self.set_flags(gtk.REALIZED)
     78             self.window = gdk.Window(
     79                     self.get_parent_window(),
     80                     width = self.allocation.width,
     81                     height = self.allocation.height,
     82                     window_type = gdk.WINDOW_CHILD,
     83                     wclass = gdk.INPUT_OUTPUT,
     84                     event_mask = self.get_events() | gdk.EXPOSURE_MASK)
     85             self.window.set_user_data(self)
     86             self.style.attach(self.window)
     87             self.style.set_background(self.window, gtk.STATE_NORMAL)
     88             self.window.move_resize(*self.allocation)
     89             
     90         def do_unrealize(self) :
     91             self.window.destroy()
     92 
     93         def do_expose_event(self, event) :
     94             cr = self.window.cairo_create()
     95             cr.set_matrix(cairo.Matrix(1, 0, 0, 1, 0, 1.5 * self.size))
     96             cr.set_font_face(cairo.ToyFontFace(self.fontname, cairo.FONT_SLANT_ITALIC if self.italic else cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD if self.bold else cairo.FONT_WEIGHT_NORMAL))
     97             cr.set_font_size(self.size)
     98             cr.show_glyphs(self.glyphs)      # [(gid, originx, originy)]
     99 
    100     glyphs = []
    101     org = [0, 0]
    102     for g in res :
    103         glyphs.append((g.gid, org[0] + g.offset[0], org[1] - g.offset[1]))
    104         org[0] += g.advance[0]
    105         org[1] -= g.advance[1]
    106 
    107     gobject.type_register(GlyphsWindow)
    108     win = gtk.Window()
    109     win.resize(org[0] + 10, 2 * opts.size + 40)
    110     win.connect('delete-event', gtk.main_quit)
    111     frame = gtk.Frame("glyphs")
    112     win.add(frame)
    113     w = GlyphsWindow(family, opts.bold, opts.italic, opts.size, glyphs)
    114     frame.add(w)
    115     win.show_all()
    116     gtk.main()
    117