#!/usr/bin/python from cairo import * from fcntl import ioctl from array import array import struct import errno import sys GIO_UNIMAP = 0x4B66 VT_GETHIFONTMASK = 0x560D if len(sys.argv) != 3: print "Usage: %s " % sys.argv[0] exit() ttyno = int(sys.argv[1]) png = sys.argv[2] tty = open('/dev/tty%d' % ttyno, 'rb') himask = array("H", (0,)) ioctl(tty, VT_GETHIFONTMASK, himask) hichar, = struct.unpack_from("@H", himask) sz = 512 while True: try: unipairs = array("H", [0]*(2*sz)) unimapdesc = array("B", struct.pack("@HP", sz, unipairs.buffer_info()[0])) ioctl(tty.fileno(), GIO_UNIMAP, unimapdesc) break except IOError as e: if e.errno != errno.ENOMEM: raise sz *= 2 tty.close() ncodes, = struct.unpack_from("@H", unimapdesc) utable = struct.unpack_from("@%dH" % (2*ncodes), unipairs) charmap = {} for u, b in zip(utable[::2], utable[1::2]): if charmap.get(b) is None: charmap[b] = unichr(u) vcs = open('/dev/vcsa%d' % ttyno, 'rb') head = vcs.read(4) rows = ord(head[0]) cols = ord(head[1]) caretX = ord(head[2]) caretY = ord(head[3]) surf = ImageSurface(FORMAT_RGB24, cols * 8, rows * 16) cr = Context(surf) cr.set_source_rgb(1,1,1) cr.set_font_face(ToyFontFace("Mono", FONT_SLANT_NORMAL, FONT_WEIGHT_NORMAL)); m = Matrix() m.scale(10.0, 12.0) cr.set_font_matrix(m) def CairoColor(b, a): return (b if a & 4 else 0, b if a & 2 else 0, b if a & 1 else 0) for y in range(rows): for x in range(cols): data = vcs.read(2) (sh,) = struct.unpack("=H", data) attr = (sh >> 8) & 0xFF ch = sh & 0xFF if hichar == 0x100: attr >>= 1 ink = attr & 0x0F paper = (attr>>4) & 0x0F b = 1.0 if attr & 0x80 else 0.75 if sh & hichar: ch |= 0x100 cr.set_source_rgb(*CairoColor(b, paper)) cr.rectangle(x*8, y*16, 8, 16) cr.fill() cr.set_source_rgb(*CairoColor(b, ink)) cr.move_to(x*8, 12 + y*16) cr.show_text(charmap.get(ch, u'?')) cr.stroke() vcs.close() surf.write_to_png(png)